@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.
Files changed (188) hide show
  1. package/lib/commonjs/alert-dialog/AlertDialog.js +35 -27
  2. package/lib/commonjs/alert-dialog/AlertDialog.js.map +1 -1
  3. package/lib/commonjs/alert-dialog/index.js +1 -1
  4. package/lib/commonjs/alert-dialog/index.js.map +1 -1
  5. package/lib/commonjs/alert-dialog/index.web.js +1 -1
  6. package/lib/commonjs/alert-dialog/index.web.js.map +1 -1
  7. package/lib/commonjs/command/Command.js +27 -16
  8. package/lib/commonjs/command/Command.js.map +1 -1
  9. package/lib/commonjs/command/index.js +1 -1
  10. package/lib/commonjs/command/index.js.map +1 -1
  11. package/lib/commonjs/command/index.web.js +1 -1
  12. package/lib/commonjs/command/index.web.js.map +1 -1
  13. package/lib/commonjs/dialog/Dialog.js +1 -2
  14. package/lib/commonjs/dialog/Dialog.js.map +1 -1
  15. package/lib/commonjs/dialog/Dialog.web.js +9 -6
  16. package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
  17. package/lib/commonjs/dialog/index.js +0 -13
  18. package/lib/commonjs/dialog/index.js.map +1 -1
  19. package/lib/commonjs/dialog/index.web.js +0 -19
  20. package/lib/commonjs/dialog/index.web.js.map +1 -1
  21. package/lib/commonjs/index.js +0 -29
  22. package/lib/commonjs/index.js.map +1 -1
  23. package/lib/commonjs/index.web.js +6 -35
  24. package/lib/commonjs/index.web.js.map +1 -1
  25. package/lib/module/alert-dialog/AlertDialog.js +35 -27
  26. package/lib/module/alert-dialog/AlertDialog.js.map +1 -1
  27. package/lib/module/alert-dialog/index.js +2 -2
  28. package/lib/module/alert-dialog/index.js.map +1 -1
  29. package/lib/module/alert-dialog/index.web.js +2 -2
  30. package/lib/module/alert-dialog/index.web.js.map +1 -1
  31. package/lib/module/command/Command.js +27 -16
  32. package/lib/module/command/Command.js.map +1 -1
  33. package/lib/module/command/index.js +2 -2
  34. package/lib/module/command/index.js.map +1 -1
  35. package/lib/module/command/index.web.js +2 -2
  36. package/lib/module/command/index.web.js.map +1 -1
  37. package/lib/module/dialog/Dialog.js +1 -2
  38. package/lib/module/dialog/Dialog.js.map +1 -1
  39. package/lib/module/dialog/Dialog.web.js +9 -6
  40. package/lib/module/dialog/Dialog.web.js.map +1 -1
  41. package/lib/module/dialog/index.js +0 -1
  42. package/lib/module/dialog/index.js.map +1 -1
  43. package/lib/module/dialog/index.web.js +0 -1
  44. package/lib/module/dialog/index.web.js.map +1 -1
  45. package/lib/module/index.js +1 -3
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/index.web.js +1 -3
  48. package/lib/module/index.web.js.map +1 -1
  49. package/lib/typescript/commonjs/alert-dialog/AlertDialog.d.ts +13 -12
  50. package/lib/typescript/commonjs/alert-dialog/AlertDialog.d.ts.map +1 -1
  51. package/lib/typescript/commonjs/alert-dialog/index.d.ts.map +1 -1
  52. package/lib/typescript/commonjs/alert-dialog/index.web.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/command/Command.d.ts +8 -8
  54. package/lib/typescript/commonjs/command/Command.d.ts.map +1 -1
  55. package/lib/typescript/commonjs/command/index.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/command/index.web.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/dialog/Dialog.d.ts +1 -2
  58. package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
  59. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts +2 -2
  60. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/dialog/index.d.ts +0 -2
  62. package/lib/typescript/commonjs/dialog/index.d.ts.map +1 -1
  63. package/lib/typescript/commonjs/dialog/index.web.d.ts +0 -2
  64. package/lib/typescript/commonjs/dialog/index.web.d.ts.map +1 -1
  65. package/lib/typescript/commonjs/index.d.ts +2 -4
  66. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  67. package/lib/typescript/commonjs/index.web.d.ts +2 -4
  68. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  69. package/lib/typescript/module/alert-dialog/AlertDialog.d.ts +13 -12
  70. package/lib/typescript/module/alert-dialog/AlertDialog.d.ts.map +1 -1
  71. package/lib/typescript/module/alert-dialog/index.d.ts.map +1 -1
  72. package/lib/typescript/module/alert-dialog/index.web.d.ts.map +1 -1
  73. package/lib/typescript/module/command/Command.d.ts +8 -8
  74. package/lib/typescript/module/command/Command.d.ts.map +1 -1
  75. package/lib/typescript/module/command/index.d.ts.map +1 -1
  76. package/lib/typescript/module/command/index.web.d.ts.map +1 -1
  77. package/lib/typescript/module/dialog/Dialog.d.ts +1 -2
  78. package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
  79. package/lib/typescript/module/dialog/Dialog.web.d.ts +2 -2
  80. package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
  81. package/lib/typescript/module/dialog/index.d.ts +0 -2
  82. package/lib/typescript/module/dialog/index.d.ts.map +1 -1
  83. package/lib/typescript/module/dialog/index.web.d.ts +0 -2
  84. package/lib/typescript/module/dialog/index.web.d.ts.map +1 -1
  85. package/lib/typescript/module/index.d.ts +2 -4
  86. package/lib/typescript/module/index.d.ts.map +1 -1
  87. package/lib/typescript/module/index.web.d.ts +2 -4
  88. package/lib/typescript/module/index.web.d.ts.map +1 -1
  89. package/package.json +1 -18
  90. package/src/__tests__/AlertDialog.test.tsx +122 -0
  91. package/src/__tests__/Command.test.tsx +107 -0
  92. package/src/alert-dialog/AlertDialog.tsx +46 -36
  93. package/src/alert-dialog/index.ts +2 -2
  94. package/src/alert-dialog/index.web.ts +2 -2
  95. package/src/command/Command.tsx +30 -19
  96. package/src/command/index.ts +2 -2
  97. package/src/command/index.web.ts +2 -2
  98. package/src/dialog/Dialog.tsx +1 -2
  99. package/src/dialog/Dialog.web.tsx +9 -6
  100. package/src/dialog/index.ts +0 -2
  101. package/src/dialog/index.web.ts +0 -6
  102. package/src/index.ts +0 -11
  103. package/src/index.web.ts +0 -11
  104. package/lib/commonjs/dialog/CenteredDialog.js +0 -252
  105. package/lib/commonjs/dialog/CenteredDialog.js.map +0 -1
  106. package/lib/commonjs/dialog/CenteredDialog.web.js +0 -330
  107. package/lib/commonjs/dialog/CenteredDialog.web.js.map +0 -1
  108. package/lib/commonjs/dialog/centered-dialog-tokens.js +0 -62
  109. package/lib/commonjs/dialog/centered-dialog-tokens.js.map +0 -1
  110. package/lib/commonjs/dialog/centered-dialog-types.js +0 -6
  111. package/lib/commonjs/dialog/centered-dialog-types.js.map +0 -1
  112. package/lib/commonjs/responsive-sheet/ResponsiveSheet.js +0 -97
  113. package/lib/commonjs/responsive-sheet/ResponsiveSheet.js.map +0 -1
  114. package/lib/commonjs/responsive-sheet/ResponsiveSheet.web.js +0 -84
  115. package/lib/commonjs/responsive-sheet/ResponsiveSheet.web.js.map +0 -1
  116. package/lib/commonjs/responsive-sheet/index.js +0 -19
  117. package/lib/commonjs/responsive-sheet/index.js.map +0 -1
  118. package/lib/commonjs/responsive-sheet/index.web.js +0 -19
  119. package/lib/commonjs/responsive-sheet/index.web.js.map +0 -1
  120. package/lib/commonjs/responsive-sheet/types.js +0 -6
  121. package/lib/commonjs/responsive-sheet/types.js.map +0 -1
  122. package/lib/module/dialog/CenteredDialog.js +0 -246
  123. package/lib/module/dialog/CenteredDialog.js.map +0 -1
  124. package/lib/module/dialog/CenteredDialog.web.js +0 -324
  125. package/lib/module/dialog/CenteredDialog.web.js.map +0 -1
  126. package/lib/module/dialog/centered-dialog-tokens.js +0 -58
  127. package/lib/module/dialog/centered-dialog-tokens.js.map +0 -1
  128. package/lib/module/dialog/centered-dialog-types.js +0 -4
  129. package/lib/module/dialog/centered-dialog-types.js.map +0 -1
  130. package/lib/module/responsive-sheet/ResponsiveSheet.js +0 -90
  131. package/lib/module/responsive-sheet/ResponsiveSheet.js.map +0 -1
  132. package/lib/module/responsive-sheet/ResponsiveSheet.web.js +0 -77
  133. package/lib/module/responsive-sheet/ResponsiveSheet.web.js.map +0 -1
  134. package/lib/module/responsive-sheet/index.js +0 -4
  135. package/lib/module/responsive-sheet/index.js.map +0 -1
  136. package/lib/module/responsive-sheet/index.web.js +0 -12
  137. package/lib/module/responsive-sheet/index.web.js.map +0 -1
  138. package/lib/module/responsive-sheet/types.js +0 -4
  139. package/lib/module/responsive-sheet/types.js.map +0 -1
  140. package/lib/typescript/commonjs/dialog/CenteredDialog.d.ts +0 -22
  141. package/lib/typescript/commonjs/dialog/CenteredDialog.d.ts.map +0 -1
  142. package/lib/typescript/commonjs/dialog/CenteredDialog.web.d.ts +0 -31
  143. package/lib/typescript/commonjs/dialog/CenteredDialog.web.d.ts.map +0 -1
  144. package/lib/typescript/commonjs/dialog/centered-dialog-tokens.d.ts +0 -47
  145. package/lib/typescript/commonjs/dialog/centered-dialog-tokens.d.ts.map +0 -1
  146. package/lib/typescript/commonjs/dialog/centered-dialog-types.d.ts +0 -74
  147. package/lib/typescript/commonjs/dialog/centered-dialog-types.d.ts.map +0 -1
  148. package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.d.ts +0 -22
  149. package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.d.ts.map +0 -1
  150. package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.web.d.ts +0 -16
  151. package/lib/typescript/commonjs/responsive-sheet/ResponsiveSheet.web.d.ts.map +0 -1
  152. package/lib/typescript/commonjs/responsive-sheet/index.d.ts +0 -3
  153. package/lib/typescript/commonjs/responsive-sheet/index.d.ts.map +0 -1
  154. package/lib/typescript/commonjs/responsive-sheet/index.web.d.ts +0 -3
  155. package/lib/typescript/commonjs/responsive-sheet/index.web.d.ts.map +0 -1
  156. package/lib/typescript/commonjs/responsive-sheet/types.d.ts +0 -58
  157. package/lib/typescript/commonjs/responsive-sheet/types.d.ts.map +0 -1
  158. package/lib/typescript/module/dialog/CenteredDialog.d.ts +0 -22
  159. package/lib/typescript/module/dialog/CenteredDialog.d.ts.map +0 -1
  160. package/lib/typescript/module/dialog/CenteredDialog.web.d.ts +0 -31
  161. package/lib/typescript/module/dialog/CenteredDialog.web.d.ts.map +0 -1
  162. package/lib/typescript/module/dialog/centered-dialog-tokens.d.ts +0 -47
  163. package/lib/typescript/module/dialog/centered-dialog-tokens.d.ts.map +0 -1
  164. package/lib/typescript/module/dialog/centered-dialog-types.d.ts +0 -74
  165. package/lib/typescript/module/dialog/centered-dialog-types.d.ts.map +0 -1
  166. package/lib/typescript/module/responsive-sheet/ResponsiveSheet.d.ts +0 -22
  167. package/lib/typescript/module/responsive-sheet/ResponsiveSheet.d.ts.map +0 -1
  168. package/lib/typescript/module/responsive-sheet/ResponsiveSheet.web.d.ts +0 -16
  169. package/lib/typescript/module/responsive-sheet/ResponsiveSheet.web.d.ts.map +0 -1
  170. package/lib/typescript/module/responsive-sheet/index.d.ts +0 -3
  171. package/lib/typescript/module/responsive-sheet/index.d.ts.map +0 -1
  172. package/lib/typescript/module/responsive-sheet/index.web.d.ts +0 -3
  173. package/lib/typescript/module/responsive-sheet/index.web.d.ts.map +0 -1
  174. package/lib/typescript/module/responsive-sheet/types.d.ts +0 -58
  175. package/lib/typescript/module/responsive-sheet/types.d.ts.map +0 -1
  176. package/src/__tests__/CenteredDialog.test.tsx +0 -108
  177. package/src/__tests__/ResponsiveSheet.test.tsx +0 -88
  178. package/src/dialog/CenteredDialog.stories.tsx +0 -125
  179. package/src/dialog/CenteredDialog.tsx +0 -305
  180. package/src/dialog/CenteredDialog.web.tsx +0 -374
  181. package/src/dialog/centered-dialog-tokens.ts +0 -68
  182. package/src/dialog/centered-dialog-types.ts +0 -74
  183. package/src/responsive-sheet/ResponsiveSheet.stories.tsx +0 -54
  184. package/src/responsive-sheet/ResponsiveSheet.tsx +0 -88
  185. package/src/responsive-sheet/ResponsiveSheet.web.tsx +0 -76
  186. package/src/responsive-sheet/index.ts +0 -6
  187. package/src/responsive-sheet/index.web.ts +0 -14
  188. 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 CenteredDialogComponent = React.ComponentType<CenteredDialogProps>;
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 `CenteredDialog`.
17
+ * Build the `AlertDialog` component bound to a platform `Dialog`.
15
18
  *
16
- * `CenteredDialog` is platform-forked (native RN `Modal` vs pure-DOM web
17
- * overlay), and this repo never relies on implicit `.web` resolution — the
18
- * platform entry files (`index.ts` / `index.web.ts`) inject the correct
19
- * `CenteredDialog` here. The body below is single-source, no duplication.
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 `CenteredDialog` that lays out a title,
22
- * description and a confirm/cancel action row. Reach for the imperative
23
- * `confirm()` helper + `<AlertDialogHost />` to trigger a confirm from an
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(CenteredDialog: CenteredDialogComponent) {
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
- <CenteredDialog
56
- visible={visible}
57
- onClose={dismissible ? onClose : () => {}}
58
- dismissible={dismissible}
59
- title={title}
60
- showClose={false}
61
- accessibilityLabel={title}
62
- cardStyle={cardStyle}
63
- testID={testID}
64
- footer={
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 { CenteredDialog } from '../dialog/index';
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(CenteredDialog);
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 { CenteredDialog } from '../dialog/index.web';
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(CenteredDialog);
5
+ export const AlertDialog = createAlertDialog(Dialog);
6
6
  export const AlertDialogHost = createAlertDialogHost(AlertDialog);
7
7
 
8
8
  export { confirm } from './confirm-store';
@@ -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 { CenteredDialogProps } from '../dialog';
17
+ import type { DialogProps } from '../dialog';
18
18
  import type { CommandItem, CommandProps } from './types';
19
19
 
20
- type CenteredDialogComponent = React.ComponentType<CenteredDialogProps>;
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 `CenteredDialog`. The
40
- * platform entry files (`index.ts` / `index.web.ts`) inject the correct one
41
- * (native RN `Modal` vs pure-DOM web overlay) — this repo never relies on
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 Bloom's `CenteredDialog`,
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(CenteredDialog: CenteredDialogComponent) {
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
- <CenteredDialog
172
- visible={visible}
174
+ <Dialog
175
+ open={visible}
173
176
  onClose={onClose}
174
- dismissible
175
- showClose={false}
176
- maxWidth={560}
177
- accessibilityLabel="Command palette"
178
- cardStyle={style}
179
- contentStyle={styles.content}
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
- </CenteredDialog>
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
- content: {
253
- paddingHorizontal: 0,
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: {
@@ -1,6 +1,6 @@
1
- import { CenteredDialog } from '../dialog/index';
1
+ import { Dialog } from '../dialog/index';
2
2
  import { createCommand } from './Command';
3
3
 
4
- export const Command = createCommand(CenteredDialog);
4
+ export const Command = createCommand(Dialog);
5
5
 
6
6
  export type { CommandProps, CommandItem } from './types';
@@ -1,6 +1,6 @@
1
- import { CenteredDialog } from '../dialog/index.web';
1
+ import { Dialog } from '../dialog/index.web';
2
2
  import { createCommand } from './Command';
3
3
 
4
- export const Command = createCommand(CenteredDialog);
4
+ export const Command = createCommand(Dialog);
5
5
 
6
6
  export type { CommandProps, CommandItem } from './types';
@@ -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 (the `responsive-sheet` native technique). Exit animations
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 (the `responsive-sheet`
79
- * technique) on a mounted-through-exit node.
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 (the `responsive-sheet` technique): the
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
  */
@@ -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';
@@ -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';