@oxyhq/bloom 0.14.0 → 0.15.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/lib/commonjs/dialog/CenteredDialog.js +2 -0
- package/lib/commonjs/dialog/CenteredDialog.js.map +1 -1
- package/lib/commonjs/dialog/CenteredDialog.web.js +2 -0
- package/lib/commonjs/dialog/CenteredDialog.web.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.js +337 -43
- package/lib/commonjs/dialog/Dialog.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +414 -63
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/dialog/index.js +6 -0
- package/lib/commonjs/dialog/index.js.map +1 -1
- package/lib/commonjs/dialog/index.web.js +6 -0
- package/lib/commonjs/dialog/index.web.js.map +1 -1
- package/lib/commonjs/dialog/placement.js +104 -0
- package/lib/commonjs/dialog/placement.js.map +1 -0
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +7 -0
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.js +63 -266
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.js.map +1 -1
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.web.js +84 -0
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.web.js.map +1 -0
- package/lib/commonjs/responsive-sheet/index.web.js +3 -3
- package/lib/commonjs/responsive-sheet/index.web.js.map +1 -1
- package/lib/module/dialog/CenteredDialog.js +2 -0
- package/lib/module/dialog/CenteredDialog.js.map +1 -1
- package/lib/module/dialog/CenteredDialog.web.js +2 -0
- package/lib/module/dialog/CenteredDialog.web.js.map +1 -1
- package/lib/module/dialog/Dialog.js +336 -46
- package/lib/module/dialog/Dialog.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +412 -65
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/dialog/index.js +1 -1
- package/lib/module/dialog/index.js.map +1 -1
- package/lib/module/dialog/index.web.js +1 -1
- package/lib/module/dialog/index.web.js.map +1 -1
- package/lib/module/dialog/placement.js +100 -0
- package/lib/module/dialog/placement.js.map +1 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +1 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/responsive-sheet/ResponsiveSheet.js +63 -266
- package/lib/module/responsive-sheet/ResponsiveSheet.js.map +1 -1
- package/lib/module/responsive-sheet/ResponsiveSheet.web.js +77 -0
- package/lib/module/responsive-sheet/ResponsiveSheet.web.js.map +1 -0
- package/lib/module/responsive-sheet/index.web.js +7 -9
- package/lib/module/responsive-sheet/index.web.js.map +1 -1
- package/lib/typescript/commonjs/dialog/CenteredDialog.d.ts +2 -0
- package/lib/typescript/commonjs/dialog/CenteredDialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/CenteredDialog.web.d.ts +2 -0
- package/lib/typescript/commonjs/dialog/CenteredDialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.d.ts +18 -15
- package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts +18 -5
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/centered-dialog-types.d.ts +4 -0
- package/lib/typescript/commonjs/dialog/centered-dialog-types.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/index.d.ts +2 -2
- package/lib/typescript/commonjs/dialog/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/index.web.d.ts +2 -2
- package/lib/typescript/commonjs/dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/placement.d.ts +71 -0
- package/lib/typescript/commonjs/dialog/placement.d.ts.map +1 -0
- package/lib/typescript/commonjs/dialog/types.d.ts +66 -3
- package/lib/typescript/commonjs/dialog/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +2 -2
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.d.ts +15 -19
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.d.ts.map +1 -1
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.web.d.ts +16 -0
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/responsive-sheet/index.web.d.ts +1 -1
- package/lib/typescript/commonjs/responsive-sheet/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/responsive-sheet/types.d.ts +5 -2
- package/lib/typescript/commonjs/responsive-sheet/types.d.ts.map +1 -1
- package/lib/typescript/module/dialog/CenteredDialog.d.ts +2 -0
- package/lib/typescript/module/dialog/CenteredDialog.d.ts.map +1 -1
- package/lib/typescript/module/dialog/CenteredDialog.web.d.ts +2 -0
- package/lib/typescript/module/dialog/CenteredDialog.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.d.ts +18 -15
- package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts +18 -5
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/centered-dialog-types.d.ts +4 -0
- package/lib/typescript/module/dialog/centered-dialog-types.d.ts.map +1 -1
- package/lib/typescript/module/dialog/index.d.ts +2 -2
- package/lib/typescript/module/dialog/index.d.ts.map +1 -1
- package/lib/typescript/module/dialog/index.web.d.ts +2 -2
- package/lib/typescript/module/dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/placement.d.ts +71 -0
- package/lib/typescript/module/dialog/placement.d.ts.map +1 -0
- package/lib/typescript/module/dialog/types.d.ts +66 -3
- package/lib/typescript/module/dialog/types.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +2 -2
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.d.ts +15 -19
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.d.ts.map +1 -1
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.web.d.ts +16 -0
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.web.d.ts.map +1 -0
- package/lib/typescript/module/responsive-sheet/index.web.d.ts +1 -1
- package/lib/typescript/module/responsive-sheet/index.web.d.ts.map +1 -1
- package/lib/typescript/module/responsive-sheet/types.d.ts +5 -2
- package/lib/typescript/module/responsive-sheet/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/DialogPlacement.test.tsx +144 -0
- package/src/__tests__/ResponsiveSheet.test.tsx +36 -52
- package/src/dialog/CenteredDialog.tsx +2 -0
- package/src/dialog/CenteredDialog.web.tsx +2 -0
- package/src/dialog/Dialog.tsx +407 -50
- package/src/dialog/Dialog.web.tsx +490 -75
- package/src/dialog/centered-dialog-types.ts +4 -0
- package/src/dialog/index.ts +4 -1
- package/src/dialog/index.web.ts +4 -1
- package/src/dialog/placement.ts +113 -0
- package/src/dialog/types.ts +69 -3
- package/src/index.ts +4 -0
- package/src/index.web.ts +4 -0
- package/src/responsive-sheet/ResponsiveSheet.tsx +58 -297
- package/src/responsive-sheet/ResponsiveSheet.web.tsx +76 -0
- package/src/responsive-sheet/index.web.ts +7 -9
- package/src/responsive-sheet/types.ts +5 -2
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.native.js +0 -226
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.native.js.map +0 -1
- package/lib/commonjs/responsive-sheet/const.js +0 -60
- package/lib/commonjs/responsive-sheet/const.js.map +0 -1
- package/lib/module/responsive-sheet/ResponsiveSheet.native.js +0 -219
- package/lib/module/responsive-sheet/ResponsiveSheet.native.js.map +0 -1
- package/lib/module/responsive-sheet/const.js +0 -56
- package/lib/module/responsive-sheet/const.js.map +0 -1
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.native.d.ts +0 -20
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.native.d.ts.map +0 -1
- package/lib/typescript/commonjs/responsive-sheet/const.d.ts +0 -43
- package/lib/typescript/commonjs/responsive-sheet/const.d.ts.map +0 -1
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.native.d.ts +0 -20
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.native.d.ts.map +0 -1
- package/lib/typescript/module/responsive-sheet/const.d.ts +0 -43
- package/lib/typescript/module/responsive-sheet/const.d.ts.map +0 -1
- package/src/responsive-sheet/ResponsiveSheet.native.tsx +0 -257
- package/src/responsive-sheet/const.ts +0 -53
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../../src/responsive-sheet/index.web.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../../src/responsive-sheet/index.web.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,gCAAgC,EAAE,MAAM,uBAAuB,CAAC;AAC1F,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
|
|
@@ -14,11 +14,14 @@ export interface ResponsiveSheetInset {
|
|
|
14
14
|
right?: number;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
+
* @deprecated Use `<Dialog placement={{ base: 'bottom', md: 'left' }}>` from
|
|
18
|
+
* `@oxyhq/bloom/dialog` instead. `ResponsiveSheet` is now a thin wrapper over
|
|
19
|
+
* `<Dialog>` retained for the migration window.
|
|
20
|
+
*
|
|
17
21
|
* A responsive overlay sheet: an anchored side-sheet on wide screens and a
|
|
18
22
|
* bottom-sheet (with drag handle) on small screens, switching by viewport
|
|
19
23
|
* width. It is a plain controlled component — the host drives `open`/`onClose`
|
|
20
|
-
* from its own state.
|
|
21
|
-
* inside a themed/positioned subtree.
|
|
24
|
+
* from its own state.
|
|
22
25
|
*/
|
|
23
26
|
export interface ResponsiveSheetProps {
|
|
24
27
|
/** Whether the sheet is open. Controlled by the host. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/responsive-sheet/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,gDAAgD;AAChD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/responsive-sheet/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,gDAAgD;AAChD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,4EAA4E;IAC5E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,yDAAyD;IACzD,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oFAAoF;IACpF,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,kFAAkF;IAClF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text } from 'react-native';
|
|
3
|
+
import { act, fireEvent, render } from '@testing-library/react-native';
|
|
4
|
+
|
|
5
|
+
import { Dialog } from '../dialog';
|
|
6
|
+
import {
|
|
7
|
+
BREAKPOINT_MD,
|
|
8
|
+
useResolvedPlacement,
|
|
9
|
+
type DialogPlacement,
|
|
10
|
+
type ResponsiveDialogPlacement,
|
|
11
|
+
} from '../dialog/placement';
|
|
12
|
+
import { BloomThemeProvider } from '../theme/BloomThemeProvider';
|
|
13
|
+
|
|
14
|
+
// The RN test mock reports a 375px-wide viewport (below every breakpoint), so a
|
|
15
|
+
// responsive `placement` map resolves to its `base`.
|
|
16
|
+
const MOCK_VIEWPORT_WIDTH = 375;
|
|
17
|
+
|
|
18
|
+
function renderWithTheme(ui: React.ReactElement) {
|
|
19
|
+
return render(
|
|
20
|
+
<BloomThemeProvider mode="light" colorPreset="teal">
|
|
21
|
+
{ui}
|
|
22
|
+
</BloomThemeProvider>,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Capture `useResolvedPlacement`'s output for a given input. */
|
|
27
|
+
function ResolveProbe({
|
|
28
|
+
placement,
|
|
29
|
+
onResolve,
|
|
30
|
+
}: {
|
|
31
|
+
placement: ResponsiveDialogPlacement | undefined;
|
|
32
|
+
onResolve: (p: DialogPlacement) => void;
|
|
33
|
+
}) {
|
|
34
|
+
const resolved = useResolvedPlacement(placement);
|
|
35
|
+
onResolve(resolved);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function resolve(placement: ResponsiveDialogPlacement | undefined): DialogPlacement {
|
|
40
|
+
let captured: DialogPlacement = 'center';
|
|
41
|
+
renderWithTheme(
|
|
42
|
+
<ResolveProbe placement={placement} onResolve={(p) => { captured = p; }} />,
|
|
43
|
+
);
|
|
44
|
+
return captured;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe('useResolvedPlacement', () => {
|
|
48
|
+
it('defaults to center when placement is undefined', () => {
|
|
49
|
+
expect(resolve(undefined)).toBe('center');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('returns a plain string placement unchanged', () => {
|
|
53
|
+
expect(resolve('left')).toBe('left');
|
|
54
|
+
expect(resolve('right')).toBe('right');
|
|
55
|
+
expect(resolve('bottom')).toBe('bottom');
|
|
56
|
+
expect(resolve('center')).toBe('center');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('resolves a responsive map to base below the first breakpoint', () => {
|
|
60
|
+
// Sanity: the mock viewport is narrower than md, so md/lg/xl never apply.
|
|
61
|
+
expect(MOCK_VIEWPORT_WIDTH).toBeLessThan(BREAKPOINT_MD);
|
|
62
|
+
expect(resolve({ base: 'bottom', md: 'left' })).toBe('bottom');
|
|
63
|
+
expect(resolve({ base: 'bottom', md: 'center' })).toBe('bottom');
|
|
64
|
+
expect(resolve({ base: 'bottom', sm: 'right', lg: 'center' })).toBe('bottom');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('ignores higher breakpoint keys that exceed the viewport width', () => {
|
|
68
|
+
// Only `base` applies at 375px wide; the `xl` override does not engage.
|
|
69
|
+
expect(resolve({ base: 'right', xl: 'left' })).toBe('right');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('Dialog controlled open mode', () => {
|
|
74
|
+
it('does not render content while open is false', () => {
|
|
75
|
+
const { queryByText } = renderWithTheme(
|
|
76
|
+
<Dialog open={false} onClose={() => {}} title="Controlled">
|
|
77
|
+
<Text>Controlled body</Text>
|
|
78
|
+
</Dialog>,
|
|
79
|
+
);
|
|
80
|
+
expect(queryByText('Controlled body')).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('renders content when open flips to true (no control needed)', () => {
|
|
84
|
+
const { getByText, rerender } = renderWithTheme(
|
|
85
|
+
<Dialog open={false} onClose={() => {}} title="Controlled">
|
|
86
|
+
<Text>Controlled body</Text>
|
|
87
|
+
</Dialog>,
|
|
88
|
+
);
|
|
89
|
+
rerender(
|
|
90
|
+
<BloomThemeProvider mode="light" colorPreset="teal">
|
|
91
|
+
<Dialog open onClose={() => {}} title="Controlled">
|
|
92
|
+
<Text>Controlled body</Text>
|
|
93
|
+
</Dialog>
|
|
94
|
+
</BloomThemeProvider>,
|
|
95
|
+
);
|
|
96
|
+
expect(getByText('Controlled body')).toBeTruthy();
|
|
97
|
+
expect(getByText('Controlled')).toBeTruthy();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('unmounts after open flips back to false and the close settles', () => {
|
|
101
|
+
jest.useFakeTimers();
|
|
102
|
+
try {
|
|
103
|
+
const { getByText, queryByText, rerender } = renderWithTheme(
|
|
104
|
+
<Dialog open onClose={() => {}} title="Controlled">
|
|
105
|
+
<Text>Controlled body</Text>
|
|
106
|
+
</Dialog>,
|
|
107
|
+
);
|
|
108
|
+
expect(getByText('Controlled body')).toBeTruthy();
|
|
109
|
+
|
|
110
|
+
rerender(
|
|
111
|
+
<BloomThemeProvider mode="light" colorPreset="teal">
|
|
112
|
+
<Dialog open={false} onClose={() => {}} title="Controlled">
|
|
113
|
+
<Text>Controlled body</Text>
|
|
114
|
+
</Dialog>
|
|
115
|
+
</BloomThemeProvider>,
|
|
116
|
+
);
|
|
117
|
+
act(() => {
|
|
118
|
+
jest.advanceTimersByTime(500);
|
|
119
|
+
});
|
|
120
|
+
expect(queryByText('Controlled body')).toBeNull();
|
|
121
|
+
} finally {
|
|
122
|
+
jest.useRealTimers();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('requests close via onClose exactly once when an action is pressed (no double-fire)', () => {
|
|
127
|
+
const onClose = jest.fn();
|
|
128
|
+
const { getByText } = renderWithTheme(
|
|
129
|
+
<Dialog
|
|
130
|
+
open
|
|
131
|
+
onClose={onClose}
|
|
132
|
+
title="Controlled"
|
|
133
|
+
actions={[{ label: 'Done' }]}
|
|
134
|
+
/>,
|
|
135
|
+
);
|
|
136
|
+
act(() => {
|
|
137
|
+
fireEvent.press(getByText('Done'));
|
|
138
|
+
});
|
|
139
|
+
// In controlled mode the action's close() requests dismissal via onClose
|
|
140
|
+
// once; the host (not the dialog) then flips `open`. It must not fire the
|
|
141
|
+
// close-completion onClose a second time.
|
|
142
|
+
expect(onClose).toHaveBeenCalledTimes(1);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Text } from 'react-native';
|
|
3
|
-
import { act,
|
|
3
|
+
import { act, render } from '@testing-library/react-native';
|
|
4
4
|
|
|
5
|
-
import { ResponsiveSheet
|
|
5
|
+
import { ResponsiveSheet } from '../responsive-sheet';
|
|
6
6
|
import { BloomThemeProvider } from '../theme/BloomThemeProvider';
|
|
7
7
|
|
|
8
8
|
function renderWithTheme(ui: React.ReactElement) {
|
|
@@ -13,9 +13,25 @@ function renderWithTheme(ui: React.ReactElement) {
|
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function rerenderWithTheme(
|
|
17
|
+
rerender: ReturnType<typeof render>['rerender'],
|
|
18
|
+
ui: React.ReactElement,
|
|
19
|
+
) {
|
|
20
|
+
rerender(
|
|
21
|
+
<BloomThemeProvider mode="light" colorPreset="teal">
|
|
22
|
+
{ui}
|
|
23
|
+
</BloomThemeProvider>,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
const LABEL = 'Filters sheet';
|
|
17
28
|
|
|
18
|
-
|
|
29
|
+
// `ResponsiveSheet` is now a deprecated thin wrapper over `<Dialog>`. These
|
|
30
|
+
// tests verify the controlled wrapper contract it still owns (open/close
|
|
31
|
+
// presence + delegation). The jest env reports a 375px-wide viewport (below
|
|
32
|
+
// the default `md` breakpoint) so the wrapper resolves to the bottom-sheet
|
|
33
|
+
// placement, which delegates to bloom's `BottomSheet`.
|
|
34
|
+
describe('ResponsiveSheet (deprecated Dialog wrapper)', () => {
|
|
19
35
|
it('renders children when open', () => {
|
|
20
36
|
const { getByText } = renderWithTheme(
|
|
21
37
|
<ResponsiveSheet open onClose={() => {}} label={LABEL}>
|
|
@@ -34,45 +50,7 @@ describe('ResponsiveSheet', () => {
|
|
|
34
50
|
expect(queryByText('Sheet body')).toBeNull();
|
|
35
51
|
});
|
|
36
52
|
|
|
37
|
-
|
|
38
|
-
// RNTL treats it as accessibility-hidden during the synchronous first frame.
|
|
39
|
-
// `includeHiddenElements` lets us assert its (real, interactive) press
|
|
40
|
-
// behavior without depending on the enter transition having committed.
|
|
41
|
-
const HIDDEN = { includeHiddenElements: true } as const;
|
|
42
|
-
|
|
43
|
-
it('calls onClose when the backdrop is pressed (default dismissOnBackdrop)', () => {
|
|
44
|
-
const onClose = jest.fn();
|
|
45
|
-
const { getByTestId } = renderWithTheme(
|
|
46
|
-
<ResponsiveSheet open onClose={onClose} label={LABEL}>
|
|
47
|
-
<Text>Sheet body</Text>
|
|
48
|
-
</ResponsiveSheet>,
|
|
49
|
-
);
|
|
50
|
-
fireEvent.press(getByTestId(RESPONSIVE_SHEET_BACKDROP_TESTID, HIDDEN));
|
|
51
|
-
expect(onClose).toHaveBeenCalledTimes(1);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('does NOT call onClose on backdrop press when dismissOnBackdrop is false', () => {
|
|
55
|
-
const onClose = jest.fn();
|
|
56
|
-
const { getByTestId } = renderWithTheme(
|
|
57
|
-
<ResponsiveSheet open onClose={onClose} label={LABEL} dismissOnBackdrop={false}>
|
|
58
|
-
<Text>Sheet body</Text>
|
|
59
|
-
</ResponsiveSheet>,
|
|
60
|
-
);
|
|
61
|
-
fireEvent.press(getByTestId(RESPONSIVE_SHEET_BACKDROP_TESTID, HIDDEN));
|
|
62
|
-
expect(onClose).not.toHaveBeenCalled();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('labels the panel and the dismiss backdrop distinctly', () => {
|
|
66
|
-
const { getByLabelText } = renderWithTheme(
|
|
67
|
-
<ResponsiveSheet open onClose={() => {}} label={LABEL}>
|
|
68
|
-
<Text>Sheet body</Text>
|
|
69
|
-
</ResponsiveSheet>,
|
|
70
|
-
);
|
|
71
|
-
expect(getByLabelText(LABEL, HIDDEN)).toBeTruthy();
|
|
72
|
-
expect(getByLabelText(`Dismiss ${LABEL}`, HIDDEN)).toBeTruthy();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('keeps the panel mounted through the exit transition after closing', () => {
|
|
53
|
+
it('unmounts the body after a controlled close settles', () => {
|
|
76
54
|
jest.useFakeTimers();
|
|
77
55
|
try {
|
|
78
56
|
const { getByText, queryByText, rerender } = renderWithTheme(
|
|
@@ -82,23 +60,29 @@ describe('ResponsiveSheet', () => {
|
|
|
82
60
|
);
|
|
83
61
|
expect(getByText('Sheet body')).toBeTruthy();
|
|
84
62
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
</BloomThemeProvider>,
|
|
63
|
+
rerenderWithTheme(
|
|
64
|
+
rerender,
|
|
65
|
+
<ResponsiveSheet open={false} onClose={() => {}} label={LABEL}>
|
|
66
|
+
<Text>Sheet body</Text>
|
|
67
|
+
</ResponsiveSheet>,
|
|
91
68
|
);
|
|
92
|
-
// Still mounted immediately after close (exit transition in flight).
|
|
93
|
-
expect(getByText('Sheet body')).toBeTruthy();
|
|
94
69
|
|
|
95
|
-
// After the
|
|
70
|
+
// After the close animation/fallback settles the body is gone.
|
|
96
71
|
act(() => {
|
|
97
|
-
jest.advanceTimersByTime(
|
|
72
|
+
jest.advanceTimersByTime(500);
|
|
98
73
|
});
|
|
99
74
|
expect(queryByText('Sheet body')).toBeNull();
|
|
100
75
|
} finally {
|
|
101
76
|
jest.useRealTimers();
|
|
102
77
|
}
|
|
103
78
|
});
|
|
79
|
+
|
|
80
|
+
it('forwards a custom label to the dialog surface', () => {
|
|
81
|
+
const { getByLabelText } = renderWithTheme(
|
|
82
|
+
<ResponsiveSheet open onClose={() => {}} label={LABEL}>
|
|
83
|
+
<Text>Sheet body</Text>
|
|
84
|
+
</ResponsiveSheet>,
|
|
85
|
+
);
|
|
86
|
+
expect(getByLabelText(LABEL)).toBeTruthy();
|
|
87
|
+
});
|
|
104
88
|
});
|
|
@@ -26,6 +26,8 @@ const CLOSE_HIT_SLOP = { top: 8, bottom: 8, left: 8, right: 8 } as const;
|
|
|
26
26
|
export const CENTERED_DIALOG_BACKDROP_TESTID = 'bloom-centered-dialog-backdrop';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
+
* @deprecated Use `<Dialog placement="center">` instead.
|
|
30
|
+
*
|
|
29
31
|
* Native variant of `<CenteredDialog>`.
|
|
30
32
|
*
|
|
31
33
|
* A controlled, centered modal: a transparent RN `Modal` (fade animation,
|
|
@@ -27,6 +27,8 @@ export const CENTERED_DIALOG_BACKDROP_TESTID = 'bloom-centered-dialog-backdrop';
|
|
|
27
27
|
const stopPropagation = (e: { stopPropagation: () => void }) => e.stopPropagation();
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
+
* @deprecated Use `<Dialog placement="center">` instead.
|
|
31
|
+
*
|
|
30
32
|
* Web variant of `<CenteredDialog>`.
|
|
31
33
|
*
|
|
32
34
|
* A centered modal card rendered into the Bloom Portal at the end of
|