@butternutbox/pawprint-native 1.5.1 → 1.6.0
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +6 -0
- package/dist/index.cjs +22 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +22 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/molecules/Drawer/Drawer.test.tsx +49 -2
- package/src/components/molecules/Drawer/Drawer.tsx +32 -3
package/package.json
CHANGED
|
@@ -6,12 +6,18 @@ import { Drawer } from "./Drawer"
|
|
|
6
6
|
|
|
7
7
|
const BasicDrawer = ({
|
|
8
8
|
open,
|
|
9
|
-
onOpenChange
|
|
9
|
+
onOpenChange,
|
|
10
|
+
onExitComplete
|
|
10
11
|
}: {
|
|
11
12
|
open?: boolean
|
|
12
13
|
onOpenChange?: (v: boolean) => void
|
|
14
|
+
onExitComplete?: () => void
|
|
13
15
|
}) => (
|
|
14
|
-
<Drawer.Root
|
|
16
|
+
<Drawer.Root
|
|
17
|
+
open={open}
|
|
18
|
+
onOpenChange={onOpenChange}
|
|
19
|
+
onExitComplete={onExitComplete}
|
|
20
|
+
>
|
|
15
21
|
<Drawer.Trigger>
|
|
16
22
|
<button>Open</button>
|
|
17
23
|
</Drawer.Trigger>
|
|
@@ -77,6 +83,47 @@ describe("Drawer", () => {
|
|
|
77
83
|
})
|
|
78
84
|
})
|
|
79
85
|
|
|
86
|
+
describe("onExitComplete", () => {
|
|
87
|
+
it("is not called while the drawer has never closed", () => {
|
|
88
|
+
const onExitComplete = vi.fn()
|
|
89
|
+
const { rerender } = renderWithTheme(
|
|
90
|
+
<BasicDrawer open={false} onExitComplete={onExitComplete} />
|
|
91
|
+
)
|
|
92
|
+
rerender(<BasicDrawer open onExitComplete={onExitComplete} />)
|
|
93
|
+
expect(onExitComplete).not.toHaveBeenCalled()
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it("is called once the drawer has closed and its content is removed", () => {
|
|
97
|
+
const onExitComplete = vi.fn(() => {
|
|
98
|
+
expect(screen.queryByText("Drawer title")).not.toBeInTheDocument()
|
|
99
|
+
})
|
|
100
|
+
const { rerender } = renderWithTheme(
|
|
101
|
+
<BasicDrawer open onExitComplete={onExitComplete} />
|
|
102
|
+
)
|
|
103
|
+
rerender(<BasicDrawer open={false} onExitComplete={onExitComplete} />)
|
|
104
|
+
expect(onExitComplete).toHaveBeenCalledTimes(1)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it("is called once per close", () => {
|
|
108
|
+
const onExitComplete = vi.fn()
|
|
109
|
+
const { rerender } = renderWithTheme(
|
|
110
|
+
<BasicDrawer open onExitComplete={onExitComplete} />
|
|
111
|
+
)
|
|
112
|
+
rerender(<BasicDrawer open={false} onExitComplete={onExitComplete} />)
|
|
113
|
+
rerender(<BasicDrawer open onExitComplete={onExitComplete} />)
|
|
114
|
+
rerender(<BasicDrawer open={false} onExitComplete={onExitComplete} />)
|
|
115
|
+
expect(onExitComplete).toHaveBeenCalledTimes(2)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it("is called when an uncontrolled drawer is closed", () => {
|
|
119
|
+
const onExitComplete = vi.fn()
|
|
120
|
+
renderWithTheme(<BasicDrawer onExitComplete={onExitComplete} />)
|
|
121
|
+
fireEvent.click(screen.getByText("Open"))
|
|
122
|
+
fireEvent.click(screen.getByLabelText("Close"))
|
|
123
|
+
expect(onExitComplete).toHaveBeenCalledTimes(1)
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
|
|
80
127
|
describe("controlled mode", () => {
|
|
81
128
|
it("respects controlled open=true", () => {
|
|
82
129
|
renderWithTheme(<BasicDrawer open />)
|
|
@@ -19,6 +19,14 @@ type DrawerRootOwnProps = {
|
|
|
19
19
|
open?: boolean
|
|
20
20
|
defaultOpen?: boolean
|
|
21
21
|
onOpenChange?: (open: boolean) => void
|
|
22
|
+
/**
|
|
23
|
+
* Called once the drawer has fully closed: the exit animation has finished
|
|
24
|
+
* and the native `Modal` has been removed. Use it to chain work that can't
|
|
25
|
+
* overlap the drawer, such as opening another modal drawer (iOS won't present
|
|
26
|
+
* a second `Modal` while the first is still on screen) or unmounting the
|
|
27
|
+
* drawer's host.
|
|
28
|
+
*/
|
|
29
|
+
onExitComplete?: () => void
|
|
22
30
|
/**
|
|
23
31
|
* Whether the drawer shows a dimming backdrop and presents as a blocking
|
|
24
32
|
* modal (default `true`). Set to `false` for a backdrop-less, pass-through
|
|
@@ -70,6 +78,7 @@ const DrawerRoot = React.forwardRef<View, DrawerProps>(
|
|
|
70
78
|
open: controlledOpen,
|
|
71
79
|
defaultOpen = false,
|
|
72
80
|
onOpenChange,
|
|
81
|
+
onExitComplete,
|
|
73
82
|
backdrop = true,
|
|
74
83
|
children,
|
|
75
84
|
style,
|
|
@@ -102,10 +111,23 @@ const DrawerRoot = React.forwardRef<View, DrawerProps>(
|
|
|
102
111
|
onOpenChange?.(false)
|
|
103
112
|
}, [onOpenChange])
|
|
104
113
|
|
|
105
|
-
const
|
|
114
|
+
const handleExitComplete = useCallback(() => {
|
|
106
115
|
setModalVisible(false)
|
|
107
116
|
}, [])
|
|
108
117
|
|
|
118
|
+
const onExitCompleteRef = useRef(onExitComplete)
|
|
119
|
+
onExitCompleteRef.current = onExitComplete
|
|
120
|
+
const wasModalVisible = useRef(modalVisible)
|
|
121
|
+
|
|
122
|
+
// Fires after the commit that removed the Modal, not from the animation
|
|
123
|
+
// callback, so consumers never act while the Modal is still mounted.
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (wasModalVisible.current && !modalVisible) {
|
|
126
|
+
onExitCompleteRef.current?.()
|
|
127
|
+
}
|
|
128
|
+
wasModalVisible.current = modalVisible
|
|
129
|
+
}, [modalVisible])
|
|
130
|
+
|
|
109
131
|
const ctx = useMemo(
|
|
110
132
|
() => ({
|
|
111
133
|
isOpen,
|
|
@@ -113,9 +135,16 @@ const DrawerRoot = React.forwardRef<View, DrawerProps>(
|
|
|
113
135
|
backdrop,
|
|
114
136
|
openDrawer,
|
|
115
137
|
closeDrawer,
|
|
116
|
-
onExitComplete
|
|
138
|
+
onExitComplete: handleExitComplete
|
|
117
139
|
}),
|
|
118
|
-
[
|
|
140
|
+
[
|
|
141
|
+
isOpen,
|
|
142
|
+
modalVisible,
|
|
143
|
+
backdrop,
|
|
144
|
+
openDrawer,
|
|
145
|
+
closeDrawer,
|
|
146
|
+
handleExitComplete
|
|
147
|
+
]
|
|
119
148
|
)
|
|
120
149
|
|
|
121
150
|
return (
|