@limonify/zest-ui 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accordion/index.d.ts +1 -0
- package/lib/accordion/index.d.ts.map +1 -1
- package/lib/accordion/index.js +3 -1
- package/lib/accordion/index.js.map +1 -1
- package/lib/accordion/panel/AccordionPanel.d.ts +19 -1
- package/lib/accordion/panel/AccordionPanel.d.ts.map +1 -1
- package/lib/accordion/panel/AccordionPanel.js +18 -2
- package/lib/accordion/panel/AccordionPanel.js.map +1 -1
- package/lib/collapsible/index.d.ts +1 -0
- package/lib/collapsible/index.d.ts.map +1 -1
- package/lib/collapsible/index.js +3 -1
- package/lib/collapsible/index.js.map +1 -1
- package/lib/collapsible/panel/CollapsiblePanel.d.ts +19 -1
- package/lib/collapsible/panel/CollapsiblePanel.d.ts.map +1 -1
- package/lib/collapsible/panel/CollapsiblePanel.js +18 -2
- package/lib/collapsible/panel/CollapsiblePanel.js.map +1 -1
- package/lib/collapsible/panel/CollapsiblePanelContext.d.ts +21 -0
- package/lib/collapsible/panel/CollapsiblePanelContext.d.ts.map +1 -0
- package/lib/collapsible/panel/CollapsiblePanelContext.js +48 -0
- package/lib/collapsible/panel/CollapsiblePanelContext.js.map +1 -0
- package/lib/collapsible/panel/useCollapsiblePanel.d.ts +17 -0
- package/lib/collapsible/panel/useCollapsiblePanel.d.ts.map +1 -1
- package/lib/collapsible/panel/useCollapsiblePanel.js +4 -2
- package/lib/collapsible/panel/useCollapsiblePanel.js.map +1 -1
- package/lib/internals/useTransitionStatus.d.ts.map +1 -1
- package/lib/internals/useTransitionStatus.js +12 -10
- package/lib/internals/useTransitionStatus.js.map +1 -1
- package/lib/switch/thumb/SwitchThumb.d.ts +19 -2
- package/lib/switch/thumb/SwitchThumb.d.ts.map +1 -1
- package/lib/switch/thumb/SwitchThumb.js +21 -3
- package/lib/switch/thumb/SwitchThumb.js.map +1 -1
- package/lib/toast/root/ToastRoot.d.ts +20 -8
- package/lib/toast/root/ToastRoot.d.ts.map +1 -1
- package/lib/toast/root/ToastRoot.js +28 -8
- package/lib/toast/root/ToastRoot.js.map +1 -1
- package/lib/toast/store.js +1 -1
- package/lib/toast/store.js.map +1 -1
- package/lib/toast/useToastManager.d.ts +7 -0
- package/lib/toast/useToastManager.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/accordion/index.ts +1 -0
- package/src/accordion/panel/AccordionPanel.tsx +40 -2
- package/src/collapsible/index.ts +1 -0
- package/src/collapsible/panel/CollapsiblePanel.tsx +40 -2
- package/src/collapsible/panel/CollapsiblePanelContext.ts +34 -0
- package/src/collapsible/panel/useCollapsiblePanel.tsx +27 -3
- package/src/internals/useTransitionStatus.ts +10 -12
- package/src/switch/thumb/SwitchThumb.tsx +40 -5
- package/src/toast/root/ToastRoot.tsx +37 -9
- package/src/toast/store.ts +1 -1
- package/src/toast/useToastManager.ts +7 -0
|
@@ -6,6 +6,7 @@ import { useToastProviderContext } from '../provider/ToastProviderContext';
|
|
|
6
6
|
import { useRenderElement } from '../../use-render/useRenderElement';
|
|
7
7
|
import { useIsoLayoutEffect } from '../../hooks/useIsoLayoutEffect';
|
|
8
8
|
import { useStableCallback } from '../../hooks/useStableCallback';
|
|
9
|
+
import { AnimationFrame } from '../../hooks/useAnimationFrame';
|
|
9
10
|
import type { ZestUIComponentProps } from '../../types';
|
|
10
11
|
import type { ToastObject } from '../useToastManager';
|
|
11
12
|
import { ToastRootContext } from './ToastRootContext';
|
|
@@ -23,12 +24,17 @@ export type ToastSwipeDirection = 'up' | 'down' | 'left' | 'right';
|
|
|
23
24
|
* `transitionStatus`, its stacking `offsetY`/`index`, and how far a swipe has
|
|
24
25
|
* travelled, and the consumer turns those into a transform.
|
|
25
26
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* `
|
|
31
|
-
*
|
|
27
|
+
* **Enter:** `transitionStatus` starts as `'starting'` (auto-clears to
|
|
28
|
+
* `undefined` after one frame). Key off `state.transitionStatus === 'starting'`
|
|
29
|
+
* to trigger a slide-in or fade-in animation.
|
|
30
|
+
*
|
|
31
|
+
* **Exit:** `removeOnClose` (on by default) drops the toast the moment it
|
|
32
|
+
* closes — the right default for a consumer who does not animate. To animate
|
|
33
|
+
* the exit, set `removeOnClose={false}`, drive the exit from
|
|
34
|
+
* `state.transitionStatus === 'ending'` using `state.measuredHeight` as the
|
|
35
|
+
* starting value (the animation target is `0`), and call
|
|
36
|
+
* `useToastManager().remove(id)` when the animation finishes.
|
|
37
|
+
* This is the same lever as `Collapsible.Panel`'s `keepMounted`.
|
|
32
38
|
*/
|
|
33
39
|
export function ToastRoot(componentProps: ToastRoot.Props) {
|
|
34
40
|
const {
|
|
@@ -64,13 +70,26 @@ export function ToastRoot(componentProps: ToastRoot.Props) {
|
|
|
64
70
|
}
|
|
65
71
|
}, [removeOnClose, toast.transitionStatus, toast.id, store]);
|
|
66
72
|
|
|
73
|
+
// `transitionStatus` starts as `'starting'` and stays that way forever.
|
|
74
|
+
// Auto-clear it after one frame so the consumer can react to `'starting'`
|
|
75
|
+
// for an enter animation without repeatedly re-triggering.
|
|
76
|
+
useIsoLayoutEffect(() => {
|
|
77
|
+
if (toast.transitionStatus === 'starting') {
|
|
78
|
+
const frame = AnimationFrame.request(() => {
|
|
79
|
+
store.updateToastInternal(toast.id, { transitionStatus: undefined });
|
|
80
|
+
});
|
|
81
|
+
return () => AnimationFrame.cancel(frame);
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}, [toast.transitionStatus, toast.id, store]);
|
|
85
|
+
|
|
67
86
|
const handleLayout = useStableCallback((event: LayoutChangeEvent) => {
|
|
68
87
|
const { height } = event.nativeEvent.layout;
|
|
69
88
|
|
|
70
89
|
// A closing toast reports a height of 0 through the store; measuring it again
|
|
71
90
|
// here would undo that and leave a gap in the stack.
|
|
72
91
|
if (toast.transitionStatus !== 'ending' && height !== toast.height) {
|
|
73
|
-
store.updateToastInternal(toast.id, { height });
|
|
92
|
+
store.updateToastInternal(toast.id, { height, measuredHeight: height });
|
|
74
93
|
}
|
|
75
94
|
});
|
|
76
95
|
|
|
@@ -124,6 +143,7 @@ export function ToastRoot(componentProps: ToastRoot.Props) {
|
|
|
124
143
|
visibleIndex,
|
|
125
144
|
offsetY,
|
|
126
145
|
height: toast.height ?? 0,
|
|
146
|
+
measuredHeight: toast.measuredHeight ?? toast.height ?? 0,
|
|
127
147
|
swiping,
|
|
128
148
|
swipeMovement,
|
|
129
149
|
swipeDirection,
|
|
@@ -137,6 +157,7 @@ export function ToastRoot(componentProps: ToastRoot.Props) {
|
|
|
137
157
|
visibleIndex,
|
|
138
158
|
offsetY,
|
|
139
159
|
toast.height,
|
|
160
|
+
toast.measuredHeight,
|
|
140
161
|
swiping,
|
|
141
162
|
swipeMovement,
|
|
142
163
|
swipeDirection,
|
|
@@ -192,8 +213,9 @@ function getDisplacement(
|
|
|
192
213
|
|
|
193
214
|
export interface ToastRootState {
|
|
194
215
|
/**
|
|
195
|
-
* The toast's transition status: `'starting'` as it arrives
|
|
196
|
-
* is
|
|
216
|
+
* The toast's transition status: `'starting'` as it arrives (auto-clears to
|
|
217
|
+
* `undefined` after one frame for enter animation), `'ending'` once it is
|
|
218
|
+
* closing.
|
|
197
219
|
*/
|
|
198
220
|
transitionStatus: 'starting' | 'ending' | undefined;
|
|
199
221
|
/**
|
|
@@ -227,6 +249,12 @@ export interface ToastRootState {
|
|
|
227
249
|
* The toast's measured height.
|
|
228
250
|
*/
|
|
229
251
|
height: number;
|
|
252
|
+
/**
|
|
253
|
+
* The last measured height before the toast closed, preserved for the
|
|
254
|
+
* consumer to use as the starting value for an exit animation.
|
|
255
|
+
* Falls back to `height` when no close has occurred yet.
|
|
256
|
+
*/
|
|
257
|
+
measuredHeight: number;
|
|
230
258
|
/**
|
|
231
259
|
* Whether a swipe is currently in progress.
|
|
232
260
|
*/
|
package/src/toast/store.ts
CHANGED
|
@@ -301,7 +301,7 @@ export class ToastStore extends ReactStore<State, {}, typeof selectors> {
|
|
|
301
301
|
|
|
302
302
|
const endingToasts = toasts.map((item) =>
|
|
303
303
|
closeAll || item.id === toastId
|
|
304
|
-
? { ...item, transitionStatus: 'ending' as const, height: 0 }
|
|
304
|
+
? { ...item, transitionStatus: 'ending' as const, height: 0, measuredHeight: item.height }
|
|
305
305
|
: item,
|
|
306
306
|
);
|
|
307
307
|
const newToasts = applyLimited(endingToasts, limit);
|
|
@@ -70,6 +70,13 @@ export interface ToastObject<Data extends object> {
|
|
|
70
70
|
* The height of the toast.
|
|
71
71
|
*/
|
|
72
72
|
height?: number | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* The last measured height of the toast, captured at the moment it closes.
|
|
75
|
+
* Unlike `height` (which is set to `0` on close for stack collapse), this
|
|
76
|
+
* preserves the value so the consumer can use it as the starting point for
|
|
77
|
+
* an exit animation.
|
|
78
|
+
*/
|
|
79
|
+
measuredHeight?: number | undefined;
|
|
73
80
|
/**
|
|
74
81
|
* Callback function to be called when the toast is closed.
|
|
75
82
|
*/
|