@@ -2,43 +2,46 @@ import {
2
2
$ ,
3
3
QRL ,
4
4
QwikMouseEvent ,
5
+ Signal ,
5
6
Slot ,
6
7
component$ ,
7
8
createContextId ,
8
9
useComputed$ ,
10
+ useContext ,
9
11
useContextProvider ,
12
+ useOn ,
10
13
useSignal ,
11
14
useStore ,
12
- useVisibleTask$ ,
13
15
} from '@builder.io/qwik' ;
14
16
15
17
export type DialogState = {
16
18
opened : boolean ;
19
+ dialogRef : Signal < HTMLDialogElement | undefined > ;
17
20
} ;
18
21
19
22
export type DialogContext = {
20
23
state : DialogState ;
24
+
21
25
open : QRL < ( ) => void > ;
22
26
close : QRL < ( ) => void > ;
23
- } ;
24
-
25
- export type RootProps = {
26
- open : boolean ;
27
- type ?: 'modal' | 'bottom-sheet' | 'side-nav' ;
27
+ closeOnDialogClick : QRL <
28
+ (
29
+ event : QwikMouseEvent < HTMLDialogElement , MouseEvent > ,
30
+ element : HTMLDialogElement
31
+ ) => void
32
+ > ;
28
33
} ;
29
34
30
35
export const dialogContext = createContextId < DialogContext > ( 'dialog' ) ;
31
36
32
- export const Root = component$ ( ( props : RootProps ) => {
33
- const dialogRef = useSignal < HTMLDialogElement > ( ) ;
34
- const classes = useComputed$ ( ( ) => [ props . type ?? 'modal' ] ) ;
35
-
37
+ export const Root = component$ ( ( ) => {
36
38
const state = useStore ( {
37
39
opened : false ,
40
+ dialogRef : useSignal < HTMLDialogElement > ( ) ,
38
41
} ) ;
39
42
40
43
const openDialog$ = $ ( ( ) => {
41
- const dialog = dialogRef . value ;
44
+ const dialog = state . dialogRef . value ;
42
45
43
46
if ( ! dialog ) {
44
47
throw new Error (
@@ -51,7 +54,7 @@ export const Root = component$((props: RootProps) => {
51
54
} ) ;
52
55
53
56
const closeDialog$ = $ ( ( ) => {
54
- const dialog = dialogRef . value ;
57
+ const dialog = state . dialogRef . value ;
55
58
56
59
if ( ! dialog ) {
57
60
throw new Error (
@@ -63,7 +66,7 @@ export const Root = component$((props: RootProps) => {
63
66
state . opened = false ;
64
67
} ) ;
65
68
66
- const handleClick $ = $ (
69
+ const closeOnDialogClick $ = $ (
67
70
(
68
71
event : QwikMouseEvent < HTMLDialogElement , MouseEvent > ,
69
72
element : HTMLDialogElement
@@ -76,21 +79,47 @@ export const Root = component$((props: RootProps) => {
76
79
77
80
const context : DialogContext = {
78
81
state,
82
+
79
83
open : openDialog$ ,
80
84
close : closeDialog$ ,
85
+ closeOnDialogClick : closeOnDialogClick$ ,
81
86
} ;
82
87
83
88
useContextProvider ( dialogContext , context ) ;
84
89
85
- useVisibleTask$ ( async ( { track } ) => {
86
- const shallBeOpened = track ( ( ) => props . open ) ;
90
+ return < Slot /> ;
91
+ } ) ;
87
92
88
- shallBeOpened ? await openDialog$ ( ) : await closeDialog$ ( ) ;
89
- } ) ;
93
+ export const Trigger = component$ ( ( ) => {
94
+ const context = useContext ( dialogContext ) ;
95
+
96
+ useOn (
97
+ 'click' ,
98
+ $ ( ( ) => context . open ( ) )
99
+ ) ;
100
+
101
+ return (
102
+ < div role = "button" >
103
+ < Slot />
104
+ </ div >
105
+ ) ;
106
+ } ) ;
107
+
108
+ export type PortalProps = {
109
+ type ?: 'modal' | 'bottom-sheet' | 'side-nav' ;
110
+ } ;
111
+
112
+ export const Portal = component$ ( ( props : PortalProps ) => {
113
+ const context = useContext ( dialogContext ) ;
114
+ const classes = useComputed$ ( ( ) => [ props . type ?? 'modal' ] ) ;
90
115
91
116
return (
92
- < dialog class = { classes } ref = { dialogRef } onClick$ = { handleClick$ } >
93
- < Slot > </ Slot >
117
+ < dialog
118
+ class = { classes }
119
+ ref = { context . state . dialogRef }
120
+ onClick$ = { context . closeOnDialogClick }
121
+ >
122
+ < Slot />
94
123
</ dialog >
95
124
) ;
96
125
} ) ;
0 commit comments