@oxyhq/bloom 0.15.0 → 0.16.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/alert-dialog/AlertDialog.js +35 -27
- package/lib/commonjs/alert-dialog/AlertDialog.js.map +1 -1
- package/lib/commonjs/alert-dialog/index.js +1 -1
- package/lib/commonjs/alert-dialog/index.js.map +1 -1
- package/lib/commonjs/alert-dialog/index.web.js +1 -1
- package/lib/commonjs/alert-dialog/index.web.js.map +1 -1
- package/lib/commonjs/command/Command.js +27 -16
- package/lib/commonjs/command/Command.js.map +1 -1
- package/lib/commonjs/command/index.js +1 -1
- package/lib/commonjs/command/index.js.map +1 -1
- package/lib/commonjs/command/index.web.js +1 -1
- package/lib/commonjs/command/index.web.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.js +1 -2
- package/lib/commonjs/dialog/Dialog.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +9 -6
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/dialog/index.js +0 -13
- package/lib/commonjs/dialog/index.js.map +1 -1
- package/lib/commonjs/dialog/index.web.js +0 -19
- package/lib/commonjs/dialog/index.web.js.map +1 -1
- package/lib/commonjs/index.js +0 -29
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +6 -35
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/module/alert-dialog/AlertDialog.js +35 -27
- package/lib/module/alert-dialog/AlertDialog.js.map +1 -1
- package/lib/module/alert-dialog/index.js +2 -2
- package/lib/module/alert-dialog/index.js.map +1 -1
- package/lib/module/alert-dialog/index.web.js +2 -2
- package/lib/module/alert-dialog/index.web.js.map +1 -1
- package/lib/module/command/Command.js +27 -16
- package/lib/module/command/Command.js.map +1 -1
- package/lib/module/command/index.js +2 -2
- package/lib/module/command/index.js.map +1 -1
- package/lib/module/command/index.web.js +2 -2
- package/lib/module/command/index.web.js.map +1 -1
- package/lib/module/dialog/Dialog.js +1 -2
- package/lib/module/dialog/Dialog.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +9 -6
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/dialog/index.js +0 -1
- package/lib/module/dialog/index.js.map +1 -1
- package/lib/module/dialog/index.web.js +0 -1
- package/lib/module/dialog/index.web.js.map +1 -1
- package/lib/module/index.js +1 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +1 -3
- package/lib/module/index.web.js.map +1 -1
- package/lib/typescript/commonjs/alert-dialog/AlertDialog.d.ts +13 -12
- package/lib/typescript/commonjs/alert-dialog/AlertDialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/alert-dialog/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/alert-dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/command/Command.d.ts +8 -8
- package/lib/typescript/commonjs/command/Command.d.ts.map +1 -1
- package/lib/typescript/commonjs/command/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/command/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.d.ts +1 -2
- package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts +2 -2
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/index.d.ts +0 -2
- package/lib/typescript/commonjs/dialog/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/index.web.d.ts +0 -2
- package/lib/typescript/commonjs/dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -4
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +2 -4
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/module/alert-dialog/AlertDialog.d.ts +13 -12
- package/lib/typescript/module/alert-dialog/AlertDialog.d.ts.map +1 -1
- package/lib/typescript/module/alert-dialog/index.d.ts.map +1 -1
- package/lib/typescript/module/alert-dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/module/command/Command.d.ts +8 -8
- package/lib/typescript/module/command/Command.d.ts.map +1 -1
- package/lib/typescript/module/command/index.d.ts.map +1 -1
- package/lib/typescript/module/command/index.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.d.ts +1 -2
- package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts +2 -2
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/index.d.ts +0 -2
- package/lib/typescript/module/dialog/index.d.ts.map +1 -1
- package/lib/typescript/module/dialog/index.web.d.ts +0 -2
- package/lib/typescript/module/dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -4
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +2 -4
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/package.json +1 -18
- package/src/__tests__/AlertDialog.test.tsx +122 -0
- package/src/__tests__/Command.test.tsx +107 -0
- package/src/alert-dialog/AlertDialog.tsx +46 -36
- package/src/alert-dialog/index.ts +2 -2
- package/src/alert-dialog/index.web.ts +2 -2
- package/src/command/Command.tsx +30 -19
- package/src/command/index.ts +2 -2
- package/src/command/index.web.ts +2 -2
- package/src/dialog/Dialog.tsx +1 -2
- package/src/dialog/Dialog.web.tsx +9 -6
- package/src/dialog/index.ts +0 -2
- package/src/dialog/index.web.ts +0 -6
- package/src/index.ts +0 -11
- package/src/index.web.ts +0 -11
- package/lib/commonjs/dialog/CenteredDialog.js +0 -252
- package/lib/commonjs/dialog/CenteredDialog.js.map +0 -1
- package/lib/commonjs/dialog/CenteredDialog.web.js +0 -330
- package/lib/commonjs/dialog/CenteredDialog.web.js.map +0 -1
- package/lib/commonjs/dialog/centered-dialog-tokens.js +0 -62
- package/lib/commonjs/dialog/centered-dialog-tokens.js.map +0 -1
- package/lib/commonjs/dialog/centered-dialog-types.js +0 -6
- package/lib/commonjs/dialog/centered-dialog-types.js.map +0 -1
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.js +0 -97
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.js.map +0 -1
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.web.js +0 -84
- package/lib/commonjs/responsive-sheet/ResponsiveSheet.web.js.map +0 -1
- package/lib/commonjs/responsive-sheet/index.js +0 -19
- package/lib/commonjs/responsive-sheet/index.js.map +0 -1
- package/lib/commonjs/responsive-sheet/index.web.js +0 -19
- package/lib/commonjs/responsive-sheet/index.web.js.map +0 -1
- package/lib/commonjs/responsive-sheet/types.js +0 -6
- package/lib/commonjs/responsive-sheet/types.js.map +0 -1
- package/lib/module/dialog/CenteredDialog.js +0 -246
- package/lib/module/dialog/CenteredDialog.js.map +0 -1
- package/lib/module/dialog/CenteredDialog.web.js +0 -324
- package/lib/module/dialog/CenteredDialog.web.js.map +0 -1
- package/lib/module/dialog/centered-dialog-tokens.js +0 -58
- package/lib/module/dialog/centered-dialog-tokens.js.map +0 -1
- package/lib/module/dialog/centered-dialog-types.js +0 -4
- package/lib/module/dialog/centered-dialog-types.js.map +0 -1
- package/lib/module/responsive-sheet/ResponsiveSheet.js +0 -90
- package/lib/module/responsive-sheet/ResponsiveSheet.js.map +0 -1
- package/lib/module/responsive-sheet/ResponsiveSheet.web.js +0 -77
- package/lib/module/responsive-sheet/ResponsiveSheet.web.js.map +0 -1
- package/lib/module/responsive-sheet/index.js +0 -4
- package/lib/module/responsive-sheet/index.js.map +0 -1
- package/lib/module/responsive-sheet/index.web.js +0 -12
- package/lib/module/responsive-sheet/index.web.js.map +0 -1
- package/lib/module/responsive-sheet/types.js +0 -4
- package/lib/module/responsive-sheet/types.js.map +0 -1
- package/lib/typescript/commonjs/dialog/CenteredDialog.d.ts +0 -22
- package/lib/typescript/commonjs/dialog/CenteredDialog.d.ts.map +0 -1
- package/lib/typescript/commonjs/dialog/CenteredDialog.web.d.ts +0 -31
- package/lib/typescript/commonjs/dialog/CenteredDialog.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/dialog/centered-dialog-tokens.d.ts +0 -47
- package/lib/typescript/commonjs/dialog/centered-dialog-tokens.d.ts.map +0 -1
- package/lib/typescript/commonjs/dialog/centered-dialog-types.d.ts +0 -74
- package/lib/typescript/commonjs/dialog/centered-dialog-types.d.ts.map +0 -1
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.d.ts +0 -22
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.d.ts.map +0 -1
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.web.d.ts +0 -16
- package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/responsive-sheet/index.d.ts +0 -3
- package/lib/typescript/commonjs/responsive-sheet/index.d.ts.map +0 -1
- package/lib/typescript/commonjs/responsive-sheet/index.web.d.ts +0 -3
- package/lib/typescript/commonjs/responsive-sheet/index.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/responsive-sheet/types.d.ts +0 -58
- package/lib/typescript/commonjs/responsive-sheet/types.d.ts.map +0 -1
- package/lib/typescript/module/dialog/CenteredDialog.d.ts +0 -22
- package/lib/typescript/module/dialog/CenteredDialog.d.ts.map +0 -1
- package/lib/typescript/module/dialog/CenteredDialog.web.d.ts +0 -31
- package/lib/typescript/module/dialog/CenteredDialog.web.d.ts.map +0 -1
- package/lib/typescript/module/dialog/centered-dialog-tokens.d.ts +0 -47
- package/lib/typescript/module/dialog/centered-dialog-tokens.d.ts.map +0 -1
- package/lib/typescript/module/dialog/centered-dialog-types.d.ts +0 -74
- package/lib/typescript/module/dialog/centered-dialog-types.d.ts.map +0 -1
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.d.ts +0 -22
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.d.ts.map +0 -1
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.web.d.ts +0 -16
- package/lib/typescript/module/responsive-sheet/ResponsiveSheet.web.d.ts.map +0 -1
- package/lib/typescript/module/responsive-sheet/index.d.ts +0 -3
- package/lib/typescript/module/responsive-sheet/index.d.ts.map +0 -1
- package/lib/typescript/module/responsive-sheet/index.web.d.ts +0 -3
- package/lib/typescript/module/responsive-sheet/index.web.d.ts.map +0 -1
- package/lib/typescript/module/responsive-sheet/types.d.ts +0 -58
- package/lib/typescript/module/responsive-sheet/types.d.ts.map +0 -1
- package/src/__tests__/CenteredDialog.test.tsx +0 -108
- package/src/__tests__/ResponsiveSheet.test.tsx +0 -88
- package/src/dialog/CenteredDialog.stories.tsx +0 -125
- package/src/dialog/CenteredDialog.tsx +0 -305
- package/src/dialog/CenteredDialog.web.tsx +0 -374
- package/src/dialog/centered-dialog-tokens.ts +0 -68
- package/src/dialog/centered-dialog-types.ts +0 -74
- package/src/responsive-sheet/ResponsiveSheet.stories.tsx +0 -54
- package/src/responsive-sheet/ResponsiveSheet.tsx +0 -88
- package/src/responsive-sheet/ResponsiveSheet.web.tsx +0 -76
- package/src/responsive-sheet/index.ts +0 -6
- package/src/responsive-sheet/index.web.ts +0 -14
- package/src/responsive-sheet/types.ts +0 -60
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { act, fireEvent, render } from '@testing-library/react-native';
|
|
3
|
+
|
|
4
|
+
import { Command } from '../command';
|
|
5
|
+
import type { CommandItem } from '../command';
|
|
6
|
+
import { BloomThemeProvider } from '../theme/BloomThemeProvider';
|
|
7
|
+
|
|
8
|
+
function renderWithTheme(ui: React.ReactElement) {
|
|
9
|
+
return render(
|
|
10
|
+
<BloomThemeProvider mode="light" colorPreset="teal">
|
|
11
|
+
{ui}
|
|
12
|
+
</BloomThemeProvider>,
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function makeItems(onSelect: () => void): CommandItem[] {
|
|
17
|
+
return [
|
|
18
|
+
{ id: 'profile', label: 'Go to profile', group: 'Navigation', onSelect },
|
|
19
|
+
{ id: 'settings', label: 'Open settings', group: 'Navigation', onSelect },
|
|
20
|
+
{
|
|
21
|
+
id: 'new-app',
|
|
22
|
+
label: 'Create application',
|
|
23
|
+
description: 'Register a new OAuth client',
|
|
24
|
+
group: 'Actions',
|
|
25
|
+
keywords: ['oauth', 'client'],
|
|
26
|
+
onSelect,
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// `Command` is now a ⌘K palette built on `<Dialog placement="center">`. These
|
|
32
|
+
// tests assert the public-API contract it owns (controlled visibility, the
|
|
33
|
+
// grouped results list, query filtering, the empty state, and select →
|
|
34
|
+
// onClose) holds on the native Dialog surface.
|
|
35
|
+
describe('Command (built on Dialog)', () => {
|
|
36
|
+
it('renders nothing when not visible', () => {
|
|
37
|
+
const { queryByText } = renderWithTheme(
|
|
38
|
+
<Command visible={false} onClose={() => {}} items={makeItems(() => {})} />,
|
|
39
|
+
);
|
|
40
|
+
expect(queryByText('Go to profile')).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('renders grouped items and their group headers when visible', () => {
|
|
44
|
+
const { getByText } = renderWithTheme(
|
|
45
|
+
<Command visible onClose={() => {}} items={makeItems(() => {})} />,
|
|
46
|
+
);
|
|
47
|
+
expect(getByText('Go to profile')).toBeTruthy();
|
|
48
|
+
expect(getByText('Open settings')).toBeTruthy();
|
|
49
|
+
expect(getByText('Create application')).toBeTruthy();
|
|
50
|
+
// Group headers are rendered above their items.
|
|
51
|
+
expect(getByText('Navigation')).toBeTruthy();
|
|
52
|
+
expect(getByText('Actions')).toBeTruthy();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('filters items by a controlled query (label, description, keywords)', () => {
|
|
56
|
+
const { getByText, queryByText, rerender } = renderWithTheme(
|
|
57
|
+
<Command
|
|
58
|
+
visible
|
|
59
|
+
onClose={() => {}}
|
|
60
|
+
items={makeItems(() => {})}
|
|
61
|
+
query="settings"
|
|
62
|
+
/>,
|
|
63
|
+
);
|
|
64
|
+
expect(getByText('Open settings')).toBeTruthy();
|
|
65
|
+
expect(queryByText('Go to profile')).toBeNull();
|
|
66
|
+
|
|
67
|
+
// A keyword on a different item matches that item.
|
|
68
|
+
rerender(
|
|
69
|
+
<BloomThemeProvider mode="light" colorPreset="teal">
|
|
70
|
+
<Command
|
|
71
|
+
visible
|
|
72
|
+
onClose={() => {}}
|
|
73
|
+
items={makeItems(() => {})}
|
|
74
|
+
query="oauth"
|
|
75
|
+
/>
|
|
76
|
+
</BloomThemeProvider>,
|
|
77
|
+
);
|
|
78
|
+
expect(getByText('Create application')).toBeTruthy();
|
|
79
|
+
expect(queryByText('Open settings')).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('shows the empty state when nothing matches', () => {
|
|
83
|
+
const { getByText } = renderWithTheme(
|
|
84
|
+
<Command
|
|
85
|
+
visible
|
|
86
|
+
onClose={() => {}}
|
|
87
|
+
items={makeItems(() => {})}
|
|
88
|
+
query="zzz-no-match"
|
|
89
|
+
emptyText="Nothing here"
|
|
90
|
+
/>,
|
|
91
|
+
);
|
|
92
|
+
expect(getByText('Nothing here')).toBeTruthy();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('invokes onSelect then onClose when an item is pressed', () => {
|
|
96
|
+
const onSelect = jest.fn();
|
|
97
|
+
const onClose = jest.fn();
|
|
98
|
+
const { getByText } = renderWithTheme(
|
|
99
|
+
<Command visible onClose={onClose} items={makeItems(onSelect)} />,
|
|
100
|
+
);
|
|
101
|
+
act(() => {
|
|
102
|
+
fireEvent.press(getByText('Open settings'));
|
|
103
|
+
});
|
|
104
|
+
expect(onSelect).toHaveBeenCalledTimes(1);
|
|
105
|
+
expect(onClose).toHaveBeenCalledTimes(1);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -2,28 +2,32 @@ import React, { memo, useCallback } from 'react';
|
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { Button } from '../button';
|
|
5
|
+
import type { DialogProps } from '../dialog';
|
|
5
6
|
import { useTheme } from '../theme/use-theme';
|
|
6
7
|
import { Text } from '../typography';
|
|
7
8
|
import { fontSize, space } from '../styles/tokens';
|
|
8
|
-
import type { CenteredDialogProps } from '../dialog';
|
|
9
9
|
import type { AlertDialogProps } from './types';
|
|
10
10
|
|
|
11
|
-
type
|
|
11
|
+
type DialogComponent = React.ComponentType<DialogProps>;
|
|
12
|
+
|
|
13
|
+
/** Centered alert-card max width (px). Matches the legacy AlertDialog card. */
|
|
14
|
+
const ALERT_DIALOG_MAX_WIDTH = 440;
|
|
12
15
|
|
|
13
16
|
/**
|
|
14
|
-
* Build the `AlertDialog` component bound to a platform `
|
|
17
|
+
* Build the `AlertDialog` component bound to a platform `Dialog`.
|
|
15
18
|
*
|
|
16
|
-
* `
|
|
17
|
-
* overlay), and this repo never
|
|
18
|
-
*
|
|
19
|
-
* `
|
|
19
|
+
* `Dialog` is platform-forked (native `BottomSheet`-backed surface vs pure-DOM
|
|
20
|
+
* web overlay) through its `./dialog` export conditions, and this repo never
|
|
21
|
+
* relies on implicit `.web` resolution — the platform entry files
|
|
22
|
+
* (`index.ts` / `index.web.ts`) inject the correct `Dialog` here. The body
|
|
23
|
+
* below is single-source, no duplication.
|
|
20
24
|
*
|
|
21
|
-
* `AlertDialog` is a thin wrapper over
|
|
22
|
-
* description and a confirm/cancel action row. Reach for the
|
|
23
|
-
* `confirm()` helper + `<AlertDialogHost />` to trigger a confirm
|
|
24
|
-
* event handler without owning visible state.
|
|
25
|
+
* `AlertDialog` is a thin wrapper over `<Dialog placement="center">` that lays
|
|
26
|
+
* out a title, description and a confirm/cancel action row. Reach for the
|
|
27
|
+
* imperative `confirm()` helper + `<AlertDialogHost />` to trigger a confirm
|
|
28
|
+
* from an event handler without owning visible state.
|
|
25
29
|
*/
|
|
26
|
-
export function createAlertDialog(
|
|
30
|
+
export function createAlertDialog(Dialog: DialogComponent) {
|
|
27
31
|
const AlertDialogComponent = function AlertDialog({
|
|
28
32
|
visible,
|
|
29
33
|
onClose,
|
|
@@ -52,16 +56,31 @@ export function createAlertDialog(CenteredDialog: CenteredDialogComponent) {
|
|
|
52
56
|
}, [onConfirm, onClose]);
|
|
53
57
|
|
|
54
58
|
return (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
<Dialog
|
|
60
|
+
open={visible}
|
|
61
|
+
onClose={onClose}
|
|
62
|
+
placement="center"
|
|
63
|
+
// Alert dialogs are blocking by default — the backdrop only dismisses
|
|
64
|
+
// when the caller opts in via `dismissible`.
|
|
65
|
+
dismissOnBackdrop={dismissible}
|
|
66
|
+
maxWidth={ALERT_DIALOG_MAX_WIDTH}
|
|
67
|
+
title={title}
|
|
68
|
+
label={title}
|
|
69
|
+
style={cardStyle}
|
|
70
|
+
testID={testID}
|
|
71
|
+
>
|
|
72
|
+
{description ? (
|
|
73
|
+
<Text
|
|
74
|
+
style={{
|
|
75
|
+
fontSize: fontSize.md,
|
|
76
|
+
lineHeight: fontSize.md * 1.4,
|
|
77
|
+
color: theme.colors.textSecondary,
|
|
78
|
+
paddingBottom: space.lg,
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
{description}
|
|
82
|
+
</Text>
|
|
83
|
+
) : null}
|
|
65
84
|
<View style={styles.actions}>
|
|
66
85
|
{!hideCancel ? (
|
|
67
86
|
<Button
|
|
@@ -69,7 +88,8 @@ export function createAlertDialog(CenteredDialog: CenteredDialogComponent) {
|
|
|
69
88
|
size="medium"
|
|
70
89
|
onPress={handleCancel}
|
|
71
90
|
style={styles.action}
|
|
72
|
-
accessibilityLabel={cancelLabel}
|
|
91
|
+
accessibilityLabel={cancelLabel}
|
|
92
|
+
>
|
|
73
93
|
{cancelLabel}
|
|
74
94
|
</Button>
|
|
75
95
|
) : null}
|
|
@@ -82,22 +102,12 @@ export function createAlertDialog(CenteredDialog: CenteredDialogComponent) {
|
|
|
82
102
|
destructive && { backgroundColor: theme.colors.negative },
|
|
83
103
|
]}
|
|
84
104
|
textStyle={destructive ? { color: theme.colors.negativeForeground } : undefined}
|
|
85
|
-
accessibilityLabel={confirmLabel}
|
|
105
|
+
accessibilityLabel={confirmLabel}
|
|
106
|
+
>
|
|
86
107
|
{confirmLabel}
|
|
87
108
|
</Button>
|
|
88
109
|
</View>
|
|
89
|
-
|
|
90
|
-
{description ? (
|
|
91
|
-
<Text
|
|
92
|
-
style={{
|
|
93
|
-
fontSize: fontSize.md,
|
|
94
|
-
lineHeight: fontSize.md * 1.4,
|
|
95
|
-
color: theme.colors.textSecondary,
|
|
96
|
-
}}>
|
|
97
|
-
{description}
|
|
98
|
-
</Text>
|
|
99
|
-
) : null}
|
|
100
|
-
</CenteredDialog>
|
|
110
|
+
</Dialog>
|
|
101
111
|
);
|
|
102
112
|
};
|
|
103
113
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dialog } from '../dialog/index';
|
|
2
2
|
import { createAlertDialog } from './AlertDialog';
|
|
3
3
|
import { createAlertDialogHost } from './AlertDialogHost';
|
|
4
4
|
|
|
5
|
-
export const AlertDialog = createAlertDialog(
|
|
5
|
+
export const AlertDialog = createAlertDialog(Dialog);
|
|
6
6
|
export const AlertDialogHost = createAlertDialogHost(AlertDialog);
|
|
7
7
|
|
|
8
8
|
export { confirm } from './confirm-store';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dialog } from '../dialog/index.web';
|
|
2
2
|
import { createAlertDialog } from './AlertDialog';
|
|
3
3
|
import { createAlertDialogHost } from './AlertDialogHost';
|
|
4
4
|
|
|
5
|
-
export const AlertDialog = createAlertDialog(
|
|
5
|
+
export const AlertDialog = createAlertDialog(Dialog);
|
|
6
6
|
export const AlertDialogHost = createAlertDialogHost(AlertDialog);
|
|
7
7
|
|
|
8
8
|
export { confirm } from './confirm-store';
|
package/src/command/Command.tsx
CHANGED
|
@@ -14,10 +14,13 @@ import { Item } from '../item';
|
|
|
14
14
|
import { Kbd } from '../kbd';
|
|
15
15
|
import { SearchInput } from '../search-input';
|
|
16
16
|
import { fontSize, space } from '../styles/tokens';
|
|
17
|
-
import type {
|
|
17
|
+
import type { DialogProps } from '../dialog';
|
|
18
18
|
import type { CommandItem, CommandProps } from './types';
|
|
19
19
|
|
|
20
|
-
type
|
|
20
|
+
type DialogComponent = React.ComponentType<DialogProps>;
|
|
21
|
+
|
|
22
|
+
/** Centered command-palette max width (px). Matches the legacy palette card. */
|
|
23
|
+
const COMMAND_MAX_WIDTH = 560;
|
|
21
24
|
|
|
22
25
|
function defaultFilter(item: CommandItem, query: string): boolean {
|
|
23
26
|
const q = query.trim().toLowerCase();
|
|
@@ -36,17 +39,17 @@ interface FlatEntry {
|
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/**
|
|
39
|
-
* Build the `Command` palette bound to a platform `
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* implicit `.web` resolution. The body is single-source.
|
|
42
|
+
* Build the `Command` palette bound to a platform `Dialog`. The platform entry
|
|
43
|
+
* files (`index.ts` / `index.web.ts`) inject the correct one (native
|
|
44
|
+
* `BottomSheet`-backed surface vs pure-DOM web overlay) — this repo never
|
|
45
|
+
* relies on implicit `.web` resolution. The body is single-source.
|
|
43
46
|
*
|
|
44
|
-
* `Command` is a ⌘K command palette built on
|
|
47
|
+
* `Command` is a ⌘K command palette built on `<Dialog placement="center">`,
|
|
45
48
|
* `SearchInput`, an `Item` results list and `Kbd` shortcut hints. Items group
|
|
46
49
|
* by their `group` field (ungrouped first). On web the list is
|
|
47
50
|
* keyboard-navigable (Up/Down/Enter); on native, tap to select.
|
|
48
51
|
*/
|
|
49
|
-
export function createCommand(
|
|
52
|
+
export function createCommand(Dialog: DialogComponent) {
|
|
50
53
|
const Command = function Command({
|
|
51
54
|
visible,
|
|
52
55
|
onClose,
|
|
@@ -168,15 +171,16 @@ export function createCommand(CenteredDialog: CenteredDialogComponent) {
|
|
|
168
171
|
: {};
|
|
169
172
|
|
|
170
173
|
return (
|
|
171
|
-
<
|
|
172
|
-
|
|
174
|
+
<Dialog
|
|
175
|
+
open={visible}
|
|
173
176
|
onClose={onClose}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
maxWidth={
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
placement="center"
|
|
178
|
+
dismissOnBackdrop
|
|
179
|
+
maxWidth={COMMAND_MAX_WIDTH}
|
|
180
|
+
label="Command palette"
|
|
181
|
+
// The palette owns its own edge-to-edge layout (full-bleed search border,
|
|
182
|
+
// padded results) so the Dialog panel contributes no padding of its own.
|
|
183
|
+
style={[styles.panel, style]}
|
|
180
184
|
testID={testID}>
|
|
181
185
|
<View {...webKeyHandler}>
|
|
182
186
|
<View style={[styles.searchWrap, { borderBottomColor: theme.colors.borderLight }]}>
|
|
@@ -200,6 +204,7 @@ export function createCommand(CenteredDialog: CenteredDialogComponent) {
|
|
|
200
204
|
) : (
|
|
201
205
|
<ScrollView
|
|
202
206
|
style={{ maxHeight: maxListHeight }}
|
|
207
|
+
contentContainerStyle={styles.list}
|
|
203
208
|
keyboardShouldPersistTaps="handled"
|
|
204
209
|
showsVerticalScrollIndicator={false}>
|
|
205
210
|
{entries.map((entry, i) => {
|
|
@@ -238,7 +243,7 @@ export function createCommand(CenteredDialog: CenteredDialogComponent) {
|
|
|
238
243
|
</ScrollView>
|
|
239
244
|
)}
|
|
240
245
|
</View>
|
|
241
|
-
</
|
|
246
|
+
</Dialog>
|
|
242
247
|
);
|
|
243
248
|
};
|
|
244
249
|
|
|
@@ -249,9 +254,15 @@ export function createCommand(CenteredDialog: CenteredDialogComponent) {
|
|
|
249
254
|
export type CommandType = ReturnType<typeof createCommand>;
|
|
250
255
|
|
|
251
256
|
const styles = StyleSheet.create({
|
|
252
|
-
|
|
253
|
-
|
|
257
|
+
// Zero out the Dialog panel's default padding (longhands beat the web
|
|
258
|
+
// panel's `padding` shorthand and the native panel's longhand paddings) so
|
|
259
|
+
// the palette renders edge-to-edge.
|
|
260
|
+
panel: {
|
|
254
261
|
paddingTop: 0,
|
|
262
|
+
paddingHorizontal: 0,
|
|
263
|
+
paddingBottom: space.xs,
|
|
264
|
+
},
|
|
265
|
+
list: {
|
|
255
266
|
paddingBottom: space.xs,
|
|
256
267
|
},
|
|
257
268
|
searchWrap: {
|
package/src/command/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dialog } from '../dialog/index';
|
|
2
2
|
import { createCommand } from './Command';
|
|
3
3
|
|
|
4
|
-
export const Command = createCommand(
|
|
4
|
+
export const Command = createCommand(Dialog);
|
|
5
5
|
|
|
6
6
|
export type { CommandProps, CommandItem } from './types';
|
package/src/command/index.web.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dialog } from '../dialog/index.web';
|
|
2
2
|
import { createCommand } from './Command';
|
|
3
3
|
|
|
4
|
-
export const Command = createCommand(
|
|
4
|
+
export const Command = createCommand(Dialog);
|
|
5
5
|
|
|
6
6
|
export type { CommandProps, CommandItem } from './types';
|
package/src/dialog/Dialog.tsx
CHANGED
|
@@ -65,8 +65,7 @@ export { DIALOG_SHEET_BACKDROP_TESTID };
|
|
|
65
65
|
* centered card via the 500px cap; flush for bottom: a full-width sheet
|
|
66
66
|
* with a drag handle). Default behavior is unchanged.
|
|
67
67
|
* - `'left'` / `'right'` — an anchored side-sheet/drawer driven by
|
|
68
|
-
* reanimated
|
|
69
|
-
* are safe on native.
|
|
68
|
+
* reanimated. Exit animations are safe on native.
|
|
70
69
|
*
|
|
71
70
|
* The component accepts three rendering modes simultaneously:
|
|
72
71
|
*
|
|
@@ -75,8 +75,8 @@ const ClosingContext = createContext(false);
|
|
|
75
75
|
*
|
|
76
76
|
* Web motion never uses reanimated `exiting` (which throws `removeChild` on
|
|
77
77
|
* concurrent React unmounts): the centered card uses CSS keyframes and the
|
|
78
|
-
* side/bottom modes use self-contained CSS transitions
|
|
79
|
-
*
|
|
78
|
+
* side/bottom modes use self-contained CSS transitions on a
|
|
79
|
+
* mounted-through-exit node.
|
|
80
80
|
*/
|
|
81
81
|
export function Dialog({
|
|
82
82
|
control,
|
|
@@ -184,9 +184,12 @@ export function Dialog({
|
|
|
184
184
|
|
|
185
185
|
// Escape-to-close while open. The listener is intentionally scoped to the
|
|
186
186
|
// open lifetime so stacked dialogs don't fight for the keydown — the
|
|
187
|
-
// top-most one wins via document-level event order.
|
|
187
|
+
// top-most one wins via document-level event order. Escape honors
|
|
188
|
+
// `dismissOnBackdrop`: a blocking dialog (e.g. an unanswered confirm) is not
|
|
189
|
+
// dismissible by Escape, matching the backdrop's behavior. The default
|
|
190
|
+
// (`dismissOnBackdrop` true) is unchanged — Escape still closes.
|
|
188
191
|
useEffect(() => {
|
|
189
|
-
if (!isOpen || typeof document === 'undefined') return;
|
|
192
|
+
if (!isOpen || !dismissOnBackdrop || typeof document === 'undefined') return;
|
|
190
193
|
const handler = (e: KeyboardEvent) => {
|
|
191
194
|
if (e.key === 'Escape') {
|
|
192
195
|
e.stopPropagation();
|
|
@@ -195,7 +198,7 @@ export function Dialog({
|
|
|
195
198
|
};
|
|
196
199
|
document.addEventListener('keydown', handler);
|
|
197
200
|
return () => document.removeEventListener('keydown', handler);
|
|
198
|
-
}, [close, isOpen]);
|
|
201
|
+
}, [close, dismissOnBackdrop, isOpen]);
|
|
199
202
|
|
|
200
203
|
useImperativeHandle(
|
|
201
204
|
control?.ref,
|
|
@@ -420,7 +423,7 @@ export { DIALOG_SHEET_BACKDROP_TESTID };
|
|
|
420
423
|
|
|
421
424
|
/**
|
|
422
425
|
* Side-sheet / bottom-sheet surface for the `left`/`right`/`bottom`
|
|
423
|
-
* placements. Pure CSS transitions
|
|
426
|
+
* placements. Pure CSS transitions: the
|
|
424
427
|
* node stays mounted through the exit while a `shown` flag drives the
|
|
425
428
|
* transform/opacity, so both directions animate without reanimated `exiting`.
|
|
426
429
|
*/
|
package/src/dialog/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { Dialog, DIALOG_SHEET_BACKDROP_TESTID } from './Dialog';
|
|
2
|
-
export { CenteredDialog, CENTERED_DIALOG_BACKDROP_TESTID } from './CenteredDialog';
|
|
3
2
|
export { BloomDialogProvider } from './BloomDialogProvider';
|
|
4
3
|
export { alert } from './alert';
|
|
5
4
|
export { useDialogContext, useDialogControl } from './context';
|
|
@@ -17,4 +16,3 @@ export type {
|
|
|
17
16
|
DialogProps,
|
|
18
17
|
ResponsiveDialogPlacement,
|
|
19
18
|
} from './types';
|
|
20
|
-
export type { CenteredDialogProps } from './centered-dialog-types';
|
package/src/dialog/index.web.ts
CHANGED
|
@@ -9,11 +9,6 @@
|
|
|
9
9
|
// `package.json`'s `exports['./dialog']`; native bundlers fall through to
|
|
10
10
|
// the React Native build above.
|
|
11
11
|
export { Dialog, BLOOM_DIALOG_CSS, DIALOG_SHEET_BACKDROP_TESTID } from './Dialog.web';
|
|
12
|
-
export {
|
|
13
|
-
CenteredDialog,
|
|
14
|
-
BLOOM_CENTERED_DIALOG_CSS,
|
|
15
|
-
CENTERED_DIALOG_BACKDROP_TESTID,
|
|
16
|
-
} from './CenteredDialog.web';
|
|
17
12
|
export { BloomDialogProvider } from './BloomDialogProvider.web';
|
|
18
13
|
export { alert } from './alert';
|
|
19
14
|
export { useDialogContext, useDialogControl } from './context';
|
|
@@ -31,4 +26,3 @@ export type {
|
|
|
31
26
|
DialogProps,
|
|
32
27
|
ResponsiveDialogPlacement,
|
|
33
28
|
} from './types';
|
|
34
|
-
export type { CenteredDialogProps } from './centered-dialog-types';
|
package/src/index.ts
CHANGED
|
@@ -21,8 +21,6 @@ export * from './portal';
|
|
|
21
21
|
export {
|
|
22
22
|
Dialog,
|
|
23
23
|
DIALOG_SHEET_BACKDROP_TESTID,
|
|
24
|
-
CenteredDialog,
|
|
25
|
-
CENTERED_DIALOG_BACKDROP_TESTID,
|
|
26
24
|
BloomDialogProvider,
|
|
27
25
|
alert,
|
|
28
26
|
useDialogContext,
|
|
@@ -31,7 +29,6 @@ export {
|
|
|
31
29
|
export type {
|
|
32
30
|
AlertButton,
|
|
33
31
|
AlertButtonStyle,
|
|
34
|
-
CenteredDialogProps,
|
|
35
32
|
DialogAction,
|
|
36
33
|
DialogActionColor,
|
|
37
34
|
DialogContextProps,
|
|
@@ -92,14 +89,6 @@ export type { ComboboxProps, ComboboxOption } from './combobox';
|
|
|
92
89
|
export { BottomSheet } from './bottom-sheet';
|
|
93
90
|
export type { BottomSheetRef, BottomSheetProps } from './bottom-sheet';
|
|
94
91
|
|
|
95
|
-
// Responsive sheet — side-sheet on wide screens, bottom-sheet on narrow.
|
|
96
|
-
export { ResponsiveSheet, RESPONSIVE_SHEET_BACKDROP_TESTID } from './responsive-sheet';
|
|
97
|
-
export type {
|
|
98
|
-
ResponsiveSheetProps,
|
|
99
|
-
ResponsiveSheetSide,
|
|
100
|
-
ResponsiveSheetInset,
|
|
101
|
-
} from './responsive-sheet';
|
|
102
|
-
|
|
103
92
|
// Data display
|
|
104
93
|
export * from './card';
|
|
105
94
|
export * from './badge';
|
package/src/index.web.ts
CHANGED
|
@@ -26,8 +26,6 @@ export * from './portal/index.web';
|
|
|
26
26
|
export {
|
|
27
27
|
Dialog,
|
|
28
28
|
DIALOG_SHEET_BACKDROP_TESTID,
|
|
29
|
-
CenteredDialog,
|
|
30
|
-
CENTERED_DIALOG_BACKDROP_TESTID,
|
|
31
29
|
BloomDialogProvider,
|
|
32
30
|
alert,
|
|
33
31
|
useDialogContext,
|
|
@@ -36,7 +34,6 @@ export {
|
|
|
36
34
|
export type {
|
|
37
35
|
AlertButton,
|
|
38
36
|
AlertButtonStyle,
|
|
39
|
-
CenteredDialogProps,
|
|
40
37
|
DialogAction,
|
|
41
38
|
DialogActionColor,
|
|
42
39
|
DialogContextProps,
|
|
@@ -97,14 +94,6 @@ export type { ComboboxProps, ComboboxOption } from './combobox/index.web';
|
|
|
97
94
|
export { BottomSheet } from './bottom-sheet';
|
|
98
95
|
export type { BottomSheetRef, BottomSheetProps } from './bottom-sheet';
|
|
99
96
|
|
|
100
|
-
// Responsive sheet — side-sheet on wide screens, bottom-sheet on narrow.
|
|
101
|
-
export { ResponsiveSheet, RESPONSIVE_SHEET_BACKDROP_TESTID } from './responsive-sheet/index.web';
|
|
102
|
-
export type {
|
|
103
|
-
ResponsiveSheetProps,
|
|
104
|
-
ResponsiveSheetSide,
|
|
105
|
-
ResponsiveSheetInset,
|
|
106
|
-
} from './responsive-sheet/index.web';
|
|
107
|
-
|
|
108
97
|
// Data display
|
|
109
98
|
export * from './card';
|
|
110
99
|
export * from './badge';
|