@oxyhq/bloom 0.4.0 → 0.5.1

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 (275) hide show
  1. package/README.md +105 -90
  2. package/lib/commonjs/bottom-sheet/index.js +2 -2
  3. package/lib/commonjs/context-menu/index.js +18 -19
  4. package/lib/commonjs/context-menu/index.js.map +1 -1
  5. package/lib/commonjs/dialog/BloomDialogProvider.js +61 -0
  6. package/lib/commonjs/dialog/BloomDialogProvider.js.map +1 -0
  7. package/lib/commonjs/dialog/BloomDialogProvider.web.js +45 -0
  8. package/lib/commonjs/dialog/BloomDialogProvider.web.js.map +1 -0
  9. package/lib/commonjs/dialog/Dialog.js +197 -100
  10. package/lib/commonjs/dialog/Dialog.js.map +1 -1
  11. package/lib/commonjs/dialog/Dialog.web.js +194 -84
  12. package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
  13. package/lib/commonjs/dialog/SheetShell.js +149 -0
  14. package/lib/commonjs/dialog/SheetShell.js.map +1 -0
  15. package/lib/commonjs/dialog/alert-store.js +116 -0
  16. package/lib/commonjs/dialog/alert-store.js.map +1 -0
  17. package/lib/commonjs/dialog/alert.js +38 -0
  18. package/lib/commonjs/dialog/alert.js.map +1 -0
  19. package/lib/commonjs/dialog/context.js +10 -2
  20. package/lib/commonjs/dialog/context.js.map +1 -1
  21. package/lib/commonjs/dialog/index.js +8 -24
  22. package/lib/commonjs/dialog/index.js.map +1 -1
  23. package/lib/commonjs/dialog/index.web.js +10 -20
  24. package/lib/commonjs/dialog/index.web.js.map +1 -1
  25. package/lib/commonjs/fonts/FontLoader.js +6 -5
  26. package/lib/commonjs/fonts/FontLoader.js.map +1 -1
  27. package/lib/commonjs/fonts/apply-font-faces.js +4 -4
  28. package/lib/commonjs/fonts/apply-font-faces.web.js +13 -12
  29. package/lib/commonjs/fonts/apply-font-faces.web.js.map +1 -1
  30. package/lib/commonjs/fonts/font-assets.js +2 -2
  31. package/lib/commonjs/fonts/font-data.web.js +22 -0
  32. package/lib/commonjs/fonts/font-data.web.js.map +1 -0
  33. package/lib/commonjs/index.js +101 -66
  34. package/lib/commonjs/index.js.map +1 -1
  35. package/lib/commonjs/index.web.js +101 -66
  36. package/lib/commonjs/index.web.js.map +1 -1
  37. package/lib/commonjs/menu/index.js +21 -23
  38. package/lib/commonjs/menu/index.js.map +1 -1
  39. package/lib/commonjs/select/index.js +26 -27
  40. package/lib/commonjs/select/index.js.map +1 -1
  41. package/lib/commonjs/toast/index.js +42 -13
  42. package/lib/commonjs/toast/index.js.map +1 -1
  43. package/lib/commonjs/toast/index.web.js +19 -15
  44. package/lib/commonjs/toast/index.web.js.map +1 -1
  45. package/lib/module/bottom-sheet/index.js +2 -2
  46. package/lib/module/context-menu/index.js +15 -16
  47. package/lib/module/context-menu/index.js.map +1 -1
  48. package/lib/module/dialog/BloomDialogProvider.js +57 -0
  49. package/lib/module/dialog/BloomDialogProvider.js.map +1 -0
  50. package/lib/module/dialog/BloomDialogProvider.web.js +41 -0
  51. package/lib/module/dialog/BloomDialogProvider.web.js.map +1 -0
  52. package/lib/module/dialog/Dialog.js +199 -87
  53. package/lib/module/dialog/Dialog.js.map +1 -1
  54. package/lib/module/dialog/Dialog.web.js +195 -70
  55. package/lib/module/dialog/Dialog.web.js.map +1 -1
  56. package/lib/module/dialog/SheetShell.js +143 -0
  57. package/lib/module/dialog/SheetShell.js.map +1 -0
  58. package/lib/module/dialog/alert-store.js +107 -0
  59. package/lib/module/dialog/alert-store.js.map +1 -0
  60. package/lib/module/dialog/alert.js +35 -0
  61. package/lib/module/dialog/alert.js.map +1 -0
  62. package/lib/module/dialog/context.js +10 -2
  63. package/lib/module/dialog/context.js.map +1 -1
  64. package/lib/module/dialog/index.js +3 -1
  65. package/lib/module/dialog/index.js.map +1 -1
  66. package/lib/module/dialog/index.web.js +9 -7
  67. package/lib/module/dialog/index.web.js.map +1 -1
  68. package/lib/module/fonts/FontLoader.js +6 -5
  69. package/lib/module/fonts/FontLoader.js.map +1 -1
  70. package/lib/module/fonts/apply-font-faces.js +4 -4
  71. package/lib/module/fonts/apply-font-faces.web.js +13 -10
  72. package/lib/module/fonts/apply-font-faces.web.js.map +1 -1
  73. package/lib/module/fonts/font-assets.js +2 -2
  74. package/lib/module/fonts/font-data.web.js +18 -0
  75. package/lib/module/fonts/font-data.web.js.map +1 -0
  76. package/lib/module/fonts/index.web.js +4 -4
  77. package/lib/module/index.js +2 -3
  78. package/lib/module/index.js.map +1 -1
  79. package/lib/module/index.web.js +2 -3
  80. package/lib/module/index.web.js.map +1 -1
  81. package/lib/module/menu/index.js +11 -13
  82. package/lib/module/menu/index.js.map +1 -1
  83. package/lib/module/select/index.js +27 -28
  84. package/lib/module/select/index.js.map +1 -1
  85. package/lib/module/toast/index.js +41 -11
  86. package/lib/module/toast/index.js.map +1 -1
  87. package/lib/module/toast/index.web.js +18 -13
  88. package/lib/module/toast/index.web.js.map +1 -1
  89. package/lib/typescript/commonjs/bottom-sheet/index.d.ts +1 -1
  90. package/lib/typescript/commonjs/context-menu/index.d.ts +4 -3
  91. package/lib/typescript/commonjs/context-menu/index.d.ts.map +1 -1
  92. package/lib/typescript/commonjs/dialog/BloomDialogProvider.d.ts +27 -0
  93. package/lib/typescript/commonjs/dialog/BloomDialogProvider.d.ts.map +1 -0
  94. package/lib/typescript/commonjs/dialog/BloomDialogProvider.web.d.ts +15 -0
  95. package/lib/typescript/commonjs/dialog/BloomDialogProvider.web.d.ts.map +1 -0
  96. package/lib/typescript/commonjs/dialog/Dialog.d.ts +37 -10
  97. package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts +26 -10
  99. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/dialog/SheetShell.d.ts +31 -0
  101. package/lib/typescript/commonjs/dialog/SheetShell.d.ts.map +1 -0
  102. package/lib/typescript/commonjs/dialog/alert-store.d.ts +70 -0
  103. package/lib/typescript/commonjs/dialog/alert-store.d.ts.map +1 -0
  104. package/lib/typescript/commonjs/dialog/alert.d.ts +27 -0
  105. package/lib/typescript/commonjs/dialog/alert.d.ts.map +1 -0
  106. package/lib/typescript/commonjs/dialog/context.d.ts +7 -0
  107. package/lib/typescript/commonjs/dialog/context.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/dialog/index.d.ts +5 -2
  109. package/lib/typescript/commonjs/dialog/index.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/dialog/index.web.d.ts +5 -2
  111. package/lib/typescript/commonjs/dialog/index.web.d.ts.map +1 -1
  112. package/lib/typescript/commonjs/dialog/types.d.ts +70 -15
  113. package/lib/typescript/commonjs/dialog/types.d.ts.map +1 -1
  114. package/lib/typescript/commonjs/fonts/FontLoader.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts +8 -1
  116. package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts.map +1 -1
  117. package/lib/typescript/commonjs/fonts/font-data.web.d.ts +5 -0
  118. package/lib/typescript/commonjs/fonts/font-data.web.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/index.d.ts +3 -3
  120. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  121. package/lib/typescript/commonjs/index.web.d.ts +3 -3
  122. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/menu/index.d.ts +4 -4
  124. package/lib/typescript/commonjs/menu/index.d.ts.map +1 -1
  125. package/lib/typescript/commonjs/select/index.d.ts.map +1 -1
  126. package/lib/typescript/commonjs/toast/index.d.ts +32 -3
  127. package/lib/typescript/commonjs/toast/index.d.ts.map +1 -1
  128. package/lib/typescript/commonjs/toast/index.web.d.ts +14 -7
  129. package/lib/typescript/commonjs/toast/index.web.d.ts.map +1 -1
  130. package/lib/typescript/module/bottom-sheet/index.d.ts +1 -1
  131. package/lib/typescript/module/context-menu/index.d.ts +4 -3
  132. package/lib/typescript/module/context-menu/index.d.ts.map +1 -1
  133. package/lib/typescript/module/dialog/BloomDialogProvider.d.ts +27 -0
  134. package/lib/typescript/module/dialog/BloomDialogProvider.d.ts.map +1 -0
  135. package/lib/typescript/module/dialog/BloomDialogProvider.web.d.ts +15 -0
  136. package/lib/typescript/module/dialog/BloomDialogProvider.web.d.ts.map +1 -0
  137. package/lib/typescript/module/dialog/Dialog.d.ts +37 -10
  138. package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
  139. package/lib/typescript/module/dialog/Dialog.web.d.ts +26 -10
  140. package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
  141. package/lib/typescript/module/dialog/SheetShell.d.ts +31 -0
  142. package/lib/typescript/module/dialog/SheetShell.d.ts.map +1 -0
  143. package/lib/typescript/module/dialog/alert-store.d.ts +70 -0
  144. package/lib/typescript/module/dialog/alert-store.d.ts.map +1 -0
  145. package/lib/typescript/module/dialog/alert.d.ts +27 -0
  146. package/lib/typescript/module/dialog/alert.d.ts.map +1 -0
  147. package/lib/typescript/module/dialog/context.d.ts +7 -0
  148. package/lib/typescript/module/dialog/context.d.ts.map +1 -1
  149. package/lib/typescript/module/dialog/index.d.ts +5 -2
  150. package/lib/typescript/module/dialog/index.d.ts.map +1 -1
  151. package/lib/typescript/module/dialog/index.web.d.ts +5 -2
  152. package/lib/typescript/module/dialog/index.web.d.ts.map +1 -1
  153. package/lib/typescript/module/dialog/types.d.ts +70 -15
  154. package/lib/typescript/module/dialog/types.d.ts.map +1 -1
  155. package/lib/typescript/module/fonts/FontLoader.d.ts.map +1 -1
  156. package/lib/typescript/module/fonts/apply-font-faces.web.d.ts +8 -1
  157. package/lib/typescript/module/fonts/apply-font-faces.web.d.ts.map +1 -1
  158. package/lib/typescript/module/fonts/font-data.web.d.ts +5 -0
  159. package/lib/typescript/module/fonts/font-data.web.d.ts.map +1 -0
  160. package/lib/typescript/module/index.d.ts +3 -3
  161. package/lib/typescript/module/index.d.ts.map +1 -1
  162. package/lib/typescript/module/index.web.d.ts +3 -3
  163. package/lib/typescript/module/index.web.d.ts.map +1 -1
  164. package/lib/typescript/module/menu/index.d.ts +4 -4
  165. package/lib/typescript/module/menu/index.d.ts.map +1 -1
  166. package/lib/typescript/module/select/index.d.ts.map +1 -1
  167. package/lib/typescript/module/toast/index.d.ts +32 -3
  168. package/lib/typescript/module/toast/index.d.ts.map +1 -1
  169. package/lib/typescript/module/toast/index.web.d.ts +14 -7
  170. package/lib/typescript/module/toast/index.web.d.ts.map +1 -1
  171. package/package.json +38 -18
  172. package/src/__tests__/Dialog.test.tsx +177 -0
  173. package/src/avatar/Avatar.stories.tsx +69 -0
  174. package/src/bottom-sheet/BottomSheet.stories.tsx +92 -0
  175. package/src/bottom-sheet/index.tsx +3 -3
  176. package/src/button/Button.stories.tsx +94 -0
  177. package/src/context-menu/ContextMenu.stories.tsx +71 -0
  178. package/src/context-menu/index.tsx +12 -12
  179. package/src/dialog/BloomDialogProvider.tsx +61 -0
  180. package/src/dialog/BloomDialogProvider.web.tsx +46 -0
  181. package/src/dialog/Dialog.stories.tsx +112 -0
  182. package/src/dialog/Dialog.tsx +217 -64
  183. package/src/dialog/Dialog.web.tsx +240 -75
  184. package/src/dialog/SheetShell.tsx +154 -0
  185. package/src/dialog/alert-store.ts +126 -0
  186. package/src/dialog/alert.ts +42 -0
  187. package/src/dialog/context.ts +14 -3
  188. package/src/dialog/index.ts +14 -2
  189. package/src/dialog/index.web.ts +20 -8
  190. package/src/dialog/types.ts +73 -16
  191. package/src/fonts/FontLoader.tsx +6 -5
  192. package/src/fonts/apply-font-faces.ts +4 -4
  193. package/src/fonts/apply-font-faces.web.ts +18 -10
  194. package/src/fonts/font-assets.ts +2 -2
  195. package/src/fonts/font-data.web.ts +15 -0
  196. package/src/fonts/index.web.ts +4 -4
  197. package/src/index.ts +17 -3
  198. package/src/index.web.ts +17 -3
  199. package/src/loading/Loading.stories.tsx +60 -0
  200. package/src/menu/Menu.stories.tsx +79 -0
  201. package/src/menu/index.tsx +13 -17
  202. package/src/prompt-input/PromptInput.stories.tsx +82 -0
  203. package/src/select/Select.stories.tsx +84 -0
  204. package/src/select/index.tsx +30 -30
  205. package/src/settings-list/SettingsList.stories.tsx +106 -0
  206. package/src/text-field/TextField.stories.tsx +90 -0
  207. package/src/toast/Toast.stories.tsx +109 -0
  208. package/src/toast/index.tsx +55 -11
  209. package/src/toast/index.web.tsx +33 -13
  210. package/lib/commonjs/fonts/assets/BlomusModernus-Bold.woff2 +0 -0
  211. package/lib/commonjs/fonts/assets/BlomusModernus-Regular.woff2 +0 -0
  212. package/lib/commonjs/fonts/assets/GeistMono-Variable.woff2 +0 -0
  213. package/lib/commonjs/fonts/assets/InterVariable.woff2 +0 -0
  214. package/lib/commonjs/prompt/Prompt.js +0 -267
  215. package/lib/commonjs/prompt/Prompt.js.map +0 -1
  216. package/lib/commonjs/prompt/index.js +0 -61
  217. package/lib/commonjs/prompt/index.js.map +0 -1
  218. package/lib/module/fonts/assets/BlomusModernus-Bold.woff2 +0 -0
  219. package/lib/module/fonts/assets/BlomusModernus-Regular.woff2 +0 -0
  220. package/lib/module/fonts/assets/GeistMono-Variable.woff2 +0 -0
  221. package/lib/module/fonts/assets/InterVariable.woff2 +0 -0
  222. package/lib/module/prompt/Prompt.js +0 -250
  223. package/lib/module/prompt/Prompt.js.map +0 -1
  224. package/lib/module/prompt/index.js +0 -4
  225. package/lib/module/prompt/index.js.map +0 -1
  226. package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts +0 -5
  227. package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +0 -1
  228. package/lib/typescript/commonjs/__tests__/BloomThemeProvider.test.d.ts +0 -2
  229. package/lib/typescript/commonjs/__tests__/BloomThemeProvider.test.d.ts.map +0 -1
  230. package/lib/typescript/commonjs/__tests__/BottomSheet.test.d.ts +0 -2
  231. package/lib/typescript/commonjs/__tests__/BottomSheet.test.d.ts.map +0 -1
  232. package/lib/typescript/commonjs/__tests__/Button.test.d.ts +0 -2
  233. package/lib/typescript/commonjs/__tests__/Button.test.d.ts.map +0 -1
  234. package/lib/typescript/commonjs/__tests__/Code.test.d.ts +0 -2
  235. package/lib/typescript/commonjs/__tests__/Code.test.d.ts.map +0 -1
  236. package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts +0 -2
  237. package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts.map +0 -1
  238. package/lib/typescript/commonjs/__tests__/Pre.test.d.ts +0 -2
  239. package/lib/typescript/commonjs/__tests__/Pre.test.d.ts.map +0 -1
  240. package/lib/typescript/commonjs/__tests__/SettingsList.test.d.ts +0 -2
  241. package/lib/typescript/commonjs/__tests__/SettingsList.test.d.ts.map +0 -1
  242. package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts +0 -5
  243. package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts.map +0 -1
  244. package/lib/typescript/commonjs/__tests__/theme.test.d.ts +0 -2
  245. package/lib/typescript/commonjs/__tests__/theme.test.d.ts.map +0 -1
  246. package/lib/typescript/commonjs/prompt/Prompt.d.ts +0 -42
  247. package/lib/typescript/commonjs/prompt/Prompt.d.ts.map +0 -1
  248. package/lib/typescript/commonjs/prompt/index.d.ts +0 -3
  249. package/lib/typescript/commonjs/prompt/index.d.ts.map +0 -1
  250. package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts +0 -5
  251. package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +0 -1
  252. package/lib/typescript/module/__tests__/BloomThemeProvider.test.d.ts +0 -2
  253. package/lib/typescript/module/__tests__/BloomThemeProvider.test.d.ts.map +0 -1
  254. package/lib/typescript/module/__tests__/BottomSheet.test.d.ts +0 -2
  255. package/lib/typescript/module/__tests__/BottomSheet.test.d.ts.map +0 -1
  256. package/lib/typescript/module/__tests__/Button.test.d.ts +0 -2
  257. package/lib/typescript/module/__tests__/Button.test.d.ts.map +0 -1
  258. package/lib/typescript/module/__tests__/Code.test.d.ts +0 -2
  259. package/lib/typescript/module/__tests__/Code.test.d.ts.map +0 -1
  260. package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts +0 -2
  261. package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts.map +0 -1
  262. package/lib/typescript/module/__tests__/Pre.test.d.ts +0 -2
  263. package/lib/typescript/module/__tests__/Pre.test.d.ts.map +0 -1
  264. package/lib/typescript/module/__tests__/SettingsList.test.d.ts +0 -2
  265. package/lib/typescript/module/__tests__/SettingsList.test.d.ts.map +0 -1
  266. package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts +0 -5
  267. package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts.map +0 -1
  268. package/lib/typescript/module/__tests__/theme.test.d.ts +0 -2
  269. package/lib/typescript/module/__tests__/theme.test.d.ts.map +0 -1
  270. package/lib/typescript/module/prompt/Prompt.d.ts +0 -42
  271. package/lib/typescript/module/prompt/Prompt.d.ts.map +0 -1
  272. package/lib/typescript/module/prompt/index.d.ts +0 -3
  273. package/lib/typescript/module/prompt/index.d.ts.map +0 -1
  274. package/src/prompt/Prompt.tsx +0 -247
  275. package/src/prompt/index.ts +0 -13
@@ -0,0 +1,92 @@
1
+ import React, { useRef } from 'react';
2
+ import { Text, View } from 'react-native';
3
+ import type { Meta, StoryObj } from '@storybook/react-vite';
4
+
5
+ import { Button } from '../button';
6
+ import { BottomSheet, type BottomSheetRef } from './index';
7
+
8
+ const meta: Meta<typeof BottomSheet> = {
9
+ title: 'Components/BottomSheet',
10
+ component: BottomSheet,
11
+ };
12
+
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof BottomSheet>;
16
+
17
+ function BasicSheet() {
18
+ const ref = useRef<BottomSheetRef>(null);
19
+ return (
20
+ <>
21
+ <Button onPress={() => ref.current?.present()}>Open sheet</Button>
22
+ <BottomSheet ref={ref}>
23
+ <View style={{ padding: 24, gap: 12 }}>
24
+ <Text style={{ fontSize: 20, fontWeight: '700' }}>Bottom sheet</Text>
25
+ <Text>
26
+ Pan down to close, or tap the backdrop. This is the default sheet
27
+ (flush, rounded top corners only).
28
+ </Text>
29
+ </View>
30
+ </BottomSheet>
31
+ </>
32
+ );
33
+ }
34
+
35
+ function DetachedSheet() {
36
+ const ref = useRef<BottomSheetRef>(null);
37
+ return (
38
+ <>
39
+ <Button onPress={() => ref.current?.present()}>Open detached</Button>
40
+ <BottomSheet ref={ref} detached>
41
+ <View style={{ padding: 24, gap: 12 }}>
42
+ <Text style={{ fontSize: 20, fontWeight: '700' }}>Detached</Text>
43
+ <Text>
44
+ Floating card with margins and rounded corners on all sides.
45
+ </Text>
46
+ </View>
47
+ </BottomSheet>
48
+ </>
49
+ );
50
+ }
51
+
52
+ function NonScrollableSheet() {
53
+ const ref = useRef<BottomSheetRef>(null);
54
+ return (
55
+ <>
56
+ <Button onPress={() => ref.current?.present()}>Open non-scrollable</Button>
57
+ <BottomSheet ref={ref} scrollable={false}>
58
+ <View style={{ padding: 24, gap: 12 }}>
59
+ <Text style={{ fontSize: 20, fontWeight: '700' }}>
60
+ Non-scrollable
61
+ </Text>
62
+ <Text>
63
+ Use when the body owns its own VirtualizedList (FlatList,
64
+ SectionList, etc.).
65
+ </Text>
66
+ </View>
67
+ </BottomSheet>
68
+ </>
69
+ );
70
+ }
71
+
72
+ export const Basic: Story = {
73
+ render: () => <BasicSheet />,
74
+ };
75
+
76
+ export const Detached: Story = {
77
+ render: () => <DetachedSheet />,
78
+ };
79
+
80
+ export const NonScrollable: Story = {
81
+ render: () => <NonScrollableSheet />,
82
+ };
83
+
84
+ export const Composition: Story = {
85
+ render: () => (
86
+ <View style={{ gap: 12, alignItems: 'flex-start' }}>
87
+ <BasicSheet />
88
+ <DetachedSheet />
89
+ <NonScrollableSheet />
90
+ </View>
91
+ ),
92
+ };
@@ -89,7 +89,7 @@ export interface BottomSheetProps {
89
89
  /**
90
90
  * Opacity of the dimming backdrop behind the sheet (0–1). Defaults to `0.5`.
91
91
  * Set to a higher value (e.g. `0.7`) when the sheet is presented over another
92
- * bottom sheet (Dialog/Prompt cases) so the underlying handle/content does not
92
+ * bottom sheet (Dialog cases) so the underlying handle/content does not
93
93
  * bleed through.
94
94
  */
95
95
  backdropOpacity?: number;
@@ -300,8 +300,8 @@ const BottomSheet = forwardRef((props: BottomSheetProps, ref: React.ForwardedRef
300
300
 
301
301
  // On unmount: ensure pending close callbacks (e.g. consumer's `onDismiss`)
302
302
  // still fire if the BS is yanked mid-animation by a parent re-render.
303
- // Without this, `Dialog.Outer.handleDismiss` never runs and queued
304
- // callbacks like `Prompt.Action`'s post-close handler are silently lost.
303
+ // Without this, `Dialog`'s `handleDismiss` never runs and queued
304
+ // callbacks (post-close handlers) are silently lost.
305
305
  // Only fires when the sheet was actually rendered (open or closing) to
306
306
  // avoid spuriously calling onDismiss on bare unmount of a never-opened
307
307
  // sheet. Refs are read inside the cleanup, so latest values are captured.
@@ -0,0 +1,94 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import type { Meta, StoryObj } from '@storybook/react-vite';
4
+
5
+ import { Button } from './Button';
6
+
7
+ const meta: Meta<typeof Button> = {
8
+ title: 'Components/Button',
9
+ component: Button,
10
+ args: {
11
+ children: 'Button',
12
+ onPress: () => {},
13
+ },
14
+ argTypes: {
15
+ variant: {
16
+ control: 'select',
17
+ options: ['primary', 'secondary', 'inverse', 'icon', 'ghost', 'text'],
18
+ },
19
+ size: {
20
+ control: 'select',
21
+ options: ['small', 'medium', 'large'],
22
+ },
23
+ disabled: { control: 'boolean' },
24
+ loading: { control: 'boolean' },
25
+ },
26
+ };
27
+
28
+ export default meta;
29
+
30
+ type Story = StoryObj<typeof Button>;
31
+
32
+ export const Basic: Story = {
33
+ args: { children: 'Save' },
34
+ };
35
+
36
+ export const Primary: Story = {
37
+ args: { variant: 'primary', children: 'Primary' },
38
+ };
39
+
40
+ export const Secondary: Story = {
41
+ args: { variant: 'secondary', children: 'Secondary' },
42
+ };
43
+
44
+ export const Ghost: Story = {
45
+ args: { variant: 'ghost', children: 'Ghost' },
46
+ };
47
+
48
+ export const TextOnly: Story = {
49
+ args: { variant: 'text', children: 'Text button' },
50
+ name: 'Text',
51
+ };
52
+
53
+ export const Inverse: Story = {
54
+ args: { variant: 'inverse', children: 'Inverse' },
55
+ };
56
+
57
+ export const Variants: Story = {
58
+ render: () => (
59
+ <View style={{ gap: 12, alignItems: 'flex-start' }}>
60
+ <Button variant="primary">Primary</Button>
61
+ <Button variant="secondary">Secondary</Button>
62
+ <Button variant="inverse">Inverse</Button>
63
+ <Button variant="ghost">Ghost</Button>
64
+ <Button variant="text">Text</Button>
65
+ </View>
66
+ ),
67
+ };
68
+
69
+ export const Sizes: Story = {
70
+ render: () => (
71
+ <View style={{ gap: 12, alignItems: 'flex-start' }}>
72
+ <Button size="small">Small</Button>
73
+ <Button size="medium">Medium</Button>
74
+ <Button size="large">Large</Button>
75
+ </View>
76
+ ),
77
+ };
78
+
79
+ export const Loading: Story = {
80
+ args: { loading: true, children: 'Submitting' },
81
+ };
82
+
83
+ export const Disabled: Story = {
84
+ args: { disabled: true, children: 'Disabled' },
85
+ };
86
+
87
+ export const Composition: Story = {
88
+ render: () => (
89
+ <View style={{ flexDirection: 'row', gap: 12, flexWrap: 'wrap' }}>
90
+ <Button variant="primary">Save</Button>
91
+ <Button variant="secondary">Cancel</Button>
92
+ </View>
93
+ ),
94
+ };
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { Pressable, Text, View } from 'react-native';
3
+ import type { Meta, StoryObj } from '@storybook/react-vite';
4
+
5
+ import { useTheme } from '../theme/use-theme';
6
+ import * as ContextMenu from './index';
7
+
8
+ const meta: Meta = {
9
+ title: 'Components/ContextMenu',
10
+ };
11
+
12
+ export default meta;
13
+
14
+ type Story = StoryObj;
15
+
16
+ function TriggerSurface() {
17
+ const theme = useTheme();
18
+ return (
19
+ <ContextMenu.Root>
20
+ <ContextMenu.Trigger label="Long-press for actions">
21
+ {({ props }) => (
22
+ <Pressable
23
+ onPress={() => props.onPress?.()}
24
+ onLongPress={() => props.onLongPress?.()}
25
+ accessibilityLabel={props.accessibilityLabel}
26
+ accessibilityHint={props.accessibilityHint}
27
+ style={{
28
+ padding: 24,
29
+ borderRadius: 12,
30
+ backgroundColor: theme.colors.backgroundSecondary,
31
+ borderWidth: 1,
32
+ borderColor: theme.colors.borderLight,
33
+ minWidth: 240,
34
+ alignItems: 'center',
35
+ }}
36
+ >
37
+ <Text style={{ color: theme.colors.text }}>
38
+ Long-press / right-click me
39
+ </Text>
40
+ </Pressable>
41
+ )}
42
+ </ContextMenu.Trigger>
43
+ <ContextMenu.Outer>
44
+ <ContextMenu.Group>
45
+ <ContextMenu.Item label="Open" onPress={() => {}}>
46
+ <ContextMenu.ItemText>Open</ContextMenu.ItemText>
47
+ </ContextMenu.Item>
48
+ <ContextMenu.Item label="Rename" onPress={() => {}}>
49
+ <ContextMenu.ItemText>Rename</ContextMenu.ItemText>
50
+ </ContextMenu.Item>
51
+ <ContextMenu.Item label="Delete" onPress={() => {}}>
52
+ <ContextMenu.ItemText>Delete</ContextMenu.ItemText>
53
+ </ContextMenu.Item>
54
+ </ContextMenu.Group>
55
+ </ContextMenu.Outer>
56
+ </ContextMenu.Root>
57
+ );
58
+ }
59
+
60
+ export const Basic: Story = {
61
+ render: () => <TriggerSurface />,
62
+ };
63
+
64
+ export const Composition: Story = {
65
+ render: () => (
66
+ <View style={{ gap: 16 }}>
67
+ <TriggerSurface />
68
+ <TriggerSurface />
69
+ </View>
70
+ ),
71
+ };
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * ContextMenu — Native implementation
3
3
  *
4
- * Opens a bottom-sheet menu via Bloom's Dialog when the user long-presses
5
- * the trigger. The menu body is rendered through Bloom's Menu component
6
- * pattern using Dialog.Outer / Dialog.ScrollableInner.
4
+ * Opens a bottom-sheet menu when the user long-presses the trigger. The
5
+ * menu body uses bloom's internal `SheetShell` (a `BottomSheet`
6
+ * presentation primitive with the same drag-handle + close-on-tap
7
+ * semantics shared by `Menu` and `Select`).
7
8
  */
8
9
  import React, {
9
10
  createContext,
@@ -15,7 +16,9 @@ import { Pressable, StyleSheet, View } from 'react-native';
15
16
 
16
17
  import { useTheme } from '../theme/use-theme';
17
18
  import { Text } from '../typography';
18
- import * as Dialog from '../dialog';
19
+ import { useDialogControl } from '../dialog/context';
20
+ import { SheetShell } from '../dialog/SheetShell';
21
+ import type { DialogControlProps } from '../dialog/types';
19
22
  import { useInteractionState } from '../hooks/useInteractionState';
20
23
  import { ItemCtx, useItemContext } from './context';
21
24
  import type {
@@ -34,7 +37,7 @@ import type {
34
37
  // ---------------------------------------------------------------------------
35
38
 
36
39
  type NativeContextMenuContextValue = ContextMenuContextValue & {
37
- control: Dialog.DialogControlProps;
40
+ control: DialogControlProps;
38
41
  };
39
42
 
40
43
  const NativeContextMenuContext = createContext<NativeContextMenuContextValue | null>(null);
@@ -55,7 +58,7 @@ function useNativeContextMenuContext(): NativeContextMenuContextValue {
55
58
  // ---------------------------------------------------------------------------
56
59
 
57
60
  export function Root({ children }: { children: React.ReactNode }) {
58
- const control = Dialog.useDialogControl();
61
+ const control = useDialogControl();
59
62
 
60
63
  const ctx = useMemo(
61
64
  () => ({
@@ -112,8 +115,7 @@ export function Outer({ children, style }: OuterProps) {
112
115
  const { control } = useNativeContextMenuContext();
113
116
 
114
117
  return (
115
- <Dialog.Outer control={control} preventExpansion>
116
- <Dialog.Handle />
118
+ <SheetShell control={control} label="Context menu">
117
119
  <NativeContextMenuContext.Provider
118
120
  value={{
119
121
  isOpen: true,
@@ -122,11 +124,9 @@ export function Outer({ children, style }: OuterProps) {
122
124
  control,
123
125
  }}
124
126
  >
125
- <Dialog.ScrollableInner label="Context menu">
126
- <View style={[styles.outerContent, style]}>{children}</View>
127
- </Dialog.ScrollableInner>
127
+ <View style={[styles.outerContent, style]}>{children}</View>
128
128
  </NativeContextMenuContext.Provider>
129
- </Dialog.Outer>
129
+ </SheetShell>
130
130
  );
131
131
  }
132
132
 
@@ -0,0 +1,61 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ import { AutoMountedDialog } from './Dialog';
4
+ import {
5
+ buttonToAction,
6
+ dismissAlert,
7
+ subscribeAlerts,
8
+ type AlertEntry,
9
+ } from './alert-store';
10
+
11
+ /**
12
+ * Mounts the imperative `alert()` host inside your app.
13
+ *
14
+ * Wrap your app root once (after `BloomThemeProvider`, so the dialog's
15
+ * colours come from the active theme) and you can call `alert()` from
16
+ * anywhere — including from code that runs before the provider mounts
17
+ * (alerts are queued and drained on subscribe).
18
+ *
19
+ * ```tsx
20
+ * import { BloomDialogProvider } from '@oxyhq/bloom';
21
+ *
22
+ * <BloomThemeProvider mode="system" colorPreset="oxy">
23
+ * <BloomDialogProvider>
24
+ * <App />
25
+ * </BloomDialogProvider>
26
+ * </BloomThemeProvider>
27
+ * ```
28
+ *
29
+ * Alerts are presented one at a time. While one is on screen, subsequent
30
+ * `alert()` calls enqueue and present in FIFO order once their predecessor
31
+ * has finished closing.
32
+ */
33
+ export function BloomDialogProvider({ children }: { children: React.ReactNode }) {
34
+ const [queue, setQueue] = useState<readonly AlertEntry[]>([]);
35
+
36
+ useEffect(() => subscribeAlerts(setQueue), []);
37
+
38
+ // Only the head of the queue is presented; this keeps the bottom-sheet
39
+ // exit/enter animations clean and matches the platform `Alert.alert`
40
+ // behaviour our consumers expect.
41
+ const head = queue[0];
42
+
43
+ return (
44
+ <>
45
+ {children}
46
+ {head ? <AlertHost key={head.id} entry={head} /> : null}
47
+ </>
48
+ );
49
+ }
50
+
51
+ function AlertHost({ entry }: { entry: AlertEntry }) {
52
+ const actions = entry.buttons.map(buttonToAction);
53
+ return (
54
+ <AutoMountedDialog
55
+ title={entry.title}
56
+ description={entry.message}
57
+ actions={actions}
58
+ onResolve={() => dismissAlert(entry.id)}
59
+ />
60
+ );
61
+ }
@@ -0,0 +1,46 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ import { AutoMountedDialog } from './Dialog.web';
4
+ import {
5
+ buttonToAction,
6
+ dismissAlert,
7
+ subscribeAlerts,
8
+ type AlertEntry,
9
+ } from './alert-store';
10
+
11
+ /**
12
+ * Web variant of `BloomDialogProvider`. Identical surface area to the
13
+ * native version — it just uses the web-fork `Dialog` (`Dialog.web.tsx`)
14
+ * underneath instead of the bottom-sheet variant.
15
+ *
16
+ * See the native file (`./BloomDialogProvider.tsx`) for the full design
17
+ * notes; this fork exists purely so the bundler's `browser` condition can
18
+ * resolve to a `Dialog` that doesn't pull in the native gesture-handler /
19
+ * reanimated stack.
20
+ */
21
+ export function BloomDialogProvider({ children }: { children: React.ReactNode }) {
22
+ const [queue, setQueue] = useState<readonly AlertEntry[]>([]);
23
+
24
+ useEffect(() => subscribeAlerts(setQueue), []);
25
+
26
+ const head = queue[0];
27
+
28
+ return (
29
+ <>
30
+ {children}
31
+ {head ? <AlertHost key={head.id} entry={head} /> : null}
32
+ </>
33
+ );
34
+ }
35
+
36
+ function AlertHost({ entry }: { entry: AlertEntry }) {
37
+ const actions = entry.buttons.map(buttonToAction);
38
+ return (
39
+ <AutoMountedDialog
40
+ title={entry.title}
41
+ description={entry.message}
42
+ actions={actions}
43
+ onResolve={() => dismissAlert(entry.id)}
44
+ />
45
+ );
46
+ }
@@ -0,0 +1,112 @@
1
+ import React from 'react';
2
+ import { Text, View } from 'react-native';
3
+ import type { Meta, StoryObj } from '@storybook/react-vite';
4
+
5
+ import { Button } from '../button';
6
+ import { Dialog } from './Dialog';
7
+ import { useDialogControl } from './context';
8
+ import { alert } from './alert';
9
+
10
+ const meta: Meta<typeof Dialog> = {
11
+ title: 'Components/Dialog',
12
+ component: Dialog,
13
+ };
14
+
15
+ export default meta;
16
+
17
+ type Story = StoryObj<typeof Dialog>;
18
+
19
+ function DeclarativeDemo() {
20
+ const control = useDialogControl();
21
+ return (
22
+ <>
23
+ <Button onPress={() => control.open()}>Open dialog</Button>
24
+ <Dialog
25
+ control={control}
26
+ title="Sign out?"
27
+ description="You'll need to enter your password to sign in again."
28
+ actions={[
29
+ { label: 'Sign out', color: 'destructive' },
30
+ { label: 'Cancel', color: 'cancel' },
31
+ ]}
32
+ />
33
+ </>
34
+ );
35
+ }
36
+
37
+ function CustomChildrenDemo() {
38
+ const control = useDialogControl();
39
+ return (
40
+ <>
41
+ <Button onPress={() => control.open()}>Open custom dialog</Button>
42
+ <Dialog control={control} title="Custom body">
43
+ <View style={{ gap: 12 }}>
44
+ <Text>Render any JSX inside the dialog body.</Text>
45
+ <Button variant="secondary" onPress={() => control.close()}>
46
+ Done
47
+ </Button>
48
+ </View>
49
+ </Dialog>
50
+ </>
51
+ );
52
+ }
53
+
54
+ function AlertDemo() {
55
+ return (
56
+ <Button
57
+ onPress={() =>
58
+ alert('Delete project?', 'This action cannot be undone.', [
59
+ { text: 'Cancel', style: 'cancel' },
60
+ { text: 'Delete', style: 'destructive' },
61
+ ])
62
+ }
63
+ >
64
+ Trigger alert()
65
+ </Button>
66
+ );
67
+ }
68
+
69
+ function ThreeActionDemo() {
70
+ const control = useDialogControl();
71
+ return (
72
+ <>
73
+ <Button onPress={() => control.open()}>Three actions</Button>
74
+ <Dialog
75
+ control={control}
76
+ title="Save changes?"
77
+ description="You have unsaved changes."
78
+ actions={[
79
+ { label: 'Save', color: 'default' },
80
+ { label: 'Discard', color: 'destructive' },
81
+ { label: 'Cancel', color: 'cancel' },
82
+ ]}
83
+ />
84
+ </>
85
+ );
86
+ }
87
+
88
+ export const Basic: Story = {
89
+ render: () => <DeclarativeDemo />,
90
+ };
91
+
92
+ export const CustomChildren: Story = {
93
+ render: () => <CustomChildrenDemo />,
94
+ };
95
+
96
+ export const AlertHelper: Story = {
97
+ render: () => <AlertDemo />,
98
+ };
99
+
100
+ export const ThreeAction: Story = {
101
+ render: () => <ThreeActionDemo />,
102
+ };
103
+
104
+ export const Composition: Story = {
105
+ render: () => (
106
+ <View style={{ gap: 12, alignItems: 'flex-start' }}>
107
+ <DeclarativeDemo />
108
+ <CustomChildrenDemo />
109
+ <AlertDemo />
110
+ </View>
111
+ ),
112
+ };