@ornikar/bumper 2.1.0 → 2.2.1-canary.431a0c996598cbee4e3c07f6b9886d37d2a76679.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/definitions/animations.d.ts +22 -0
- package/dist/definitions/animations.d.ts.map +1 -0
- package/dist/definitions/components/toast/SafeToastViewport.d.ts +9 -0
- package/dist/definitions/components/toast/SafeToastViewport.d.ts.map +1 -0
- package/dist/definitions/components/toast/ToastProvider.d.ts +10 -0
- package/dist/definitions/components/toast/ToastProvider.d.ts.map +1 -0
- package/dist/definitions/components/toast/ToastRenderer.d.ts +8 -0
- package/dist/definitions/components/toast/ToastRenderer.d.ts.map +1 -0
- package/dist/definitions/components/toast/ToastStoreProvider.d.ts +11 -0
- package/dist/definitions/components/toast/ToastStoreProvider.d.ts.map +1 -0
- package/dist/definitions/components/toast/decorators/ToastProviderDecorator.d.ts +2 -0
- package/dist/definitions/components/toast/decorators/ToastProviderDecorator.d.ts.map +1 -0
- package/dist/definitions/components/toast/types.d.ts +8 -0
- package/dist/definitions/components/toast/types.d.ts.map +1 -0
- package/dist/definitions/components/toast/useToast.d.ts +9 -0
- package/dist/definitions/components/toast/useToast.d.ts.map +1 -0
- package/dist/definitions/index.d.ts +9 -0
- package/dist/definitions/index.d.ts.map +1 -1
- package/dist/definitions/tamagui.config.d.ts +20 -1
- package/dist/definitions/tamagui.config.d.ts.map +1 -1
- package/dist/index-metro.es.android.js +284 -6
- package/dist/index-metro.es.android.js.map +1 -1
- package/dist/index-metro.es.ios.js +284 -6
- package/dist/index-metro.es.ios.js.map +1 -1
- package/dist/index-node-22.17.cjs.js +286 -2
- package/dist/index-node-22.17.cjs.js.map +1 -1
- package/dist/index-node-22.17.cjs.web.js +285 -1
- package/dist/index-node-22.17.cjs.web.js.map +1 -1
- package/dist/index-node-22.17.es.mjs +283 -5
- package/dist/index-node-22.17.es.mjs.map +1 -1
- package/dist/index-node-22.17.es.web.mjs +282 -5
- package/dist/index-node-22.17.es.web.mjs.map +1 -1
- package/dist/index.es.js +292 -6
- package/dist/index.es.js.map +1 -1
- package/dist/index.es.web.js +290 -5
- package/dist/index.es.web.js.map +1 -1
- package/dist/tsbuildinfo +1 -1
- package/package.json +20 -8
- package/src/animations.ts +25 -0
- package/src/components/toast/SafeToastViewport.tsx +26 -0
- package/src/components/toast/Toast.stories.tsx +75 -0
- package/src/components/toast/ToastProvider.tsx +33 -0
- package/src/components/toast/ToastRenderer.tsx +26 -0
- package/src/components/toast/ToastStoreProvider.tsx +41 -0
- package/src/components/toast/__snapshots__/Toast.stories.tsx.snap +146 -0
- package/src/components/toast/__snapshots_web__/Toast.stories.tsx.snap +81 -0
- package/src/components/toast/decorators/ToastProviderDecorator.tsx +23 -0
- package/src/components/toast/types.ts +9 -0
- package/src/components/toast/useToast.tsx +35 -0
- package/src/index.ts +15 -0
- package/src/tamagui.config.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ornikar/bumper",
|
|
3
|
-
"version": "2.1.0",
|
|
3
|
+
"version": "2.2.1-canary.431a0c996598cbee4e3c07f6b9886d37d2a76679.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"directory": "@ornikar/bumper",
|
|
@@ -11,9 +11,6 @@
|
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
13
13
|
"sideEffects": false,
|
|
14
|
-
"bin": {
|
|
15
|
-
"run-transformers": "./scripts/run-transformers.js"
|
|
16
|
-
},
|
|
17
14
|
"engines": {
|
|
18
15
|
"node": ">=22.17.0"
|
|
19
16
|
},
|
|
@@ -21,13 +18,27 @@
|
|
|
21
18
|
"build": "ORNIKAR_ONLY=bumper yarn ../.. build",
|
|
22
19
|
"lint:eslint": "yarn ../.. eslint --report-unused-disable-directives --quiet @ornikar/bumper"
|
|
23
20
|
},
|
|
24
|
-
"ornikar": {
|
|
21
|
+
"ornikar": {
|
|
22
|
+
"entries": [
|
|
23
|
+
"index"
|
|
24
|
+
],
|
|
25
|
+
"extraEntries": [
|
|
26
|
+
"./src/tamagui.config.ts"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
25
29
|
"dependencies": {
|
|
26
30
|
"@babel/runtime": "^7.24.0",
|
|
27
|
-
"@tamagui/
|
|
31
|
+
"@tamagui/animations-css": "1.135.6",
|
|
32
|
+
"@tamagui/animations-react-native": "1.135.6",
|
|
33
|
+
"@tamagui/core": "1.135.6",
|
|
34
|
+
"@tamagui/portal": "1.135.6",
|
|
35
|
+
"@tamagui/toast": "1.135.6",
|
|
36
|
+
"burnt": "0.12.2",
|
|
37
|
+
"react-native-safe-area-context": "4.12.0"
|
|
28
38
|
},
|
|
29
39
|
"peerDependencies": {
|
|
30
40
|
"@storybook/addons": ">=7.6.20",
|
|
41
|
+
"expo": "*",
|
|
31
42
|
"react": "^18.3.1",
|
|
32
43
|
"react-dom": "^18.3.1",
|
|
33
44
|
"react-native": ">=0.76.9"
|
|
@@ -49,7 +60,7 @@
|
|
|
49
60
|
"react": "18.3.1",
|
|
50
61
|
"react-dom": "18.3.1",
|
|
51
62
|
"react-native": "0.76.9",
|
|
52
|
-
"
|
|
63
|
+
"react-native-reanimated": "3.18.0"
|
|
53
64
|
},
|
|
54
65
|
"expo": {},
|
|
55
66
|
"exports": {
|
|
@@ -70,7 +81,8 @@
|
|
|
70
81
|
"import": "./dist/index.es.web.js"
|
|
71
82
|
}
|
|
72
83
|
},
|
|
73
|
-
"./package.json": "./package.json"
|
|
84
|
+
"./package.json": "./package.json",
|
|
85
|
+
"./src/tamagui.config.ts": "./src/tamagui.config.ts"
|
|
74
86
|
},
|
|
75
87
|
"browser": "./dist/index.es",
|
|
76
88
|
"main": "./dist/index-node-22.17.es.mjs",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createAnimations as createWebAnimations } from '@tamagui/animations-css';
|
|
2
|
+
import { createAnimations as createNativeAnimations } from '@tamagui/animations-react-native';
|
|
3
|
+
|
|
4
|
+
export const nativeAnimations = createNativeAnimations({
|
|
5
|
+
fast: {
|
|
6
|
+
damping: 20,
|
|
7
|
+
mass: 1.2,
|
|
8
|
+
stiffness: 250,
|
|
9
|
+
},
|
|
10
|
+
medium: {
|
|
11
|
+
damping: 10,
|
|
12
|
+
mass: 0.9,
|
|
13
|
+
stiffness: 100,
|
|
14
|
+
},
|
|
15
|
+
slow: {
|
|
16
|
+
damping: 20,
|
|
17
|
+
stiffness: 60,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const webAnimations = createWebAnimations({
|
|
22
|
+
fast: 'ease-in 150ms',
|
|
23
|
+
medium: 'ease-in 300ms',
|
|
24
|
+
slow: 'ease-in 450ms',
|
|
25
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ToastViewport } from '@tamagui/toast';
|
|
2
|
+
import type { ToastViewportProps } from '@tamagui/toast';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
5
|
+
|
|
6
|
+
export interface SafeToastViewportProps {
|
|
7
|
+
name?: ToastViewportProps['name'];
|
|
8
|
+
position?: 'top' | 'bottom';
|
|
9
|
+
portalToRoot?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function SafeToastViewport({ name, position = 'top', portalToRoot = false }: SafeToastViewportProps): ReactNode {
|
|
13
|
+
const { left, top, bottom, right } = useSafeAreaInsets();
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<ToastViewport
|
|
17
|
+
multipleToasts
|
|
18
|
+
portalToRoot={portalToRoot}
|
|
19
|
+
name={name}
|
|
20
|
+
top={position === 'top' ? top : undefined}
|
|
21
|
+
bottom={position === 'bottom' ? bottom : undefined}
|
|
22
|
+
left={left}
|
|
23
|
+
right={right}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { ComponentStory, Meta } from '@storybook/react';
|
|
2
|
+
import { type ReactNode } from 'react';
|
|
3
|
+
import { StorySection } from '../../story-components/StorySection';
|
|
4
|
+
import { VStack } from '../primitives/Stacks';
|
|
5
|
+
import { View } from '../primitives/View';
|
|
6
|
+
import { Typography } from '../typography/Typograhy';
|
|
7
|
+
import { ToastProvider } from './ToastProvider';
|
|
8
|
+
import { ToastStoryDecorator } from './decorators/ToastProviderDecorator';
|
|
9
|
+
import type { ToastProps } from './types';
|
|
10
|
+
import { useToast } from './useToast';
|
|
11
|
+
|
|
12
|
+
function ToastComponent(props: ToastProps) {
|
|
13
|
+
return (
|
|
14
|
+
<VStack
|
|
15
|
+
backgroundColor="$bg.highlight.default"
|
|
16
|
+
padding="$16"
|
|
17
|
+
borderRadius="$space.4"
|
|
18
|
+
height="$space.56"
|
|
19
|
+
justifyContent="center"
|
|
20
|
+
>
|
|
21
|
+
<Typography.Text variant="body-l" weight="bold">
|
|
22
|
+
{props.title}
|
|
23
|
+
</Typography.Text>
|
|
24
|
+
{props.description && <Typography.Text>{props.description}</Typography.Text>}
|
|
25
|
+
</VStack>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function ToastTrigger(): ReactNode {
|
|
30
|
+
const { showToast } = useToast();
|
|
31
|
+
|
|
32
|
+
const showExampleToast = () => {
|
|
33
|
+
showToast({
|
|
34
|
+
title: 'Example Toast',
|
|
35
|
+
description: 'This is an example of a toast message.',
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const showExampleToast2 = () => {
|
|
40
|
+
showToast({
|
|
41
|
+
title: 'Example Toast 2',
|
|
42
|
+
description: 'This is an other example of a toast message.',
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<View onPress={showExampleToast}>
|
|
48
|
+
<Typography.Text>Show Toast</Typography.Text>
|
|
49
|
+
</View>
|
|
50
|
+
<View onPress={showExampleToast2}>
|
|
51
|
+
<Typography.Text>Show Toast 2</Typography.Text>
|
|
52
|
+
</View>
|
|
53
|
+
</>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default {
|
|
58
|
+
title: 'bumper/Toast',
|
|
59
|
+
component: ToastProvider,
|
|
60
|
+
decorators: [ToastStoryDecorator],
|
|
61
|
+
} satisfies Meta<typeof ToastProvider>;
|
|
62
|
+
|
|
63
|
+
export const ToastProviderStory: ComponentStory<typeof ToastProvider> = () => (
|
|
64
|
+
<StorySection.Demo>
|
|
65
|
+
<ToastTrigger />
|
|
66
|
+
</StorySection.Demo>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
ToastProviderStory.storyName = 'Toast';
|
|
70
|
+
ToastProviderStory.parameters = {
|
|
71
|
+
toast: {
|
|
72
|
+
position: 'top',
|
|
73
|
+
component: ToastComponent,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PortalProvider } from '@tamagui/portal';
|
|
2
|
+
import { ToastProvider as TamaguiToastProvider } from '@tamagui/toast';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
import { SafeToastViewport } from './SafeToastViewport';
|
|
5
|
+
import { ToastRenderer } from './ToastRenderer';
|
|
6
|
+
import { ToastStoreProvider } from './ToastStoreProvider';
|
|
7
|
+
import type { ToastProps } from './types';
|
|
8
|
+
|
|
9
|
+
export interface ToastProviderProps {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
position?: 'top' | 'bottom';
|
|
12
|
+
viewportName?: string;
|
|
13
|
+
ToastComponent: React.ComponentType<ToastProps>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function ToastProvider({
|
|
17
|
+
children,
|
|
18
|
+
position = 'top',
|
|
19
|
+
viewportName,
|
|
20
|
+
ToastComponent,
|
|
21
|
+
}: ToastProviderProps): ReactNode {
|
|
22
|
+
return (
|
|
23
|
+
<PortalProvider>
|
|
24
|
+
<TamaguiToastProvider swipeDirection="horizontal">
|
|
25
|
+
<ToastStoreProvider>
|
|
26
|
+
{children}
|
|
27
|
+
<SafeToastViewport portalToRoot name={viewportName} position={position} />
|
|
28
|
+
<ToastRenderer ToastComponent={ToastComponent} />
|
|
29
|
+
</ToastStoreProvider>
|
|
30
|
+
</TamaguiToastProvider>
|
|
31
|
+
</PortalProvider>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Toast } from '@tamagui/toast';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import type { ToastProps } from './types';
|
|
5
|
+
import { useToast } from './useToast';
|
|
6
|
+
|
|
7
|
+
interface ToastRendererProps {
|
|
8
|
+
ToastComponent: React.ComponentType<ToastProps>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ToastRenderer({ ToastComponent }: ToastRendererProps): ReactNode {
|
|
12
|
+
const { toasts, hideToast: removeToast } = useToast();
|
|
13
|
+
|
|
14
|
+
const hideToast = useCallback(
|
|
15
|
+
(id: string) => () => {
|
|
16
|
+
removeToast(id);
|
|
17
|
+
},
|
|
18
|
+
[removeToast],
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return toasts.map((toast) => (
|
|
22
|
+
<Toast key={toast.id} id={toast.id} duration={toast.timeout} viewportName={toast.viewportName}>
|
|
23
|
+
<ToastComponent {...toast} hideToast={hideToast(toast.id)} />
|
|
24
|
+
</Toast>
|
|
25
|
+
));
|
|
26
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { PropsWithChildren, ReactNode } from 'react';
|
|
2
|
+
import { createContext, useCallback, useContext, useMemo, useState } from 'react';
|
|
3
|
+
import type { ToastOptions } from './types';
|
|
4
|
+
|
|
5
|
+
interface ToastStore {
|
|
6
|
+
toasts: ToastOptions[];
|
|
7
|
+
addToast: (toast: ToastOptions) => void;
|
|
8
|
+
removeToast: (id: string) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const useToastState = (): ToastStore => {
|
|
12
|
+
const [toasts, setToasts] = useState<ToastOptions[]>([]);
|
|
13
|
+
|
|
14
|
+
const removeToast = useCallback((id: string) => {
|
|
15
|
+
setToasts((prevToasts) => prevToasts.filter((t) => t.id !== id));
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
const addToast = useCallback((toast: ToastOptions) => {
|
|
19
|
+
setToasts((prevToasts) => [...prevToasts, toast]);
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
return { toasts, addToast, removeToast };
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const ToastStoreContext = createContext<ToastStore | undefined>(undefined);
|
|
26
|
+
|
|
27
|
+
export function ToastStoreProvider({ children }: PropsWithChildren): ReactNode {
|
|
28
|
+
const { toasts, addToast, removeToast } = useToastState();
|
|
29
|
+
|
|
30
|
+
const value = useMemo(() => ({ toasts, addToast, removeToast }), [toasts, addToast, removeToast]);
|
|
31
|
+
|
|
32
|
+
return <ToastStoreContext.Provider value={value}>{children}</ToastStoreContext.Provider>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const useToastStore = (): ToastStore => {
|
|
36
|
+
const context = useContext(ToastStoreContext);
|
|
37
|
+
if (!context) {
|
|
38
|
+
throw new Error('useToastStore must be used within a ToastStoreProvider');
|
|
39
|
+
}
|
|
40
|
+
return context;
|
|
41
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
|
2
|
+
|
|
3
|
+
exports[`bumper/Toast Toast 1`] = `
|
|
4
|
+
<RNCSafeAreaProvider
|
|
5
|
+
onInsetsChange={[Function]}
|
|
6
|
+
style={
|
|
7
|
+
[
|
|
8
|
+
{
|
|
9
|
+
"flex": 1,
|
|
10
|
+
},
|
|
11
|
+
undefined,
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
>
|
|
15
|
+
<RNCSafeAreaProvider
|
|
16
|
+
onInsetsChange={[Function]}
|
|
17
|
+
style={
|
|
18
|
+
[
|
|
19
|
+
{
|
|
20
|
+
"flex": 1,
|
|
21
|
+
},
|
|
22
|
+
undefined,
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
>
|
|
26
|
+
<View
|
|
27
|
+
style={
|
|
28
|
+
{
|
|
29
|
+
"flexDirection": "column",
|
|
30
|
+
"paddingBottom": 12,
|
|
31
|
+
"paddingLeft": 4,
|
|
32
|
+
"paddingRight": 4,
|
|
33
|
+
"paddingTop": 4,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
>
|
|
37
|
+
<Text
|
|
38
|
+
style={
|
|
39
|
+
{
|
|
40
|
+
"fontFamily": "GTStandardSemibold",
|
|
41
|
+
"fontSize": 38,
|
|
42
|
+
"letterSpacing": 0,
|
|
43
|
+
"lineHeight": 48,
|
|
44
|
+
"marginBottom": 4,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
suppressHighlighting={true}
|
|
48
|
+
>
|
|
49
|
+
Demo
|
|
50
|
+
</Text>
|
|
51
|
+
<View
|
|
52
|
+
onBlur={[Function]}
|
|
53
|
+
onClick={[Function]}
|
|
54
|
+
onFocus={[Function]}
|
|
55
|
+
onResponderGrant={[Function]}
|
|
56
|
+
onResponderMove={[Function]}
|
|
57
|
+
onResponderRelease={[Function]}
|
|
58
|
+
onResponderTerminate={[Function]}
|
|
59
|
+
onResponderTerminationRequest={[Function]}
|
|
60
|
+
onStartShouldSetResponder={[Function]}
|
|
61
|
+
>
|
|
62
|
+
<Text
|
|
63
|
+
style={
|
|
64
|
+
{
|
|
65
|
+
"fontFamily": "GTStandard",
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
suppressHighlighting={true}
|
|
69
|
+
>
|
|
70
|
+
Show Toast
|
|
71
|
+
</Text>
|
|
72
|
+
</View>
|
|
73
|
+
<View
|
|
74
|
+
onBlur={[Function]}
|
|
75
|
+
onClick={[Function]}
|
|
76
|
+
onFocus={[Function]}
|
|
77
|
+
onResponderGrant={[Function]}
|
|
78
|
+
onResponderMove={[Function]}
|
|
79
|
+
onResponderRelease={[Function]}
|
|
80
|
+
onResponderTerminate={[Function]}
|
|
81
|
+
onResponderTerminationRequest={[Function]}
|
|
82
|
+
onStartShouldSetResponder={[Function]}
|
|
83
|
+
>
|
|
84
|
+
<Text
|
|
85
|
+
style={
|
|
86
|
+
{
|
|
87
|
+
"fontFamily": "GTStandard",
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
suppressHighlighting={true}
|
|
91
|
+
>
|
|
92
|
+
Show Toast 2
|
|
93
|
+
</Text>
|
|
94
|
+
</View>
|
|
95
|
+
</View>
|
|
96
|
+
<View
|
|
97
|
+
pointerEvents="box-none"
|
|
98
|
+
style={
|
|
99
|
+
{
|
|
100
|
+
"bottom": 0,
|
|
101
|
+
"left": 0,
|
|
102
|
+
"maxWidth": "100%",
|
|
103
|
+
"position": "absolute",
|
|
104
|
+
"right": 0,
|
|
105
|
+
"top": 0,
|
|
106
|
+
"zIndex": 9007199254740991,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
>
|
|
110
|
+
<View
|
|
111
|
+
aria-label="Notifications (F8)"
|
|
112
|
+
pointerEvents="box-none"
|
|
113
|
+
role="region"
|
|
114
|
+
style={
|
|
115
|
+
{
|
|
116
|
+
"bottom": 0,
|
|
117
|
+
"flexDirection": "column",
|
|
118
|
+
"left": 0,
|
|
119
|
+
"maxWidth": "100%",
|
|
120
|
+
"position": "absolute",
|
|
121
|
+
"right": 0,
|
|
122
|
+
"top": 0,
|
|
123
|
+
"zIndex": 100000,
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
tabIndex={-1}
|
|
127
|
+
>
|
|
128
|
+
<View
|
|
129
|
+
focusable={false}
|
|
130
|
+
pointerEvents="box-none"
|
|
131
|
+
style={
|
|
132
|
+
{
|
|
133
|
+
"flexDirection": "column",
|
|
134
|
+
"left": 0,
|
|
135
|
+
"maxWidth": "100%",
|
|
136
|
+
"position": "absolute",
|
|
137
|
+
"right": 0,
|
|
138
|
+
"top": 0,
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/>
|
|
142
|
+
</View>
|
|
143
|
+
</View>
|
|
144
|
+
</RNCSafeAreaProvider>
|
|
145
|
+
</RNCSafeAreaProvider>
|
|
146
|
+
`;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
|
2
|
+
|
|
3
|
+
exports[`bumper/Toast Toast 1`] = `
|
|
4
|
+
<DocumentFragment>
|
|
5
|
+
<div
|
|
6
|
+
class="css-view-175oi2r r-flex-13awgt0"
|
|
7
|
+
>
|
|
8
|
+
<span
|
|
9
|
+
class=""
|
|
10
|
+
style="display: contents;"
|
|
11
|
+
>
|
|
12
|
+
<span
|
|
13
|
+
class=" "
|
|
14
|
+
style="display: contents;"
|
|
15
|
+
>
|
|
16
|
+
<span
|
|
17
|
+
class=" t_light is_Theme"
|
|
18
|
+
style="display: contents;"
|
|
19
|
+
>
|
|
20
|
+
<div
|
|
21
|
+
class="css-view-175oi2r r-flex-13awgt0"
|
|
22
|
+
>
|
|
23
|
+
<div
|
|
24
|
+
class="is_VStack _display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _paddingTop-t-space-4 _paddingBottom-t-space-12 _paddingRight-t-space-4 _paddingLeft-t-space-4"
|
|
25
|
+
>
|
|
26
|
+
<span
|
|
27
|
+
class="font_GTStandard _WebkitFontSmoothing-_platformweb_antialiased _display-inline _boxSizing-border-box _wordWrap-break-word _whiteSpace-pre-wrap _marginTop-0px _marginRight-0px _marginBottom-t-space-4 _marginLeft-0px _fontFamily-f-family _fontSize-f-size-head100347201 _lineHeight-f-lineHeigh1544154440 _letterSpacing-f-letterSpa1195674547 _fontWeight-f-weight-se1074390495"
|
|
28
|
+
data-disable-theme="true"
|
|
29
|
+
>
|
|
30
|
+
Demo
|
|
31
|
+
</span>
|
|
32
|
+
<div
|
|
33
|
+
class="_display-flex _alignItems-stretch _flexDirection-column _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0"
|
|
34
|
+
>
|
|
35
|
+
<span
|
|
36
|
+
class="font_GTStandard _WebkitFontSmoothing-_platformweb_antialiased _display-inline _boxSizing-border-box _wordWrap-break-word _whiteSpace-pre-wrap _marginTop-0px _marginRight-0px _marginBottom-0px _marginLeft-0px _fontFamily-f-family"
|
|
37
|
+
data-disable-theme="true"
|
|
38
|
+
>
|
|
39
|
+
Show Toast
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
<div
|
|
43
|
+
class="_display-flex _alignItems-stretch _flexDirection-column _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0"
|
|
44
|
+
>
|
|
45
|
+
<span
|
|
46
|
+
class="font_GTStandard _WebkitFontSmoothing-_platformweb_antialiased _display-inline _boxSizing-border-box _wordWrap-break-word _whiteSpace-pre-wrap _marginTop-0px _marginRight-0px _marginBottom-0px _marginLeft-0px _fontFamily-f-family"
|
|
47
|
+
data-disable-theme="true"
|
|
48
|
+
>
|
|
49
|
+
Show Toast 2
|
|
50
|
+
</span>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<span
|
|
54
|
+
style="z-index: 9007199254740991; position: fixed; inset: 0; contain: strict; pointer-events: none;"
|
|
55
|
+
>
|
|
56
|
+
<div
|
|
57
|
+
aria-label="Notifications (F8)"
|
|
58
|
+
class="is_ViewportWrapper _display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-fixed _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _pointerEvents-box-none _top-0px _bottom-0px _left-0px _right-0px _maxWidth-10037 _zIndex-100000"
|
|
59
|
+
role="region"
|
|
60
|
+
tabindex="-1"
|
|
61
|
+
>
|
|
62
|
+
<div
|
|
63
|
+
class="is_ToastViewport _display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-fixed _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _pointerEvents-box-none _maxWidth-10037 _top-0px _left-0px _right-0px"
|
|
64
|
+
tabindex="-1"
|
|
65
|
+
>
|
|
66
|
+
<div
|
|
67
|
+
style="display: contents;"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</span>
|
|
72
|
+
<div
|
|
73
|
+
style="display: contents;"
|
|
74
|
+
/>
|
|
75
|
+
</div>
|
|
76
|
+
</span>
|
|
77
|
+
</span>
|
|
78
|
+
</span>
|
|
79
|
+
</div>
|
|
80
|
+
</DocumentFragment>
|
|
81
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { makeDecorator } from '@storybook/addons';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
4
|
+
import { ToastProvider } from '../ToastProvider';
|
|
5
|
+
|
|
6
|
+
export const ToastStoryDecorator = makeDecorator({
|
|
7
|
+
name: 'ToastStoryDecorator',
|
|
8
|
+
parameterName: 'toast',
|
|
9
|
+
wrapper: (storyFn, context): ReactNode => {
|
|
10
|
+
const story = storyFn(context) as unknown as ReactNode;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<SafeAreaProvider>
|
|
14
|
+
<ToastProvider
|
|
15
|
+
ToastComponent={context.parameters.toast.component || null}
|
|
16
|
+
position={context.parameters.toast?.position || 'top'}
|
|
17
|
+
>
|
|
18
|
+
{story}
|
|
19
|
+
</ToastProvider>
|
|
20
|
+
</SafeAreaProvider>
|
|
21
|
+
);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useToastStore } from './ToastStoreProvider';
|
|
3
|
+
import type { ToastOptions } from './types';
|
|
4
|
+
|
|
5
|
+
interface UseToastReturn {
|
|
6
|
+
toasts: ToastOptions[];
|
|
7
|
+
showToast: (options: ToastOptions) => void;
|
|
8
|
+
hideToast: (id: string) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useToast(): UseToastReturn {
|
|
12
|
+
const { toasts, addToast, removeToast } = useToastStore();
|
|
13
|
+
|
|
14
|
+
const showToast = useCallback(
|
|
15
|
+
(options: ToastOptions): void => {
|
|
16
|
+
const { title, ...otherOptions } = options;
|
|
17
|
+
const id = `${JSON.stringify(options)}${Math.random()}`;
|
|
18
|
+
addToast({ id, title, ...otherOptions });
|
|
19
|
+
},
|
|
20
|
+
[addToast],
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const hideToast = useCallback(
|
|
24
|
+
(id: string): void => {
|
|
25
|
+
removeToast(id);
|
|
26
|
+
},
|
|
27
|
+
[removeToast],
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
toasts,
|
|
32
|
+
showToast,
|
|
33
|
+
hideToast,
|
|
34
|
+
};
|
|
35
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
export { BumperDecorator } from './core/BumperDecorator';
|
|
2
2
|
export { BumperProvider } from './core/BumperProvider';
|
|
3
3
|
|
|
4
|
+
// Primitives
|
|
5
|
+
export type { HStackProps, StackProps, VStackProps } from './components/primitives/Stacks';
|
|
6
|
+
export { HStack, Stack, VStack } from './components/primitives/Stacks';
|
|
7
|
+
export type { ViewProps } from './components/primitives/View';
|
|
8
|
+
export { View } from './components/primitives/View';
|
|
9
|
+
|
|
10
|
+
// Typography
|
|
11
|
+
export type { TypographyTextProps } from './components/typography/Typograhy';
|
|
12
|
+
export { Typography } from './components/typography/Typograhy';
|
|
13
|
+
|
|
4
14
|
// Breakpoints
|
|
5
15
|
export { useBreakpointValue } from './components/breakpoints/hooks/useBreakpointValue';
|
|
6
16
|
export { useCurrentBreakpointName } from './components/breakpoints/hooks/useCurrentBreakpointName';
|
|
@@ -9,3 +19,8 @@ export type { SwitchBreakpointsProps } from './components/breakpoints/SwitchBrea
|
|
|
9
19
|
export { SwitchBreakpoints } from './components/breakpoints/SwitchBreakpoins';
|
|
10
20
|
export type { ValueForBreakpoint } from './components/breakpoints/utils/breakpointsUtils';
|
|
11
21
|
export { getValueForBreakpoint } from './components/breakpoints/utils/breakpointsUtils';
|
|
22
|
+
|
|
23
|
+
// Toast
|
|
24
|
+
export { SafeToastViewport as ToastViewport } from './components/toast/SafeToastViewport';
|
|
25
|
+
export { ToastProvider } from './components/toast/ToastProvider';
|
|
26
|
+
export { useToast } from './components/toast/useToast';
|
package/src/tamagui.config.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createTamagui, createTokens } from '@tamagui/core';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import { nativeAnimations, webAnimations } from './animations';
|
|
2
4
|
import { light } from './themes/light';
|
|
3
5
|
import { BreakpointNameEnum, breakpoints } from './themes/utils/breakpoints';
|
|
4
6
|
import { fonts } from './tokens/fonts';
|
|
@@ -33,6 +35,7 @@ export const config = createTamagui({
|
|
|
33
35
|
autocompleteSpecificTokens: true,
|
|
34
36
|
debug: false,
|
|
35
37
|
},
|
|
38
|
+
animations: Platform.OS === 'web' ? webAnimations : nativeAnimations,
|
|
36
39
|
});
|
|
37
40
|
|
|
38
41
|
type Conf = typeof config;
|