|
1 |
| -import { useId } from '@chakra-ui/vue-composables' |
2 |
| -import { createContext } from '@chakra-ui/vue-utils' |
3 | 1 | import { MotionVariants } from '@vueuse/motion'
|
4 |
| -import { computed, ComputedRef, reactive, ref, Ref, watchEffect } from 'vue' |
5 |
| - |
6 |
| -export type DialogTransitionStatus = 'exited' | 'entered' | 'initial' | 'active' |
7 |
| - |
8 |
| -export interface TransitionInstance { |
9 |
| - id: number | string |
10 |
| - isActive: boolean |
11 |
| - el?: HTMLElement |
12 |
| - status: DialogTransitionStatus |
13 |
| -} |
14 |
| - |
15 |
| -export interface TransitionStateHelpers { |
16 |
| - /** |
17 |
| - * Sets the transition status to 'initial' |
18 |
| - */ |
19 |
| - initial: VoidFunction |
20 |
| - /** |
21 |
| - * Sets the transition status to 'active' |
22 |
| - */ |
23 |
| - active: VoidFunction |
24 |
| - /** |
25 |
| - * Sets the transition status to 'entered' |
26 |
| - */ |
27 |
| - entered: VoidFunction |
28 |
| - /** |
29 |
| - * Sets the transition status to 'exited' |
30 |
| - */ |
31 |
| - exited: VoidFunction |
32 |
| -} |
33 |
| - |
34 |
| -export interface DialogTransitionContext { |
35 |
| - /** |
36 |
| - * Local state transitioning state |
37 |
| - */ |
38 |
| - localIsOpen: Ref<boolean> |
39 |
| - /** |
40 |
| - * Reflects whether all children are currently transitioning |
41 |
| - */ |
42 |
| - isTransitioning: ComputedRef<boolean> |
43 |
| - /** |
44 |
| - * Reflects whether all children are currently transitioning in |
45 |
| - */ |
46 |
| - isTransitioningIn: ComputedRef<boolean> |
47 |
| - /** |
48 |
| - * Reflects whether all children are currently transitioning out |
49 |
| - */ |
50 |
| - isTransitioningOut: ComputedRef<boolean> |
51 |
| - /** |
52 |
| - * Registers a new transition to set of transitions |
53 |
| - */ |
54 |
| - register: ( |
55 |
| - uid: number | string |
56 |
| - ) => [Ref<TransitionInstance>, TransitionStateHelpers] |
57 |
| -} |
58 |
| - |
59 |
| -export interface DialogTransitionsOptions { |
60 |
| - /** |
61 |
| - * Callback invoked when all children have finished transitioning in |
62 |
| - */ |
63 |
| - onChildrenEntered: () => void |
64 |
| - /** |
65 |
| - * Callback invoked when all children have finished transitioning out |
66 |
| - */ |
67 |
| - onChildrenLeft: () => void |
68 |
| -} |
69 |
| - |
70 |
| -const [DialogTransitionsProvider, useDialogTransition] = createContext< |
71 |
| - ComputedRef<DialogTransitionContext> |
72 |
| ->({ |
73 |
| - strict: true, |
74 |
| - name: 'DialogTransitionContext', |
75 |
| - errorMessage: |
76 |
| - 'useDialogTransition: `context` is undefined. Seems you forgot to wrap modal components in `<CModal />`, `<CDrawer />` or `<CAlertDialog />', |
77 |
| -}) |
78 |
| - |
79 |
| -/** |
80 |
| - * Hook used to manage all transitions in a compound component context |
81 |
| - * used by CModal, CDrawer and CAlertDialog |
82 |
| - */ |
83 |
| -export function useDialogTransitions( |
84 |
| - isOpen: Ref<boolean> | ComputedRef<boolean>, |
85 |
| - events?: DialogTransitionsOptions |
86 |
| -) { |
87 |
| - const localIsOpen = ref(false) |
88 |
| - const transitions = ref<Ref<TransitionInstance>[]>([]) |
89 |
| - |
90 |
| - const isTransitioning = computed(() => |
91 |
| - transitions.value.find((transition) => |
92 |
| - ['entered', 'exited'].includes(transition.value.status) |
93 |
| - )?.value |
94 |
| - ? true |
95 |
| - : false |
96 |
| - ) |
97 |
| - |
98 |
| - const transitionsStore = reactive({}) |
99 |
| - |
100 |
| - const transitionsEntered = computed(() => |
101 |
| - transitions.value.every( |
102 |
| - (transition) => transition.value.status === 'entered' |
103 |
| - ) |
104 |
| - ) |
105 |
| - |
106 |
| - const transitionsExited = computed(() => |
107 |
| - transitions.value.every( |
108 |
| - (transition) => transition.value.status === 'exited' |
109 |
| - ) |
110 |
| - ) |
111 |
| - |
112 |
| - const isTransitioningIn = computed( |
113 |
| - () => (isOpen.value && !!isTransitioning.value) as boolean |
114 |
| - ) |
115 |
| - |
116 |
| - const isTransitioningOut = computed( |
117 |
| - () => (!isOpen.value && !!isTransitioning.value) as boolean |
118 |
| - ) |
119 |
| - |
120 |
| - const register: DialogTransitionContext['register'] = (uid) => { |
121 |
| - const transition = ref<TransitionInstance>({ |
122 |
| - id: uid, |
123 |
| - isActive: false, |
124 |
| - el: undefined, // TODO May include this later |
125 |
| - status: 'initial', |
126 |
| - }) |
127 |
| - |
128 |
| - const exited = () => { |
129 |
| - transition.value.status = 'exited' |
130 |
| - } |
131 |
| - const initial = () => { |
132 |
| - transition.value.status = 'initial' |
133 |
| - } |
134 |
| - const entered = () => { |
135 |
| - transition.value.status = 'entered' |
136 |
| - } |
137 |
| - const active = () => { |
138 |
| - transition.value.status = 'active' |
139 |
| - } |
140 |
| - |
141 |
| - if (transitionsStore[uid]) { |
142 |
| - return [transition, { active, initial, entered, exited }] |
143 |
| - } else { |
144 |
| - transitions.value.push(transition) |
145 |
| - transitionsStore[uid] = transition |
146 |
| - } |
147 |
| - |
148 |
| - return [transition, { active, initial, entered, exited }] |
149 |
| - } |
150 |
| - |
151 |
| - watchEffect( |
152 |
| - () => { |
153 |
| - if (isOpen.value) { |
154 |
| - localIsOpen.value = true |
155 |
| - } else if (!isOpen.value) { |
156 |
| - localIsOpen.value = false |
157 |
| - } |
158 |
| - |
159 |
| - if (transitionsEntered.value) { |
160 |
| - events?.onChildrenEntered() |
161 |
| - } |
162 |
| - |
163 |
| - if (transitionsExited.value) { |
164 |
| - events?.onChildrenLeft() |
165 |
| - } |
166 |
| - }, |
167 |
| - { |
168 |
| - flush: 'post', |
169 |
| - } |
170 |
| - ) |
171 |
| - |
172 |
| - const dialogTransitionsContext = computed(() => ({ |
173 |
| - localIsOpen, |
174 |
| - isTransitioning, |
175 |
| - isTransitioningIn, |
176 |
| - isTransitioningOut, |
177 |
| - register, |
178 |
| - })) |
179 |
| - |
180 |
| - DialogTransitionsProvider(dialogTransitionsContext) |
181 |
| - |
182 |
| - return { |
183 |
| - localIsOpen, |
184 |
| - isTransitioning, |
185 |
| - isTransitioningIn, |
186 |
| - isTransitioningOut, |
187 |
| - register, |
188 |
| - transitionsEntered, |
189 |
| - transitionsExited, |
190 |
| - } |
191 |
| -} |
192 |
| - |
193 |
| -export { useDialogTransition } |
194 | 2 |
|
195 | 3 | export type DialogMotionPreset =
|
196 | 4 | | 'slideInBottom'
|
|
0 commit comments