@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.
- package/README.md +105 -90
- package/lib/commonjs/bottom-sheet/index.js +2 -2
- package/lib/commonjs/context-menu/index.js +18 -19
- package/lib/commonjs/context-menu/index.js.map +1 -1
- package/lib/commonjs/dialog/BloomDialogProvider.js +61 -0
- package/lib/commonjs/dialog/BloomDialogProvider.js.map +1 -0
- package/lib/commonjs/dialog/BloomDialogProvider.web.js +45 -0
- package/lib/commonjs/dialog/BloomDialogProvider.web.js.map +1 -0
- package/lib/commonjs/dialog/Dialog.js +197 -100
- package/lib/commonjs/dialog/Dialog.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +194 -84
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/dialog/SheetShell.js +149 -0
- package/lib/commonjs/dialog/SheetShell.js.map +1 -0
- package/lib/commonjs/dialog/alert-store.js +116 -0
- package/lib/commonjs/dialog/alert-store.js.map +1 -0
- package/lib/commonjs/dialog/alert.js +38 -0
- package/lib/commonjs/dialog/alert.js.map +1 -0
- package/lib/commonjs/dialog/context.js +10 -2
- package/lib/commonjs/dialog/context.js.map +1 -1
- package/lib/commonjs/dialog/index.js +8 -24
- package/lib/commonjs/dialog/index.js.map +1 -1
- package/lib/commonjs/dialog/index.web.js +10 -20
- package/lib/commonjs/dialog/index.web.js.map +1 -1
- package/lib/commonjs/fonts/FontLoader.js +6 -5
- package/lib/commonjs/fonts/FontLoader.js.map +1 -1
- package/lib/commonjs/fonts/apply-font-faces.js +4 -4
- package/lib/commonjs/fonts/apply-font-faces.web.js +13 -12
- package/lib/commonjs/fonts/apply-font-faces.web.js.map +1 -1
- package/lib/commonjs/fonts/font-assets.js +2 -2
- package/lib/commonjs/fonts/font-data.web.js +22 -0
- package/lib/commonjs/fonts/font-data.web.js.map +1 -0
- package/lib/commonjs/index.js +101 -66
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +101 -66
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/menu/index.js +21 -23
- package/lib/commonjs/menu/index.js.map +1 -1
- package/lib/commonjs/select/index.js +26 -27
- package/lib/commonjs/select/index.js.map +1 -1
- package/lib/commonjs/toast/index.js +42 -13
- package/lib/commonjs/toast/index.js.map +1 -1
- package/lib/commonjs/toast/index.web.js +19 -15
- package/lib/commonjs/toast/index.web.js.map +1 -1
- package/lib/module/bottom-sheet/index.js +2 -2
- package/lib/module/context-menu/index.js +15 -16
- package/lib/module/context-menu/index.js.map +1 -1
- package/lib/module/dialog/BloomDialogProvider.js +57 -0
- package/lib/module/dialog/BloomDialogProvider.js.map +1 -0
- package/lib/module/dialog/BloomDialogProvider.web.js +41 -0
- package/lib/module/dialog/BloomDialogProvider.web.js.map +1 -0
- package/lib/module/dialog/Dialog.js +199 -87
- package/lib/module/dialog/Dialog.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +195 -70
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/dialog/SheetShell.js +143 -0
- package/lib/module/dialog/SheetShell.js.map +1 -0
- package/lib/module/dialog/alert-store.js +107 -0
- package/lib/module/dialog/alert-store.js.map +1 -0
- package/lib/module/dialog/alert.js +35 -0
- package/lib/module/dialog/alert.js.map +1 -0
- package/lib/module/dialog/context.js +10 -2
- package/lib/module/dialog/context.js.map +1 -1
- package/lib/module/dialog/index.js +3 -1
- package/lib/module/dialog/index.js.map +1 -1
- package/lib/module/dialog/index.web.js +9 -7
- package/lib/module/dialog/index.web.js.map +1 -1
- package/lib/module/fonts/FontLoader.js +6 -5
- package/lib/module/fonts/FontLoader.js.map +1 -1
- package/lib/module/fonts/apply-font-faces.js +4 -4
- package/lib/module/fonts/apply-font-faces.web.js +13 -10
- package/lib/module/fonts/apply-font-faces.web.js.map +1 -1
- package/lib/module/fonts/font-assets.js +2 -2
- package/lib/module/fonts/font-data.web.js +18 -0
- package/lib/module/fonts/font-data.web.js.map +1 -0
- package/lib/module/fonts/index.web.js +4 -4
- package/lib/module/index.js +2 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +2 -3
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/menu/index.js +11 -13
- package/lib/module/menu/index.js.map +1 -1
- package/lib/module/select/index.js +27 -28
- package/lib/module/select/index.js.map +1 -1
- package/lib/module/toast/index.js +41 -11
- package/lib/module/toast/index.js.map +1 -1
- package/lib/module/toast/index.web.js +18 -13
- package/lib/module/toast/index.web.js.map +1 -1
- package/lib/typescript/commonjs/bottom-sheet/index.d.ts +1 -1
- package/lib/typescript/commonjs/context-menu/index.d.ts +4 -3
- package/lib/typescript/commonjs/context-menu/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/BloomDialogProvider.d.ts +27 -0
- package/lib/typescript/commonjs/dialog/BloomDialogProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/dialog/BloomDialogProvider.web.d.ts +15 -0
- package/lib/typescript/commonjs/dialog/BloomDialogProvider.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/dialog/Dialog.d.ts +37 -10
- package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts +26 -10
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/SheetShell.d.ts +31 -0
- package/lib/typescript/commonjs/dialog/SheetShell.d.ts.map +1 -0
- package/lib/typescript/commonjs/dialog/alert-store.d.ts +70 -0
- package/lib/typescript/commonjs/dialog/alert-store.d.ts.map +1 -0
- package/lib/typescript/commonjs/dialog/alert.d.ts +27 -0
- package/lib/typescript/commonjs/dialog/alert.d.ts.map +1 -0
- package/lib/typescript/commonjs/dialog/context.d.ts +7 -0
- package/lib/typescript/commonjs/dialog/context.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/index.d.ts +5 -2
- package/lib/typescript/commonjs/dialog/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/index.web.d.ts +5 -2
- package/lib/typescript/commonjs/dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/types.d.ts +70 -15
- package/lib/typescript/commonjs/dialog/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/fonts/FontLoader.d.ts.map +1 -1
- package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts +8 -1
- package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/fonts/font-data.web.d.ts +5 -0
- package/lib/typescript/commonjs/fonts/font-data.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +3 -3
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +3 -3
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/menu/index.d.ts +4 -4
- package/lib/typescript/commonjs/menu/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/select/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/toast/index.d.ts +32 -3
- package/lib/typescript/commonjs/toast/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/toast/index.web.d.ts +14 -7
- package/lib/typescript/commonjs/toast/index.web.d.ts.map +1 -1
- package/lib/typescript/module/bottom-sheet/index.d.ts +1 -1
- package/lib/typescript/module/context-menu/index.d.ts +4 -3
- package/lib/typescript/module/context-menu/index.d.ts.map +1 -1
- package/lib/typescript/module/dialog/BloomDialogProvider.d.ts +27 -0
- package/lib/typescript/module/dialog/BloomDialogProvider.d.ts.map +1 -0
- package/lib/typescript/module/dialog/BloomDialogProvider.web.d.ts +15 -0
- package/lib/typescript/module/dialog/BloomDialogProvider.web.d.ts.map +1 -0
- package/lib/typescript/module/dialog/Dialog.d.ts +37 -10
- package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts +26 -10
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/SheetShell.d.ts +31 -0
- package/lib/typescript/module/dialog/SheetShell.d.ts.map +1 -0
- package/lib/typescript/module/dialog/alert-store.d.ts +70 -0
- package/lib/typescript/module/dialog/alert-store.d.ts.map +1 -0
- package/lib/typescript/module/dialog/alert.d.ts +27 -0
- package/lib/typescript/module/dialog/alert.d.ts.map +1 -0
- package/lib/typescript/module/dialog/context.d.ts +7 -0
- package/lib/typescript/module/dialog/context.d.ts.map +1 -1
- package/lib/typescript/module/dialog/index.d.ts +5 -2
- package/lib/typescript/module/dialog/index.d.ts.map +1 -1
- package/lib/typescript/module/dialog/index.web.d.ts +5 -2
- package/lib/typescript/module/dialog/index.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/types.d.ts +70 -15
- package/lib/typescript/module/dialog/types.d.ts.map +1 -1
- package/lib/typescript/module/fonts/FontLoader.d.ts.map +1 -1
- package/lib/typescript/module/fonts/apply-font-faces.web.d.ts +8 -1
- package/lib/typescript/module/fonts/apply-font-faces.web.d.ts.map +1 -1
- package/lib/typescript/module/fonts/font-data.web.d.ts +5 -0
- package/lib/typescript/module/fonts/font-data.web.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +3 -3
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +3 -3
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/menu/index.d.ts +4 -4
- package/lib/typescript/module/menu/index.d.ts.map +1 -1
- package/lib/typescript/module/select/index.d.ts.map +1 -1
- package/lib/typescript/module/toast/index.d.ts +32 -3
- package/lib/typescript/module/toast/index.d.ts.map +1 -1
- package/lib/typescript/module/toast/index.web.d.ts +14 -7
- package/lib/typescript/module/toast/index.web.d.ts.map +1 -1
- package/package.json +38 -18
- package/src/__tests__/Dialog.test.tsx +177 -0
- package/src/avatar/Avatar.stories.tsx +69 -0
- package/src/bottom-sheet/BottomSheet.stories.tsx +92 -0
- package/src/bottom-sheet/index.tsx +3 -3
- package/src/button/Button.stories.tsx +94 -0
- package/src/context-menu/ContextMenu.stories.tsx +71 -0
- package/src/context-menu/index.tsx +12 -12
- package/src/dialog/BloomDialogProvider.tsx +61 -0
- package/src/dialog/BloomDialogProvider.web.tsx +46 -0
- package/src/dialog/Dialog.stories.tsx +112 -0
- package/src/dialog/Dialog.tsx +217 -64
- package/src/dialog/Dialog.web.tsx +240 -75
- package/src/dialog/SheetShell.tsx +154 -0
- package/src/dialog/alert-store.ts +126 -0
- package/src/dialog/alert.ts +42 -0
- package/src/dialog/context.ts +14 -3
- package/src/dialog/index.ts +14 -2
- package/src/dialog/index.web.ts +20 -8
- package/src/dialog/types.ts +73 -16
- package/src/fonts/FontLoader.tsx +6 -5
- package/src/fonts/apply-font-faces.ts +4 -4
- package/src/fonts/apply-font-faces.web.ts +18 -10
- package/src/fonts/font-assets.ts +2 -2
- package/src/fonts/font-data.web.ts +15 -0
- package/src/fonts/index.web.ts +4 -4
- package/src/index.ts +17 -3
- package/src/index.web.ts +17 -3
- package/src/loading/Loading.stories.tsx +60 -0
- package/src/menu/Menu.stories.tsx +79 -0
- package/src/menu/index.tsx +13 -17
- package/src/prompt-input/PromptInput.stories.tsx +82 -0
- package/src/select/Select.stories.tsx +84 -0
- package/src/select/index.tsx +30 -30
- package/src/settings-list/SettingsList.stories.tsx +106 -0
- package/src/text-field/TextField.stories.tsx +90 -0
- package/src/toast/Toast.stories.tsx +109 -0
- package/src/toast/index.tsx +55 -11
- package/src/toast/index.web.tsx +33 -13
- package/lib/commonjs/fonts/assets/BlomusModernus-Bold.woff2 +0 -0
- package/lib/commonjs/fonts/assets/BlomusModernus-Regular.woff2 +0 -0
- package/lib/commonjs/fonts/assets/GeistMono-Variable.woff2 +0 -0
- package/lib/commonjs/fonts/assets/InterVariable.woff2 +0 -0
- package/lib/commonjs/prompt/Prompt.js +0 -267
- package/lib/commonjs/prompt/Prompt.js.map +0 -1
- package/lib/commonjs/prompt/index.js +0 -61
- package/lib/commonjs/prompt/index.js.map +0 -1
- package/lib/module/fonts/assets/BlomusModernus-Bold.woff2 +0 -0
- package/lib/module/fonts/assets/BlomusModernus-Regular.woff2 +0 -0
- package/lib/module/fonts/assets/GeistMono-Variable.woff2 +0 -0
- package/lib/module/fonts/assets/InterVariable.woff2 +0 -0
- package/lib/module/prompt/Prompt.js +0 -250
- package/lib/module/prompt/Prompt.js.map +0 -1
- package/lib/module/prompt/index.js +0 -4
- package/lib/module/prompt/index.js.map +0 -1
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts +0 -5
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/BottomSheet.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/BottomSheet.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/Button.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/Button.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/Code.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/Code.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/Pre.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/Pre.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/SettingsList.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/SettingsList.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts +0 -5
- package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/theme.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/theme.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/prompt/Prompt.d.ts +0 -42
- package/lib/typescript/commonjs/prompt/Prompt.d.ts.map +0 -1
- package/lib/typescript/commonjs/prompt/index.d.ts +0 -3
- package/lib/typescript/commonjs/prompt/index.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts +0 -5
- package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/BloomThemeProvider.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/BloomThemeProvider.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/BottomSheet.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/BottomSheet.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/Button.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/Button.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/Code.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/Code.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/Pre.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/Pre.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/SettingsList.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/SettingsList.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts +0 -5
- package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/theme.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/theme.test.d.ts.map +0 -1
- package/lib/typescript/module/prompt/Prompt.d.ts +0 -42
- package/lib/typescript/module/prompt/Prompt.d.ts.map +0 -1
- package/lib/typescript/module/prompt/index.d.ts +0 -3
- package/lib/typescript/module/prompt/index.d.ts.map +0 -1
- package/src/prompt/Prompt.tsx +0 -247
- 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
|
|
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
|
|
304
|
-
// callbacks
|
|
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
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
|
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:
|
|
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 =
|
|
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
|
-
<
|
|
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
|
-
<
|
|
126
|
-
<View style={[styles.outerContent, style]}>{children}</View>
|
|
127
|
-
</Dialog.ScrollableInner>
|
|
127
|
+
<View style={[styles.outerContent, style]}>{children}</View>
|
|
128
128
|
</NativeContextMenuContext.Provider>
|
|
129
|
-
</
|
|
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
|
+
};
|