@cdx-ui/components 0.0.1-beta.79 → 0.0.1-beta.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/animation/hooks/index.js +17 -0
- package/lib/commonjs/animation/hooks/index.js.map +1 -0
- package/lib/commonjs/animation/hooks/useCombinedAnimationDisabledState.js +50 -0
- package/lib/commonjs/animation/hooks/useCombinedAnimationDisabledState.js.map +1 -0
- package/lib/commonjs/animation/index.js +39 -0
- package/lib/commonjs/animation/index.js.map +1 -0
- package/lib/commonjs/animation/types.js +6 -0
- package/lib/commonjs/animation/types.js.map +1 -0
- package/lib/commonjs/animation/utils.js +223 -0
- package/lib/commonjs/animation/utils.js.map +1 -0
- package/lib/commonjs/components/CLAUDE.md +1 -1
- package/lib/commonjs/components/Card/index.js +45 -17
- package/lib/commonjs/components/Card/index.js.map +1 -1
- package/lib/commonjs/components/Toast/animation.js +329 -0
- package/lib/commonjs/components/Toast/animation.js.map +1 -0
- package/lib/commonjs/components/Toast/hooks.js +66 -0
- package/lib/commonjs/components/Toast/hooks.js.map +1 -0
- package/lib/commonjs/components/Toast/index.js +493 -0
- package/lib/commonjs/components/Toast/index.js.map +1 -0
- package/lib/commonjs/components/Toast/styles.js +141 -0
- package/lib/commonjs/components/Toast/styles.js.map +1 -0
- package/lib/commonjs/components/Toast/types.js +6 -0
- package/lib/commonjs/components/Toast/types.js.map +1 -0
- package/lib/commonjs/components/index.js +12 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/index.js +15 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/providers/animation-settings/index.js +31 -0
- package/lib/commonjs/providers/animation-settings/index.js.map +1 -0
- package/lib/commonjs/providers/animation-settings/provider.js +59 -0
- package/lib/commonjs/providers/animation-settings/provider.js.map +1 -0
- package/lib/commonjs/providers/animation-settings/types.js +6 -0
- package/lib/commonjs/providers/animation-settings/types.js.map +1 -0
- package/lib/commonjs/providers/forge-design/index.js +29 -0
- package/lib/commonjs/providers/forge-design/index.js.map +1 -0
- package/lib/commonjs/providers/forge-design/provider.js +71 -0
- package/lib/commonjs/providers/forge-design/provider.js.map +1 -0
- package/lib/commonjs/providers/forge-design/types.js +6 -0
- package/lib/commonjs/providers/forge-design/types.js.map +1 -0
- package/lib/commonjs/providers/text-component/index.js +28 -0
- package/lib/commonjs/providers/text-component/index.js.map +1 -0
- package/lib/commonjs/providers/text-component/provider.js +11 -0
- package/lib/commonjs/providers/text-component/provider.js.map +1 -0
- package/lib/commonjs/providers/text-component/types.js +6 -0
- package/lib/commonjs/providers/text-component/types.js.map +1 -0
- package/lib/commonjs/providers/toast/index.js +33 -0
- package/lib/commonjs/providers/toast/index.js.map +1 -0
- package/lib/commonjs/providers/toast/insets-container.js +160 -0
- package/lib/commonjs/providers/toast/insets-container.js.map +1 -0
- package/lib/commonjs/providers/toast/lifecycle.context.js +36 -0
- package/lib/commonjs/providers/toast/lifecycle.context.js.map +1 -0
- package/lib/commonjs/providers/toast/provider.js +508 -0
- package/lib/commonjs/providers/toast/provider.js.map +1 -0
- package/lib/commonjs/providers/toast/reducer.js +46 -0
- package/lib/commonjs/providers/toast/reducer.js.map +1 -0
- package/lib/commonjs/providers/toast/toast-config.context.js +29 -0
- package/lib/commonjs/providers/toast/toast-config.context.js.map +1 -0
- package/lib/commonjs/providers/toast/toast-item-renderer.js +43 -0
- package/lib/commonjs/providers/toast/toast-item-renderer.js.map +1 -0
- package/lib/commonjs/providers/toast/types.js +6 -0
- package/lib/commonjs/providers/toast/types.js.map +1 -0
- package/lib/module/animation/hooks/index.js +4 -0
- package/lib/module/animation/hooks/index.js.map +1 -0
- package/lib/module/animation/hooks/useCombinedAnimationDisabledState.js +47 -0
- package/lib/module/animation/hooks/useCombinedAnimationDisabledState.js.map +1 -0
- package/lib/module/animation/index.js +6 -0
- package/lib/module/animation/index.js.map +1 -0
- package/lib/module/animation/types.js +4 -0
- package/lib/module/animation/types.js.map +1 -0
- package/lib/module/animation/utils.js +212 -0
- package/lib/module/animation/utils.js.map +1 -0
- package/lib/module/components/CLAUDE.md +1 -1
- package/lib/module/components/Card/index.js +47 -19
- package/lib/module/components/Card/index.js.map +1 -1
- package/lib/module/components/Toast/animation.js +324 -0
- package/lib/module/components/Toast/animation.js.map +1 -0
- package/lib/module/components/Toast/hooks.js +61 -0
- package/lib/module/components/Toast/hooks.js.map +1 -0
- package/lib/module/components/Toast/index.js +487 -0
- package/lib/module/components/Toast/index.js.map +1 -0
- package/lib/module/components/Toast/styles.js +138 -0
- package/lib/module/components/Toast/styles.js.map +1 -0
- package/lib/module/components/Toast/types.js +4 -0
- package/lib/module/components/Toast/types.js.map +1 -0
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/providers/animation-settings/index.js +4 -0
- package/lib/module/providers/animation-settings/index.js.map +1 -0
- package/lib/module/providers/animation-settings/provider.js +52 -0
- package/lib/module/providers/animation-settings/provider.js.map +1 -0
- package/lib/module/providers/animation-settings/types.js +4 -0
- package/lib/module/providers/animation-settings/types.js.map +1 -0
- package/lib/module/providers/forge-design/index.js +5 -0
- package/lib/module/providers/forge-design/index.js.map +1 -0
- package/lib/module/providers/forge-design/provider.js +66 -0
- package/lib/module/providers/forge-design/provider.js.map +1 -0
- package/lib/module/providers/forge-design/types.js +4 -0
- package/lib/module/providers/forge-design/types.js.map +1 -0
- package/lib/module/providers/text-component/index.js +5 -0
- package/lib/module/providers/text-component/index.js.map +1 -0
- package/lib/module/providers/text-component/provider.js +6 -0
- package/lib/module/providers/text-component/provider.js.map +1 -0
- package/lib/module/providers/text-component/types.js +4 -0
- package/lib/module/providers/text-component/types.js.map +1 -0
- package/lib/module/providers/toast/index.js +6 -0
- package/lib/module/providers/toast/index.js.map +1 -0
- package/lib/module/providers/toast/insets-container.js +156 -0
- package/lib/module/providers/toast/insets-container.js.map +1 -0
- package/lib/module/providers/toast/lifecycle.context.js +32 -0
- package/lib/module/providers/toast/lifecycle.context.js.map +1 -0
- package/lib/module/providers/toast/provider.js +503 -0
- package/lib/module/providers/toast/provider.js.map +1 -0
- package/lib/module/providers/toast/reducer.js +42 -0
- package/lib/module/providers/toast/reducer.js.map +1 -0
- package/lib/module/providers/toast/toast-config.context.js +25 -0
- package/lib/module/providers/toast/toast-config.context.js.map +1 -0
- package/lib/module/providers/toast/toast-item-renderer.js +39 -0
- package/lib/module/providers/toast/toast-item-renderer.js.map +1 -0
- package/lib/module/providers/toast/types.js +4 -0
- package/lib/module/providers/toast/types.js.map +1 -0
- package/lib/typescript/animation/hooks/index.d.ts +2 -0
- package/lib/typescript/animation/hooks/index.d.ts.map +1 -0
- package/lib/typescript/animation/hooks/useCombinedAnimationDisabledState.d.ts +22 -0
- package/lib/typescript/animation/hooks/useCombinedAnimationDisabledState.d.ts.map +1 -0
- package/lib/typescript/animation/index.d.ts +4 -0
- package/lib/typescript/animation/index.d.ts.map +1 -0
- package/lib/typescript/animation/types.d.ts +105 -0
- package/lib/typescript/animation/types.d.ts.map +1 -0
- package/lib/typescript/animation/utils.d.ts +120 -0
- package/lib/typescript/animation/utils.d.ts.map +1 -0
- package/lib/typescript/components/Card/index.d.ts +4 -0
- package/lib/typescript/components/Card/index.d.ts.map +1 -1
- package/lib/typescript/components/Toast/animation.d.ts +21 -0
- package/lib/typescript/components/Toast/animation.d.ts.map +1 -0
- package/lib/typescript/components/Toast/hooks.d.ts +17 -0
- package/lib/typescript/components/Toast/hooks.d.ts.map +1 -0
- package/lib/typescript/components/Toast/index.d.ts +28 -0
- package/lib/typescript/components/Toast/index.d.ts.map +1 -0
- package/lib/typescript/components/Toast/styles.d.ts +73 -0
- package/lib/typescript/components/Toast/styles.d.ts.map +1 -0
- package/lib/typescript/components/Toast/types.d.ts +303 -0
- package/lib/typescript/components/Toast/types.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/providers/animation-settings/index.d.ts +3 -0
- package/lib/typescript/providers/animation-settings/index.d.ts.map +1 -0
- package/lib/typescript/providers/animation-settings/provider.d.ts +28 -0
- package/lib/typescript/providers/animation-settings/provider.d.ts.map +1 -0
- package/lib/typescript/providers/animation-settings/types.d.ts +35 -0
- package/lib/typescript/providers/animation-settings/types.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/index.d.ts +3 -0
- package/lib/typescript/providers/forge-design/index.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/provider.d.ts +24 -0
- package/lib/typescript/providers/forge-design/provider.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/types.d.ts +82 -0
- package/lib/typescript/providers/forge-design/types.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/index.d.ts +3 -0
- package/lib/typescript/providers/text-component/index.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/provider.d.ts +7 -0
- package/lib/typescript/providers/text-component/provider.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/types.d.ts +51 -0
- package/lib/typescript/providers/text-component/types.d.ts.map +1 -0
- package/lib/typescript/providers/toast/index.d.ts +5 -0
- package/lib/typescript/providers/toast/index.d.ts.map +1 -0
- package/lib/typescript/providers/toast/insets-container.d.ts +72 -0
- package/lib/typescript/providers/toast/insets-container.d.ts.map +1 -0
- package/lib/typescript/providers/toast/lifecycle.context.d.ts +32 -0
- package/lib/typescript/providers/toast/lifecycle.context.d.ts.map +1 -0
- package/lib/typescript/providers/toast/provider.d.ts +32 -0
- package/lib/typescript/providers/toast/provider.d.ts.map +1 -0
- package/lib/typescript/providers/toast/reducer.d.ts +14 -0
- package/lib/typescript/providers/toast/reducer.d.ts.map +1 -0
- package/lib/typescript/providers/toast/toast-config.context.d.ts +20 -0
- package/lib/typescript/providers/toast/toast-config.context.d.ts.map +1 -0
- package/lib/typescript/providers/toast/toast-item-renderer.d.ts +7 -0
- package/lib/typescript/providers/toast/toast-item-renderer.d.ts.map +1 -0
- package/lib/typescript/providers/toast/types.d.ts +422 -0
- package/lib/typescript/providers/toast/types.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/animation/hooks/index.ts +1 -0
- package/src/animation/hooks/useCombinedAnimationDisabledState.ts +46 -0
- package/src/animation/index.ts +3 -0
- package/src/animation/types.ts +128 -0
- package/src/animation/utils.ts +249 -0
- package/src/components/CLAUDE.md +1 -1
- package/src/components/Card/index.tsx +58 -28
- package/src/components/Toast/animation.ts +387 -0
- package/src/components/Toast/hooks.ts +92 -0
- package/src/components/Toast/index.tsx +520 -0
- package/src/components/Toast/styles.ts +186 -0
- package/src/components/Toast/types.ts +332 -0
- package/src/components/index.ts +1 -0
- package/src/index.ts +2 -0
- package/src/providers/animation-settings/index.ts +11 -0
- package/src/providers/animation-settings/provider.tsx +54 -0
- package/src/providers/animation-settings/types.ts +37 -0
- package/src/providers/forge-design/index.ts +2 -0
- package/src/providers/forge-design/provider.tsx +61 -0
- package/src/providers/forge-design/types.ts +84 -0
- package/src/providers/text-component/index.ts +2 -0
- package/src/providers/text-component/provider.tsx +7 -0
- package/src/providers/text-component/types.ts +52 -0
- package/src/providers/toast/index.ts +4 -0
- package/src/providers/toast/insets-container.tsx +230 -0
- package/src/providers/toast/lifecycle.context.tsx +37 -0
- package/src/providers/toast/provider.tsx +567 -0
- package/src/providers/toast/reducer.ts +40 -0
- package/src/providers/toast/toast-config.context.ts +25 -0
- package/src/providers/toast/toast-item-renderer.tsx +40 -0
- package/src/providers/toast/types.ts +431 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Platform, View } from 'react-native';
|
|
3
|
+
import { GestureDetector } from 'react-native-gesture-handler';
|
|
4
|
+
import Animated from 'react-native-reanimated';
|
|
5
|
+
import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
|
|
6
|
+
import { CloseIcon } from '@cdx-ui/icons';
|
|
7
|
+
import {
|
|
8
|
+
ToastRoot as ToastRootPrimitive,
|
|
9
|
+
useToastContext,
|
|
10
|
+
Slot,
|
|
11
|
+
dataAttributes,
|
|
12
|
+
mergeDataAttributes,
|
|
13
|
+
} from '@cdx-ui/primitives';
|
|
14
|
+
import { AnimationSettingsProvider } from '../../providers/animation-settings';
|
|
15
|
+
import type { ToastComponentProps } from '../../providers/toast';
|
|
16
|
+
import { useToastLifecycle } from '../../providers/toast/lifecycle.context';
|
|
17
|
+
import { useToastConfig } from '../../providers/toast/toast-config.context';
|
|
18
|
+
import { Button } from '../Button';
|
|
19
|
+
import { Text } from '../Text';
|
|
20
|
+
import { Icon } from '../Icon';
|
|
21
|
+
import { IconButton } from '../IconButton';
|
|
22
|
+
import { useToastRootAnimation } from './animation';
|
|
23
|
+
import { useButtonColor, useVerticalPlaceholderStyles } from './hooks';
|
|
24
|
+
import {
|
|
25
|
+
toastRootVariants,
|
|
26
|
+
toastLabelVariants,
|
|
27
|
+
toastDescriptionVariants,
|
|
28
|
+
toastIconVariants,
|
|
29
|
+
toastStyleSheet,
|
|
30
|
+
toastWrapperVariants,
|
|
31
|
+
} from './styles';
|
|
32
|
+
import type {
|
|
33
|
+
DefaultToastProps,
|
|
34
|
+
ToastActionProps,
|
|
35
|
+
ToastCloseProps,
|
|
36
|
+
ToastContextValue,
|
|
37
|
+
ToastDescriptionProps,
|
|
38
|
+
ToastIconProps,
|
|
39
|
+
ToastProps,
|
|
40
|
+
ToastTitleProps,
|
|
41
|
+
} from './types';
|
|
42
|
+
|
|
43
|
+
const SCOPE = 'TOAST';
|
|
44
|
+
|
|
45
|
+
const useToastStyleContext = () => useStyleContext(SCOPE) as ToastContextValue;
|
|
46
|
+
|
|
47
|
+
const AnimatedToastRoot = Animated.createAnimatedComponent(ToastRootPrimitive);
|
|
48
|
+
|
|
49
|
+
const IS_WEB = Platform.OS === 'web';
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Fallback timeout for web exit transitions. Covers cases where
|
|
53
|
+
* `transitionend` never fires — `prefers-reduced-motion: reduce`
|
|
54
|
+
* collapsing the transition, a backgrounded tab, or the element being
|
|
55
|
+
* hidden before it triggers. Longer than the longest CSS transition
|
|
56
|
+
* (200ms enter / 150ms exit) plus a ~100ms buffer.
|
|
57
|
+
*/
|
|
58
|
+
const WEB_TRANSITION_SAFETY_MS = 300;
|
|
59
|
+
|
|
60
|
+
type ToastDataState = 'entering' | 'open' | 'closed';
|
|
61
|
+
|
|
62
|
+
// --------------------------------------------------
|
|
63
|
+
|
|
64
|
+
const ToastRoot = forwardRef<View, ToastProps>((props, ref) => {
|
|
65
|
+
const globalConfig = useToastConfig();
|
|
66
|
+
|
|
67
|
+
const {
|
|
68
|
+
children,
|
|
69
|
+
color: localColor,
|
|
70
|
+
placement: localPlacement,
|
|
71
|
+
index,
|
|
72
|
+
total,
|
|
73
|
+
heights,
|
|
74
|
+
maxVisibleToasts,
|
|
75
|
+
className,
|
|
76
|
+
style,
|
|
77
|
+
animation: localAnimation,
|
|
78
|
+
isSwipeable: localIsSwipeable,
|
|
79
|
+
isAnimatedStyleActive = true,
|
|
80
|
+
hide,
|
|
81
|
+
...restProps
|
|
82
|
+
} = props;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Merge global config with local props, ensuring local props take precedence
|
|
86
|
+
*/
|
|
87
|
+
const color = localColor ?? globalConfig?.color ?? 'default';
|
|
88
|
+
const placement = localPlacement ?? globalConfig?.placement ?? 'bottom';
|
|
89
|
+
const animation = localAnimation ?? globalConfig?.animation;
|
|
90
|
+
const isSwipeable = localIsSwipeable ?? globalConfig?.isSwipeable;
|
|
91
|
+
|
|
92
|
+
// Access id from props (id is omitted from ToastProps type but available at runtime)
|
|
93
|
+
const toastProps = props as ToastProps & Pick<ToastComponentProps, 'id'>;
|
|
94
|
+
const { id } = toastProps;
|
|
95
|
+
|
|
96
|
+
const rootClassName = cn(toastRootVariants({ color }), className);
|
|
97
|
+
|
|
98
|
+
// Extract padding and backgroundColor for placeholder Views
|
|
99
|
+
const { topStyle, bottomStyle } = useVerticalPlaceholderStyles({
|
|
100
|
+
rootClassName,
|
|
101
|
+
style,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const { rContainerStyle, entering, exiting, panGesture, isAllAnimationsDisabled } =
|
|
105
|
+
useToastRootAnimation({
|
|
106
|
+
animation,
|
|
107
|
+
index,
|
|
108
|
+
total,
|
|
109
|
+
heights,
|
|
110
|
+
placement,
|
|
111
|
+
hide,
|
|
112
|
+
id,
|
|
113
|
+
isSwipeable,
|
|
114
|
+
maxVisibleToasts,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const rootStyle = isAnimatedStyleActive
|
|
118
|
+
? [toastStyleSheet.root, rContainerStyle, style]
|
|
119
|
+
: [toastStyleSheet.root, style];
|
|
120
|
+
|
|
121
|
+
const animationSettingsContextValue = useMemo(
|
|
122
|
+
() => ({
|
|
123
|
+
isAllAnimationsDisabled,
|
|
124
|
+
}),
|
|
125
|
+
[isAllAnimationsDisabled],
|
|
126
|
+
);
|
|
127
|
+
const parent = useParentContext();
|
|
128
|
+
const ctx = useMemo(
|
|
129
|
+
() => ({ ...parent, [SCOPE]: { color, hide, id } }),
|
|
130
|
+
[parent, color, hide, id],
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// ---- Web enter/exit lifecycle -----------------------------------------
|
|
134
|
+
// On web the CSS engine drives enter/exit via `data-state` transitions
|
|
135
|
+
// (see `toastWrapperVariants`). The state machine is:
|
|
136
|
+
// mount → `entering` → (rAF) → `open` → (hide) → `closed` → (transitionend) → unmount
|
|
137
|
+
// Native ignores `dataState`; Reanimated `entering` / `exiting` still handle the visuals.
|
|
138
|
+
|
|
139
|
+
const lifecycle = useToastLifecycle();
|
|
140
|
+
const isPendingRemoval = lifecycle?.pendingRemovalIds.has(id) ?? false;
|
|
141
|
+
const isFrontmost = lifecycle?.frontmostId === id;
|
|
142
|
+
|
|
143
|
+
const [localState, setLocalState] = useState<Exclude<ToastDataState, 'closed'>>('entering');
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (!IS_WEB) return;
|
|
147
|
+
// rAF ensures the first paint commits with `data-state="entering"`
|
|
148
|
+
// (opacity 0 + slight translate), then the next frame transitions
|
|
149
|
+
// to `data-state="open"` with the CSS engine driving the animation.
|
|
150
|
+
const raf = requestAnimationFrame(() => {
|
|
151
|
+
setLocalState('open');
|
|
152
|
+
});
|
|
153
|
+
return () => cancelAnimationFrame(raf);
|
|
154
|
+
}, []);
|
|
155
|
+
|
|
156
|
+
const dataState: ToastDataState = isPendingRemoval ? 'closed' : localState;
|
|
157
|
+
|
|
158
|
+
const wrapperRef = useRef<View | null>(null);
|
|
159
|
+
|
|
160
|
+
// Keep the latest `remove` reachable from a ref so the pending-removal effect
|
|
161
|
+
// below doesn't list `lifecycle` in its dep array. The context value changes
|
|
162
|
+
// whenever any toast in the stack updates, which would otherwise reset the
|
|
163
|
+
// safety timeout on every unrelated re-render.
|
|
164
|
+
const removeRef = useRef<((id: string) => void) | undefined>(lifecycle?.remove);
|
|
165
|
+
removeRef.current = lifecycle?.remove;
|
|
166
|
+
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
if (!IS_WEB) return;
|
|
169
|
+
if (!isPendingRemoval) return;
|
|
170
|
+
|
|
171
|
+
const node = wrapperRef.current as unknown as
|
|
172
|
+
| (HTMLElement & {
|
|
173
|
+
addEventListener: HTMLElement['addEventListener'];
|
|
174
|
+
removeEventListener: HTMLElement['removeEventListener'];
|
|
175
|
+
})
|
|
176
|
+
| null;
|
|
177
|
+
|
|
178
|
+
let removed = false;
|
|
179
|
+
const doRemove = () => {
|
|
180
|
+
if (removed) return;
|
|
181
|
+
removed = true;
|
|
182
|
+
removeRef.current?.(id);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const safetyTimer = setTimeout(doRemove, WEB_TRANSITION_SAFETY_MS);
|
|
186
|
+
|
|
187
|
+
if (!node || typeof node.addEventListener !== 'function') {
|
|
188
|
+
return () => {
|
|
189
|
+
clearTimeout(safetyTimer);
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const handler = (event: Event) => {
|
|
194
|
+
const propertyName = (event as unknown as { propertyName?: string }).propertyName ?? '';
|
|
195
|
+
// Ignore transitions on unrelated properties (e.g. shadow tokens) so
|
|
196
|
+
// we don't unmount before the exit animation actually completes.
|
|
197
|
+
if (propertyName === 'opacity' || propertyName === 'transform') {
|
|
198
|
+
doRemove();
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
node.addEventListener('transitionend', handler);
|
|
202
|
+
|
|
203
|
+
return () => {
|
|
204
|
+
clearTimeout(safetyTimer);
|
|
205
|
+
node.removeEventListener('transitionend', handler);
|
|
206
|
+
};
|
|
207
|
+
}, [isPendingRemoval, id]);
|
|
208
|
+
|
|
209
|
+
const wrapperClassName = cn(toastWrapperVariants({ placement }));
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<AnimationSettingsProvider value={animationSettingsContextValue}>
|
|
213
|
+
<ParentContext.Provider value={ctx}>
|
|
214
|
+
<GestureDetector gesture={panGesture}>
|
|
215
|
+
<Animated.View
|
|
216
|
+
ref={wrapperRef}
|
|
217
|
+
className={wrapperClassName}
|
|
218
|
+
entering={entering}
|
|
219
|
+
exiting={exiting}
|
|
220
|
+
{...(IS_WEB && { tabIndex: isFrontmost ? 0 : -1 })}
|
|
221
|
+
{...mergeDataAttributes(
|
|
222
|
+
dataAttributes({ state: dataState }),
|
|
223
|
+
isFrontmost ? dataAttributes({ frontmost: 'true' }) : undefined,
|
|
224
|
+
)}
|
|
225
|
+
>
|
|
226
|
+
{/* Animated toast instance */}
|
|
227
|
+
<AnimatedToastRoot
|
|
228
|
+
ref={ref}
|
|
229
|
+
className={rootClassName}
|
|
230
|
+
style={rootStyle}
|
|
231
|
+
{...restProps}
|
|
232
|
+
{...mergeDataAttributes(
|
|
233
|
+
restProps,
|
|
234
|
+
dataAttributes({
|
|
235
|
+
slot: 'toast',
|
|
236
|
+
placement,
|
|
237
|
+
index: String(index ?? 0),
|
|
238
|
+
...(isFrontmost && { frontmost: 'true' }),
|
|
239
|
+
}),
|
|
240
|
+
)}
|
|
241
|
+
>
|
|
242
|
+
{children}
|
|
243
|
+
{/*
|
|
244
|
+
When visible toasts have different heights, the toast adapts to the last visible toast height.
|
|
245
|
+
In cases where a toast originally has one height and gets smaller when a new toast comes to stack,
|
|
246
|
+
content might be visible behind the last toast without proper padding.
|
|
247
|
+
The placeholder Views ensure that the content under active toast is hidden.
|
|
248
|
+
*/}
|
|
249
|
+
<View className="absolute left-0 right-0 top-0" style={topStyle} />
|
|
250
|
+
<View className="absolute left-0 right-0 bottom-0" style={bottomStyle} />
|
|
251
|
+
</AnimatedToastRoot>
|
|
252
|
+
{/*
|
|
253
|
+
Hidden toast instance used to measure natural height on native.
|
|
254
|
+
Web owns its own natural height (Reanimated's height-spring is disabled
|
|
255
|
+
on web to avoid the enter/exit glitch), so the duplicate node is skipped
|
|
256
|
+
— this halves the DOM node count per toast on web.
|
|
257
|
+
*/}
|
|
258
|
+
{!IS_WEB && (
|
|
259
|
+
<AnimatedToastRoot
|
|
260
|
+
pointerEvents="none"
|
|
261
|
+
className={cn(rootClassName, 'absolute opacity-0')}
|
|
262
|
+
style={[toastStyleSheet.root, style]}
|
|
263
|
+
onLayout={(event) => {
|
|
264
|
+
const measuredHeight = event.nativeEvent.layout.height;
|
|
265
|
+
heights.modify((value) => {
|
|
266
|
+
'worklet';
|
|
267
|
+
return { ...value, [id]: measuredHeight };
|
|
268
|
+
});
|
|
269
|
+
}}
|
|
270
|
+
{...restProps}
|
|
271
|
+
>
|
|
272
|
+
{children}
|
|
273
|
+
</AnimatedToastRoot>
|
|
274
|
+
)}
|
|
275
|
+
</Animated.View>
|
|
276
|
+
</GestureDetector>
|
|
277
|
+
</ParentContext.Provider>
|
|
278
|
+
</AnimationSettingsProvider>
|
|
279
|
+
);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// --------------------------------------------------
|
|
283
|
+
|
|
284
|
+
const ToastTitle = forwardRef<View, ToastTitleProps>((props, ref) => {
|
|
285
|
+
const { children, className, ...restProps } = props;
|
|
286
|
+
|
|
287
|
+
const { nativeID } = useToastContext();
|
|
288
|
+
const { color } = useToastStyleContext();
|
|
289
|
+
|
|
290
|
+
const labelClassName = cn(toastLabelVariants({ color }), className);
|
|
291
|
+
|
|
292
|
+
return (
|
|
293
|
+
<Text
|
|
294
|
+
ref={ref}
|
|
295
|
+
className={labelClassName}
|
|
296
|
+
nativeID={`${nativeID}_label`}
|
|
297
|
+
role="heading"
|
|
298
|
+
aria-level={3}
|
|
299
|
+
{...restProps}
|
|
300
|
+
>
|
|
301
|
+
{children}
|
|
302
|
+
</Text>
|
|
303
|
+
);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// --------------------------------------------------
|
|
307
|
+
|
|
308
|
+
const ToastDescription = forwardRef<View, ToastDescriptionProps>((props, ref) => {
|
|
309
|
+
const { children, className, ...restProps } = props;
|
|
310
|
+
|
|
311
|
+
const { nativeID } = useToastContext();
|
|
312
|
+
const { color } = useToastStyleContext();
|
|
313
|
+
const descriptionClassName = cn(toastDescriptionVariants({ color }), className);
|
|
314
|
+
|
|
315
|
+
return (
|
|
316
|
+
<Text
|
|
317
|
+
ref={ref}
|
|
318
|
+
className={descriptionClassName}
|
|
319
|
+
nativeID={`${nativeID}_description`}
|
|
320
|
+
{...restProps}
|
|
321
|
+
>
|
|
322
|
+
{children}
|
|
323
|
+
</Text>
|
|
324
|
+
);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// --------------------------------------------------
|
|
328
|
+
|
|
329
|
+
const ToastIcon = ({ asChild, className, style, as, ...props }: ToastIconProps) => {
|
|
330
|
+
const { color } = useToastStyleContext();
|
|
331
|
+
const computedClassName = cn(toastIconVariants({ color }), className);
|
|
332
|
+
|
|
333
|
+
if (asChild) {
|
|
334
|
+
return (
|
|
335
|
+
<Slot
|
|
336
|
+
className={computedClassName}
|
|
337
|
+
style={style}
|
|
338
|
+
{...props}
|
|
339
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'toast-icon' }))}
|
|
340
|
+
/>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (!as) {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<Icon
|
|
350
|
+
as={as}
|
|
351
|
+
className={computedClassName}
|
|
352
|
+
style={style}
|
|
353
|
+
{...props}
|
|
354
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'toast-icon' }))}
|
|
355
|
+
/>
|
|
356
|
+
);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
ToastIcon.displayName = 'Toast.Icon';
|
|
360
|
+
|
|
361
|
+
// --------------------------------------------------
|
|
362
|
+
|
|
363
|
+
const ToastAction = forwardRef<View, ToastActionProps>((props, ref) => {
|
|
364
|
+
const { children, variant, color, size = 'small', className, ...restProps } = props;
|
|
365
|
+
|
|
366
|
+
const { color: toastColor } = useToastStyleContext();
|
|
367
|
+
|
|
368
|
+
// TODO: Add toastActionVariants to styles.ts to restore color-aware action styling
|
|
369
|
+
|
|
370
|
+
const buttonColor = useButtonColor({ color, toastColor });
|
|
371
|
+
|
|
372
|
+
return (
|
|
373
|
+
<Button
|
|
374
|
+
ref={ref}
|
|
375
|
+
variant={variant ?? 'outline'}
|
|
376
|
+
color={buttonColor}
|
|
377
|
+
size={size}
|
|
378
|
+
className={className}
|
|
379
|
+
{...restProps}
|
|
380
|
+
>
|
|
381
|
+
<Button.Label>{children}</Button.Label>
|
|
382
|
+
</Button>
|
|
383
|
+
);
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// --------------------------------------------------
|
|
387
|
+
|
|
388
|
+
const ToastClose = forwardRef<View, ToastCloseProps>((props, ref) => {
|
|
389
|
+
const { children, size = 'small', className, onPress, ...restProps } = props;
|
|
390
|
+
const { hide, id } = useToastStyleContext();
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Handle close button press
|
|
394
|
+
* If hide and id are available from context, use them to hide the toast
|
|
395
|
+
* Otherwise, use the provided onPress handler
|
|
396
|
+
*/
|
|
397
|
+
const handlePress = (event: any) => {
|
|
398
|
+
if (hide && id) {
|
|
399
|
+
hide(id);
|
|
400
|
+
}
|
|
401
|
+
if (onPress && typeof onPress === 'function') {
|
|
402
|
+
onPress(event);
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
return (
|
|
407
|
+
<IconButton
|
|
408
|
+
ref={ref}
|
|
409
|
+
variant="ghost"
|
|
410
|
+
size={size}
|
|
411
|
+
aria-label="Close"
|
|
412
|
+
className={className}
|
|
413
|
+
onPress={handlePress}
|
|
414
|
+
as={CloseIcon}
|
|
415
|
+
{...restProps}
|
|
416
|
+
/>
|
|
417
|
+
);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// --------------------------------------------------
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Default styled toast component for simplified toast.show() API
|
|
424
|
+
* Used internally when showing toasts with string or config object (without component)
|
|
425
|
+
*/
|
|
426
|
+
export function DefaultToast(props: DefaultToastProps) {
|
|
427
|
+
const globalConfig = useToastConfig();
|
|
428
|
+
|
|
429
|
+
const {
|
|
430
|
+
id,
|
|
431
|
+
color: localColor,
|
|
432
|
+
placement: localPlacement,
|
|
433
|
+
isSwipeable: localIsSwipeable,
|
|
434
|
+
animation: localAnimation,
|
|
435
|
+
label,
|
|
436
|
+
description,
|
|
437
|
+
actionLabel,
|
|
438
|
+
onActionPress,
|
|
439
|
+
icon,
|
|
440
|
+
hide,
|
|
441
|
+
show,
|
|
442
|
+
...toastComponentProps
|
|
443
|
+
} = props;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Merge global config with local props, ensuring local props take precedence
|
|
447
|
+
*/
|
|
448
|
+
const color = localColor ?? globalConfig?.color ?? 'default';
|
|
449
|
+
const placement = localPlacement ?? globalConfig?.placement ?? 'bottom';
|
|
450
|
+
const isSwipeable = localIsSwipeable ?? globalConfig?.isSwipeable;
|
|
451
|
+
const animation = localAnimation ?? globalConfig?.animation;
|
|
452
|
+
|
|
453
|
+
const handleActionPress = () => {
|
|
454
|
+
if (onActionPress) {
|
|
455
|
+
onActionPress({ show, hide });
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
return (
|
|
460
|
+
<ToastRoot
|
|
461
|
+
id={id}
|
|
462
|
+
color={color}
|
|
463
|
+
placement={placement}
|
|
464
|
+
isSwipeable={isSwipeable}
|
|
465
|
+
animation={animation}
|
|
466
|
+
className="flex-row gap-3"
|
|
467
|
+
hide={hide}
|
|
468
|
+
show={show}
|
|
469
|
+
{...(color === 'danger' && { role: 'alert' as const })}
|
|
470
|
+
{...toastComponentProps}
|
|
471
|
+
>
|
|
472
|
+
{icon ? <ToastIcon as={icon} /> : null}
|
|
473
|
+
<View className="flex-1">
|
|
474
|
+
{label && <ToastTitle>{label}</ToastTitle>}
|
|
475
|
+
{description && <ToastDescription>{description}</ToastDescription>}
|
|
476
|
+
</View>
|
|
477
|
+
{actionLabel && <ToastAction onPress={handleActionPress}>{actionLabel}</ToastAction>}
|
|
478
|
+
</ToastRoot>
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// --------------------------------------------------
|
|
483
|
+
|
|
484
|
+
ToastRoot.displayName = 'Toast';
|
|
485
|
+
ToastTitle.displayName = 'Toast.Title';
|
|
486
|
+
ToastDescription.displayName = 'Toast.Description';
|
|
487
|
+
ToastIcon.displayName = 'Toast.Icon';
|
|
488
|
+
ToastAction.displayName = 'Toast.Action';
|
|
489
|
+
ToastClose.displayName = 'Toast.Close';
|
|
490
|
+
|
|
491
|
+
type ToastCompoundComponent = typeof ToastRoot & {
|
|
492
|
+
Title: typeof ToastTitle;
|
|
493
|
+
Description: typeof ToastDescription;
|
|
494
|
+
Icon: typeof ToastIcon;
|
|
495
|
+
Action: typeof ToastAction;
|
|
496
|
+
Close: typeof ToastClose;
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
export const Toast = Object.assign(ToastRoot, {
|
|
500
|
+
Title: ToastTitle,
|
|
501
|
+
Description: ToastDescription,
|
|
502
|
+
Icon: ToastIcon,
|
|
503
|
+
Action: ToastAction,
|
|
504
|
+
Close: ToastClose,
|
|
505
|
+
}) as ToastCompoundComponent;
|
|
506
|
+
|
|
507
|
+
export type {
|
|
508
|
+
ToastColor,
|
|
509
|
+
ToastPlacement,
|
|
510
|
+
ToastRootAnimation,
|
|
511
|
+
ToastProps,
|
|
512
|
+
ToastTitleProps,
|
|
513
|
+
ToastDescriptionProps,
|
|
514
|
+
ToastIconProps,
|
|
515
|
+
ToastActionProps,
|
|
516
|
+
ToastCloseProps,
|
|
517
|
+
ToastContextValue,
|
|
518
|
+
ToastRootRef,
|
|
519
|
+
DefaultToastProps,
|
|
520
|
+
} from './types';
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Toast root styles
|
|
6
|
+
*
|
|
7
|
+
* @note ANIMATED PROPERTIES (cannot be set via className):
|
|
8
|
+
* The following properties are animated and cannot be overridden using Tailwind classes:
|
|
9
|
+
* - `opacity` - Animated for visibility transitions when toasts are pushed beyond visible stack limits
|
|
10
|
+
* - `transform` (translateY) - Animated for vertical position transitions when toasts are stacked, and for swipe-to-dismiss gestures
|
|
11
|
+
* - `transform` (scale) - Animated for size scaling transitions when toasts are stacked (toasts behind active one are scaled down)
|
|
12
|
+
* - `height` - Animated for height transitions when toast content changes
|
|
13
|
+
*
|
|
14
|
+
* To customize these properties, use the `animation` prop on `Toast.Root`:
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <Toast.Root
|
|
17
|
+
* animation={{
|
|
18
|
+
* opacity: {
|
|
19
|
+
* value: [1, 0],
|
|
20
|
+
* timingConfig: { duration: 300 }
|
|
21
|
+
* },
|
|
22
|
+
* translateY: {
|
|
23
|
+
* value: [0, 10],
|
|
24
|
+
* timingConfig: { duration: 300 }
|
|
25
|
+
* },
|
|
26
|
+
* scale: {
|
|
27
|
+
* value: [1, 0.97],
|
|
28
|
+
* timingConfig: { duration: 300 }
|
|
29
|
+
* }
|
|
30
|
+
* }}
|
|
31
|
+
* />
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* To completely disable animated styles and apply your own via className or style prop,
|
|
35
|
+
* set `isAnimatedStyleActive={false}` on `Toast.Root`.
|
|
36
|
+
*/
|
|
37
|
+
export const toastRootVariants = cva(
|
|
38
|
+
[
|
|
39
|
+
// `overflow-hidden` was intentionally removed: on web it clips the drop
|
|
40
|
+
// shadow and clips the child's transform mid-transition, producing a
|
|
41
|
+
// visual "cut off" during enter/exit. Consumers that need clipping for
|
|
42
|
+
// custom child content (e.g. a background image) can add it themselves.
|
|
43
|
+
'flex-row items-center gap-2 rounded-[var(--border-radius-default)] min-h-12 px-4 py-2 shadow-lg bg-surface-primary border border-stroke-secondary',
|
|
44
|
+
'native:overflow-hidden',
|
|
45
|
+
],
|
|
46
|
+
{
|
|
47
|
+
variants: {
|
|
48
|
+
color: {
|
|
49
|
+
default: '',
|
|
50
|
+
info: '',
|
|
51
|
+
success: '',
|
|
52
|
+
warning: '',
|
|
53
|
+
danger: '',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
defaultVariants: {
|
|
57
|
+
color: 'default',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Toast wrapper variants
|
|
64
|
+
*
|
|
65
|
+
* Applied to the outer `Animated.View` that carries `data-state="entering|open|closed"`.
|
|
66
|
+
* On web the CSS engine drives the enter/exit animation via `data-state` transitions —
|
|
67
|
+
* fade + short translate — replacing the Reanimated layout animations that ran on
|
|
68
|
+
* the same element on native. Native ignores these classes (no `web:` prefix hits).
|
|
69
|
+
*
|
|
70
|
+
* `placement` picks the slide direction so top-placed toasts translate up on close and
|
|
71
|
+
* bottom-placed toasts translate down. The unprefixed `-translate-y-2` / `translate-y-2`
|
|
72
|
+
* on the `top-*` / `bottom-*` variants also seeds the entering-state offset synchronously
|
|
73
|
+
* — CSS transitions to `translate-y-0` when `data-state` flips to `open`.
|
|
74
|
+
*
|
|
75
|
+
* `motion-reduce:transition-none` collapses the transition for users with
|
|
76
|
+
* `prefers-reduced-motion: reduce`. In that case `transitionend` may never fire, so
|
|
77
|
+
* the Toast component's safety timeout handles removal.
|
|
78
|
+
*/
|
|
79
|
+
export const toastWrapperVariants = cva(
|
|
80
|
+
[
|
|
81
|
+
'absolute',
|
|
82
|
+
'web:transition-[opacity,transform] web:duration-200 web:ease-out',
|
|
83
|
+
'web:data-[state=entering]:opacity-0',
|
|
84
|
+
'web:data-[state=open]:opacity-100',
|
|
85
|
+
'web:data-[state=closed]:opacity-0 web:data-[state=closed]:duration-150',
|
|
86
|
+
'web:motion-reduce:transition-none web:motion-reduce:duration-0',
|
|
87
|
+
],
|
|
88
|
+
{
|
|
89
|
+
variants: {
|
|
90
|
+
placement: {
|
|
91
|
+
'top-start': [
|
|
92
|
+
'top-0 native:left-0 native:right-0',
|
|
93
|
+
'web:left-0 web:max-w-[460px]',
|
|
94
|
+
'web:data-[state=entering]:-translate-y-2',
|
|
95
|
+
'web:data-[state=closed]:-translate-y-2',
|
|
96
|
+
],
|
|
97
|
+
top: [
|
|
98
|
+
'top-0 native:left-0 native:right-0',
|
|
99
|
+
'web:left-1/2 web:-translate-x-1/2 web:max-w-[460px]',
|
|
100
|
+
'web:data-[state=entering]:-translate-y-2',
|
|
101
|
+
'web:data-[state=closed]:-translate-y-2',
|
|
102
|
+
],
|
|
103
|
+
'top-end': [
|
|
104
|
+
'top-0 native:left-0 native:right-0',
|
|
105
|
+
'web:right-0 web:max-w-[460px]',
|
|
106
|
+
'web:data-[state=entering]:-translate-y-2',
|
|
107
|
+
'web:data-[state=closed]:-translate-y-2',
|
|
108
|
+
],
|
|
109
|
+
'bottom-start': [
|
|
110
|
+
'bottom-0 native:left-0 native:right-0',
|
|
111
|
+
'web:left-0 web:max-w-[460px]',
|
|
112
|
+
'web:data-[state=entering]:translate-y-2',
|
|
113
|
+
'web:data-[state=closed]:translate-y-2',
|
|
114
|
+
],
|
|
115
|
+
bottom: [
|
|
116
|
+
'bottom-0 native:left-0 native:right-0',
|
|
117
|
+
'web:left-1/2 web:-translate-x-1/2 web:max-w-[460px]',
|
|
118
|
+
'web:data-[state=entering]:translate-y-2',
|
|
119
|
+
'web:data-[state=closed]:translate-y-2',
|
|
120
|
+
],
|
|
121
|
+
'bottom-end': [
|
|
122
|
+
'bottom-0 native:left-0 native:right-0',
|
|
123
|
+
'web:right-0 web:max-w-[460px]',
|
|
124
|
+
'web:data-[state=entering]:translate-y-2',
|
|
125
|
+
'web:data-[state=closed]:translate-y-2',
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
defaultVariants: {
|
|
130
|
+
placement: 'bottom',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
export const toastLabelVariants = cva(['text-base font-sans-medium'], {
|
|
136
|
+
variants: {
|
|
137
|
+
color: {
|
|
138
|
+
default: 'text-content-primary',
|
|
139
|
+
info: 'text-content-info',
|
|
140
|
+
success: 'text-content-success',
|
|
141
|
+
warning: 'text-content-warning',
|
|
142
|
+
danger: 'text-content-danger',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
defaultVariants: {
|
|
146
|
+
color: 'default',
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export const toastDescriptionVariants = cva(['text-sm text-content-primary'], {
|
|
151
|
+
variants: {
|
|
152
|
+
color: {
|
|
153
|
+
default: 'text-content-primary',
|
|
154
|
+
info: 'text-content-info',
|
|
155
|
+
success: 'text-content-success',
|
|
156
|
+
warning: 'text-content-warning',
|
|
157
|
+
danger: 'text-content-danger',
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
defaultVariants: {
|
|
161
|
+
color: 'default',
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
export const toastIconVariants = cva(['size-5'], {
|
|
166
|
+
variants: {
|
|
167
|
+
color: {
|
|
168
|
+
default: 'text-content-primary',
|
|
169
|
+
info: 'text-content-info',
|
|
170
|
+
success: 'text-content-success',
|
|
171
|
+
warning: 'text-content-warning',
|
|
172
|
+
danger: 'text-content-danger',
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
defaultVariants: {
|
|
176
|
+
color: 'default',
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
export const toastStyleSheet = StyleSheet.create({
|
|
181
|
+
root: {
|
|
182
|
+
borderCurve: 'continuous',
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
export type ToastColorProps = VariantProps<typeof toastRootVariants>;
|