@@ -18,11 +18,13 @@ import {
18
18
toRefs ,
19
19
computed ,
20
20
ToRefs ,
21
- unref ,
22
- ref ,
23
21
mergeProps ,
24
- Fragment ,
22
+ onMounted ,
23
+ watchEffect ,
24
+ UnwrapRef ,
25
25
watch ,
26
+ ref ,
27
+ cloneVNode ,
26
28
} from 'vue'
27
29
import {
28
30
chakra ,
@@ -33,18 +35,26 @@ import {
33
35
} from '@chakra-ui/vue-system'
34
36
import { createContext , TemplateRef } from '@chakra-ui/vue-utils'
35
37
import { CPortal } from '@chakra-ui/c-portal'
36
- import { FocusLockOptions , useFocusLock } from '@chakra-ui/c-focus-lock'
38
+ import {
39
+ CFocusLock ,
40
+ FocusLockProps ,
41
+ useFocusLock ,
42
+ } from '@chakra-ui/c-focus-lock'
37
43
import { CScrollLock } from '@chakra-ui/c-scroll-lock'
38
44
import { CMotion } from '@chakra-ui/c-motion'
39
45
40
46
import { useModal , UseModalOptions , UseModalReturn } from './use-modal'
41
47
import { focus , FocusableElement } from '@chakra-ui/utils'
48
+ import { FocusTarget } from 'focus-trap'
42
49
43
50
type ScrollBehavior = 'inside' | 'outside'
44
51
type MotionPreset = 'slideInBottom' | 'slideInRight' | 'scale' | 'none'
45
52
46
53
export interface ModalOptions
47
- extends Omit < FocusLockOptions , 'enabled' | 'closeModal' | 'handleEscape' > {
54
+ extends Omit <
55
+ FocusLockProps ,
56
+ 'enabled' | 'closeModal' | 'isActive' | 'handleEscape'
57
+ > {
48
58
/**
49
59
* If `true`, the modal will be centered on screen.
50
60
* @default false
@@ -60,7 +70,7 @@ export interface ModalOptions
60
70
scrollBehavior ?: ScrollBehavior
61
71
}
62
72
63
- export interface CModalProps extends UseModalOptions , ModalOptions {
73
+ export interface CModalProps extends UnwrapRef < UseModalOptions > , ModalOptions {
64
74
/**
65
75
* If `true`, the modal will display
66
76
*
@@ -85,15 +95,7 @@ export interface CModalProps extends UseModalOptions, ModalOptions {
85
95
*
86
96
* @default true
87
97
*/
88
- autoFocus ?: boolean
89
- /**
90
- * The `ref` of element to receive focus when the modal opens.
91
- */
92
- initialFocusRef ?: ( ) => FocusableElement
93
- /**
94
- * The `ref` of element to receive focus when the modal closes.
95
- */
96
- finalFocusRef ?: ( ) => FocusableElement
98
+ autoFocus : boolean
97
99
/**
98
100
* If `true`, the modal will return focus to the element that triggered it when it closes.
99
101
* @default true
@@ -123,7 +125,18 @@ export interface CModalProps extends UseModalOptions, ModalOptions {
123
125
motionPreset ?: MotionPreset
124
126
}
125
127
126
- type IUseModalOptions = ToRefs < Omit < CModalProps , 'closeModal' | 'handleEscape' > >
128
+ type IUseModalOptions = ToRefs <
129
+ Omit <
130
+ CModalProps ,
131
+ | 'closeModal'
132
+ | 'handleEscape'
133
+ | 'preserveScrollBarGap'
134
+ | 'allowPinchZoom'
135
+ | 'motionPreset'
136
+ | 'trapFocus'
137
+ | 'autoFocus'
138
+ >
139
+ >
127
140
128
141
interface CModalContext extends IUseModalOptions , UseModalReturn {
129
142
// /** The transition to be used for the CModal */
@@ -204,11 +217,11 @@ export const CModal = defineComponent({
204
217
}
205
218
206
219
const styles = useMultiStyleConfig ( 'Modal' , mergeProps ( props , attrs ) )
207
- const modalOptions = reactive ( {
208
- ...props ,
220
+ const modalOptions = {
221
+ ...toRefs ( reactive ( props ) ) ,
209
222
closeModal,
210
223
handleEscape,
211
- } )
224
+ }
212
225
const modal = useModal ( modalOptions )
213
226
214
227
ModalContextProvider ( {
@@ -235,6 +248,8 @@ export const CModalFocusScope = defineComponent({
235
248
initialFocusRef,
236
249
returnFocusOnClose,
237
250
finalFocusRef,
251
+ dialogRef,
252
+ dialogEl,
238
253
blockScrollOnMount,
239
254
} = useModalContext ( )
240
255
@@ -244,31 +259,47 @@ export const CModalFocusScope = defineComponent({
244
259
: finalFocusRef ?. value
245
260
)
246
261
247
- const focusLockOptions : FocusLockOptions = reactive ( {
248
- enabled : isOpen . value ,
249
- autoFocus : true ,
250
- initialFocusRef : initialFocusRef ?. value ,
251
- returnFocus : returnFocusOnClose ?. value ,
252
- clickOutsideDeactivates : false ,
253
- escapeDeactivates : false ,
254
- onDeactivate : ( ) => {
255
- if ( finalFocusEl . value ) {
256
- focus ( finalFocusEl . value )
257
- }
258
- } ,
259
- } )
262
+ // const focusLockOptions = reactive({
263
+ // immediate: true,
264
+ // initialFocus: initialFocusRef?.value as FocusTarget,
265
+ // returnFocus: returnFocusOnClose?.value,
266
+ // clickOutsideDeactivates: false,
267
+ // escapeDeactivates: false,
268
+ // onDeactivate: () => {
269
+ // if (finalFocusEl.value) {
270
+ // focus(finalFocusEl.value as FocusableElement)
271
+ // }
272
+ // },
273
+ // onActivate: () => {
274
+ // console.log('focus lock activated')
275
+ // },
276
+ // })
277
+ // })
260
278
261
- const { lock } = useFocusLock ( focusLockOptions )
279
+ const contentRef = ref ( )
280
+
281
+ watch ( contentRef , ( el ) => console . log ( 'contentRef value updated' , el ) , {
282
+ flush : 'post' ,
283
+ } )
262
284
263
285
return ( ) => {
264
286
return h (
265
- CScrollLock ,
287
+ CFocusLock ,
266
288
{
267
- ref : lock ,
268
- ...attrs ,
269
- enabled : blockScrollOnMount ?. value ,
289
+ attrs,
270
290
} ,
271
- slots
291
+ ( ) => [
292
+ h (
293
+ CScrollLock ,
294
+ {
295
+ enabled : blockScrollOnMount ?. value ,
296
+ } ,
297
+ ( ) =>
298
+ slots . default ?.( {
299
+ contentRef,
300
+ } )
301
+ ) ,
302
+ ]
272
303
)
273
304
}
274
305
} ,
@@ -283,7 +314,13 @@ export const CModalContent = defineComponent({
283
314
inheritAttrs : false ,
284
315
emits : [ 'click' ] ,
285
316
setup ( _ , { attrs, slots } ) {
286
- const { dialogProps, dialogContainerProps, isOpen } = useModalContext ( )
317
+ const {
318
+ dialogProps,
319
+ dialogContainerProps,
320
+ dialogEl,
321
+ dialogRef,
322
+ isOpen,
323
+ } = useModalContext ( )
287
324
const styles = useStyles ( )
288
325
289
326
const dialogContainerStyles = computed < SystemStyleObject > ( ( ) => ( {
@@ -305,8 +342,14 @@ export const CModalContent = defineComponent({
305
342
...styles . value . dialog ,
306
343
} ) )
307
344
345
+ const dialogHack = ref ( )
346
+
347
+ watch ( dialogHack , ( el ) => {
348
+ console . log ( 'fromCModalContent' , el )
349
+ } )
350
+
308
351
return ( ) =>
309
- h ( CModalFocusScope , { } , ( ) => [
352
+ h ( CModalFocusScope , null , ( ) =>
310
353
h (
311
354
chakra ( 'div' , {
312
355
label : 'modal__content-container' ,
@@ -321,22 +364,28 @@ export const CModalContent = defineComponent({
321
364
} ,
322
365
( ) => [
323
366
isOpen . value &&
324
- h (
325
- chakra ( 'div' , {
326
- __css : dialogStyles . value ,
327
- label : 'modal__content' ,
328
- } ) ,
367
+ cloneVNode (
368
+ h (
369
+ chakra ( 'div' , {
370
+ __css : dialogStyles . value ,
371
+ label : 'modal__content' ,
372
+ } ) ,
373
+ {
374
+ ...attrs ,
375
+ ...dialogProps . value ,
376
+ ref : dialogHack ,
377
+ } ,
378
+ slots
379
+ ) ,
329
380
{
330
- ...attrs ,
331
- ...dialogProps . value ,
332
- } ,
333
- slots
381
+ ref : dialogHack ,
382
+ }
334
383
) ,
335
384
]
336
385
) ,
337
386
]
338
- ) ,
339
- ] )
387
+ )
388
+ )
340
389
} ,
341
390
} )
342
391
0 commit comments