@a-type/ui 3.0.43 → 3.1.0-beta.4
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/dist/cjs/components/layouts/PageNav.js +1 -1
- package/dist/cjs/components/layouts/PageNav.js.map +1 -1
- package/dist/cjs/components/particles/ParticleLayer.js +2 -1
- package/dist/cjs/components/particles/ParticleLayer.js.map +1 -1
- package/dist/cjs/components/provider/Provider.js +2 -2
- package/dist/cjs/components/provider/Provider.js.map +1 -1
- package/dist/cjs/components/toasts/toasts.d.ts +34 -5
- package/dist/cjs/components/toasts/toasts.js +100 -31
- package/dist/cjs/components/toasts/toasts.js.map +1 -1
- package/dist/cjs/components/toasts/toasts.stories.js +44 -13
- package/dist/cjs/components/toasts/toasts.stories.js.map +1 -1
- package/dist/cjs/components/viewport/ViewportState.js +8 -4
- package/dist/cjs/components/viewport/ViewportState.js.map +1 -1
- package/dist/cjs/hooks/useOverrideTheme.js +1 -1
- package/dist/cjs/hooks/useOverrideTheme.js.map +1 -1
- package/dist/cjs/hooks/useSize.d.ts +1 -1
- package/dist/cjs/hooks/useSize.js.map +1 -1
- package/dist/cjs/hooks/useTitleBarColor.js +3 -0
- package/dist/cjs/hooks/useTitleBarColor.js.map +1 -1
- package/dist/cjs/hooks/useVisualViewportOffset.js +10 -1
- package/dist/cjs/hooks/useVisualViewportOffset.js.map +1 -1
- package/dist/css/main.css +3 -4
- package/dist/esm/components/layouts/PageNav.js +1 -1
- package/dist/esm/components/layouts/PageNav.js.map +1 -1
- package/dist/esm/components/particles/ParticleLayer.js +2 -1
- package/dist/esm/components/particles/ParticleLayer.js.map +1 -1
- package/dist/esm/components/provider/Provider.js +3 -3
- package/dist/esm/components/provider/Provider.js.map +1 -1
- package/dist/esm/components/toasts/toasts.d.ts +34 -5
- package/dist/esm/components/toasts/toasts.js +97 -28
- package/dist/esm/components/toasts/toasts.js.map +1 -1
- package/dist/esm/components/toasts/toasts.stories.js +40 -9
- package/dist/esm/components/toasts/toasts.stories.js.map +1 -1
- package/dist/esm/components/viewport/ViewportState.js +8 -4
- package/dist/esm/components/viewport/ViewportState.js.map +1 -1
- package/dist/esm/hooks/useOverrideTheme.js +1 -1
- package/dist/esm/hooks/useOverrideTheme.js.map +1 -1
- package/dist/esm/hooks/useSize.d.ts +1 -1
- package/dist/esm/hooks/useSize.js.map +1 -1
- package/dist/esm/hooks/useTitleBarColor.js +3 -0
- package/dist/esm/hooks/useTitleBarColor.js.map +1 -1
- package/dist/esm/hooks/useVisualViewportOffset.js +10 -1
- package/dist/esm/hooks/useVisualViewportOffset.js.map +1 -1
- package/package.json +3 -2
- package/src/components/layouts/PageNav.tsx +3 -1
- package/src/components/particles/ParticleLayer.tsx +3 -1
- package/src/components/provider/Provider.tsx +15 -11
- package/src/components/toasts/toasts.stories.tsx +50 -8
- package/src/components/toasts/toasts.tsx +249 -63
- package/src/components/viewport/ViewportState.ts +8 -4
- package/src/hooks/useOverrideTheme.ts +1 -1
- package/src/hooks/useSize.ts +1 -1
- package/src/hooks/useTitleBarColor.ts +3 -0
- package/src/hooks/useVisualViewportOffset.ts +38 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a-type/ui",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.1.0-beta.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/a-type/ui"
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@a-type/utils": "^1.1.4",
|
|
44
|
+
"@base-ui/react": "^1.0.0",
|
|
44
45
|
"@radix-ui/react-accordion": "^1.2.2",
|
|
45
46
|
"@radix-ui/react-checkbox": "^1.1.3",
|
|
46
47
|
"@radix-ui/react-collapsible": "^1.1.2",
|
|
@@ -85,13 +86,13 @@
|
|
|
85
86
|
"@storybook/react": "8.4.7",
|
|
86
87
|
"@storybook/react-vite": "8.4.7",
|
|
87
88
|
"@storybook/test": "8.4.7",
|
|
89
|
+
"@types/dom-chromium-installation-events": "^101.0.4",
|
|
88
90
|
"@types/pluralize": "^0.0.33",
|
|
89
91
|
"@types/react": "^19.0.1",
|
|
90
92
|
"@types/react-dom": "^19.0.2",
|
|
91
93
|
"@types/react-is": "^19.0.0",
|
|
92
94
|
"@types/w3c-image-capture": "^1.0.10",
|
|
93
95
|
"@types/web-app-manifest": "^1.0.9",
|
|
94
|
-
"@types/dom-chromium-installation-events": "^101.0.4",
|
|
95
96
|
"@unocss/cli": "66.5.4",
|
|
96
97
|
"@unocss/core": "66.5.4",
|
|
97
98
|
"@unocss/transformer-variant-group": "66.5.4",
|
|
@@ -11,7 +11,9 @@ export function PageNav({
|
|
|
11
11
|
children,
|
|
12
12
|
...props
|
|
13
13
|
}: HTMLAttributes<HTMLDivElement>) {
|
|
14
|
-
const bodyRef = useRef(
|
|
14
|
+
const bodyRef = useRef(
|
|
15
|
+
typeof document === 'undefined' ? null : document.documentElement,
|
|
16
|
+
);
|
|
15
17
|
const ref = useBoundsCssVars<HTMLDivElement>(undefined, bodyRef, {
|
|
16
18
|
left: '--nav-left',
|
|
17
19
|
top: '--nav-top',
|
|
@@ -31,9 +31,11 @@ export function ParticleLayer({
|
|
|
31
31
|
/>
|
|
32
32
|
);
|
|
33
33
|
|
|
34
|
+
const ssr = typeof document === 'undefined';
|
|
35
|
+
|
|
34
36
|
return (
|
|
35
37
|
<ParticlesProvider value={particles}>
|
|
36
|
-
{noPortal ? canvas : createPortal(canvas, document.body)}
|
|
38
|
+
{noPortal || ssr ? canvas : createPortal(canvas, document.body)}
|
|
37
39
|
{children}
|
|
38
40
|
</ParticlesProvider>
|
|
39
41
|
);
|
|
@@ -4,7 +4,7 @@ import { useVirtualKeyboardBehavior } from '../../hooks/useVirtualKeyboardBehavi
|
|
|
4
4
|
import { IconSpritesheet } from '../icon/index.js';
|
|
5
5
|
import { ParticleLayer } from '../particles/index.js';
|
|
6
6
|
import { PwaInstall } from '../pwaInstall/PwaInstall.js';
|
|
7
|
-
import { Toaster } from '../toasts/toasts.js';
|
|
7
|
+
import { DefaultToastProvider, Toaster } from '../toasts/toasts.js';
|
|
8
8
|
import { TooltipProvider } from '../tooltip/index.js';
|
|
9
9
|
|
|
10
10
|
export interface ProviderProps {
|
|
@@ -47,10 +47,12 @@ export function Provider({
|
|
|
47
47
|
<ConfigContext.Provider
|
|
48
48
|
value={{ virtualKeyboardBehavior: supportedVirtualKeyboardBehavior }}
|
|
49
49
|
>
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
<DefaultToastProvider>
|
|
51
|
+
<TooltipProvider>
|
|
52
|
+
{children}
|
|
53
|
+
{otherStuff}
|
|
54
|
+
</TooltipProvider>
|
|
55
|
+
</DefaultToastProvider>
|
|
54
56
|
</ConfigContext.Provider>
|
|
55
57
|
);
|
|
56
58
|
|
|
@@ -58,12 +60,14 @@ export function Provider({
|
|
|
58
60
|
<ConfigContext.Provider
|
|
59
61
|
value={{ virtualKeyboardBehavior: supportedVirtualKeyboardBehavior }}
|
|
60
62
|
>
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
<DefaultToastProvider>
|
|
64
|
+
<TooltipProvider>
|
|
65
|
+
<ParticleLayer>
|
|
66
|
+
{children}
|
|
67
|
+
{otherStuff}
|
|
68
|
+
</ParticleLayer>
|
|
69
|
+
</TooltipProvider>
|
|
70
|
+
</DefaultToastProvider>
|
|
67
71
|
</ConfigContext.Provider>
|
|
68
72
|
);
|
|
69
73
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { toast } from 'react-hot-toast';
|
|
3
2
|
import { Box } from '../box/Box.js';
|
|
4
3
|
import { Button } from '../button/Button.js';
|
|
4
|
+
import { toast } from './toasts.js';
|
|
5
5
|
|
|
6
6
|
const meta = {
|
|
7
7
|
title: 'Components/toasts',
|
|
@@ -24,7 +24,7 @@ export const Default: Story = {
|
|
|
24
24
|
toast(
|
|
25
25
|
'This is a default toast! With a lot of text. Enough to wrap around.',
|
|
26
26
|
{
|
|
27
|
-
duration:
|
|
27
|
+
duration: 120_000,
|
|
28
28
|
},
|
|
29
29
|
);
|
|
30
30
|
}}
|
|
@@ -35,7 +35,7 @@ export const Default: Story = {
|
|
|
35
35
|
color="success"
|
|
36
36
|
onClick={() => {
|
|
37
37
|
toast.success('This is a success toast!', {
|
|
38
|
-
duration:
|
|
38
|
+
duration: 20_000,
|
|
39
39
|
});
|
|
40
40
|
}}
|
|
41
41
|
>
|
|
@@ -45,7 +45,7 @@ export const Default: Story = {
|
|
|
45
45
|
color="attention"
|
|
46
46
|
onClick={() => {
|
|
47
47
|
toast.error('This is an error toast!', {
|
|
48
|
-
duration:
|
|
48
|
+
duration: 20_000,
|
|
49
49
|
});
|
|
50
50
|
}}
|
|
51
51
|
>
|
|
@@ -53,10 +53,13 @@ export const Default: Story = {
|
|
|
53
53
|
</Button>
|
|
54
54
|
<Button
|
|
55
55
|
onClick={() => {
|
|
56
|
-
const
|
|
56
|
+
const { complete } = toast.loading('This is a loading toast!');
|
|
57
57
|
setTimeout(() => {
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
complete('Loading complete!', {
|
|
59
|
+
duration: 5000,
|
|
60
|
+
type: 'success',
|
|
61
|
+
});
|
|
62
|
+
}, 5000);
|
|
60
63
|
}}
|
|
61
64
|
>
|
|
62
65
|
Show Loading Toast
|
|
@@ -68,7 +71,8 @@ export const Default: Story = {
|
|
|
68
71
|
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
69
72
|
})(),
|
|
70
73
|
{
|
|
71
|
-
loading:
|
|
74
|
+
loading:
|
|
75
|
+
'Promise is loading... This text is longer to test animation of transition',
|
|
72
76
|
success: 'Promise resolved!',
|
|
73
77
|
error: 'Promise rejected.',
|
|
74
78
|
},
|
|
@@ -77,6 +81,44 @@ export const Default: Story = {
|
|
|
77
81
|
>
|
|
78
82
|
Show Promise Toast
|
|
79
83
|
</Button>
|
|
84
|
+
<Button
|
|
85
|
+
onClick={() => {
|
|
86
|
+
toast('This is a toast with actions!', {
|
|
87
|
+
timeout: 20_000,
|
|
88
|
+
data: {
|
|
89
|
+
actions: [
|
|
90
|
+
{
|
|
91
|
+
label: 'Retry',
|
|
92
|
+
emphasis: 'primary',
|
|
93
|
+
onClick: () => {
|
|
94
|
+
alert('Retry clicked!');
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
label: 'Undo',
|
|
99
|
+
emphasis: 'light',
|
|
100
|
+
onClick: () => {
|
|
101
|
+
alert('Undo clicked!');
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}}
|
|
108
|
+
>
|
|
109
|
+
Show Toast with Actions
|
|
110
|
+
</Button>
|
|
111
|
+
<Button
|
|
112
|
+
onClick={() => {
|
|
113
|
+
toast({
|
|
114
|
+
title: 'Rich Toast',
|
|
115
|
+
description: 'This toast has both a title and a description.',
|
|
116
|
+
timeout: 20_000,
|
|
117
|
+
});
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
Show Rich Toast
|
|
121
|
+
</Button>
|
|
80
122
|
</Box>
|
|
81
123
|
);
|
|
82
124
|
},
|
|
@@ -1,75 +1,261 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Toast,
|
|
3
|
+
ToastManagerAddOptions,
|
|
4
|
+
ToastManagerPromiseOptions,
|
|
5
|
+
ToastObject,
|
|
6
|
+
} from '@base-ui/react/toast';
|
|
3
7
|
import clsx from 'clsx';
|
|
4
|
-
import {
|
|
5
|
-
import { createPortal } from 'react-dom';
|
|
6
|
-
import { DefaultToastOptions, useToaster } from 'react-hot-toast';
|
|
8
|
+
import { ReactNode } from 'react';
|
|
7
9
|
import { useResolvedColorMode } from '../../colorMode.js';
|
|
10
|
+
import { Button, ButtonProps } from '../button/index.js';
|
|
8
11
|
import { Icon } from '../icon/Icon.js';
|
|
12
|
+
import { Spinner } from '../spinner/Spinner.js';
|
|
9
13
|
|
|
10
|
-
const
|
|
14
|
+
export const manager = Toast.createToastManager();
|
|
11
15
|
|
|
12
|
-
export const
|
|
16
|
+
export const DefaultToastProvider = ({
|
|
17
|
+
children,
|
|
18
|
+
...rest
|
|
19
|
+
}: {
|
|
20
|
+
children?: React.ReactNode;
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}) => {
|
|
23
|
+
return (
|
|
24
|
+
<Toast.Provider toastManager={manager} {...rest}>
|
|
25
|
+
{children}
|
|
26
|
+
</Toast.Provider>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export function Toaster() {
|
|
31
|
+
return (
|
|
32
|
+
<Toast.Portal>
|
|
33
|
+
<Toast.Viewport className="overflow-clip">
|
|
34
|
+
<ToastList />
|
|
35
|
+
</Toast.Viewport>
|
|
36
|
+
</Toast.Portal>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function ToastList() {
|
|
41
|
+
const { toasts: untypedToasts } = Toast.useToastManager();
|
|
13
42
|
const mode = useResolvedColorMode();
|
|
14
|
-
const { toasts, handlers } = useToaster(toastOptions);
|
|
15
|
-
const { startPause, endPause } = handlers;
|
|
16
|
-
const visibleToasts = toasts.filter((t) => t.visible);
|
|
17
43
|
|
|
18
|
-
|
|
19
|
-
|
|
44
|
+
const toasts = untypedToasts as Array<ToastObject<CustomToastData>>;
|
|
45
|
+
|
|
46
|
+
return toasts.map((toast) => (
|
|
47
|
+
<Toast.Root
|
|
48
|
+
key={toast.id}
|
|
49
|
+
toast={toast}
|
|
50
|
+
swipeDirection={['up', 'right', 'left']}
|
|
20
51
|
className={clsx(
|
|
21
|
-
|
|
52
|
+
// variable setup
|
|
53
|
+
'[--gap:0.75rem] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))]',
|
|
54
|
+
'[--shrink:calc(1-var(--scale))] [--height:var(--toast-frontmost-height,var(--toast-height))]',
|
|
55
|
+
'[--offset-y:calc(var(--toast-offset-y)+calc(var(--toast-index)*var(--gap))+var(--toast-swipe-movement-y))]',
|
|
56
|
+
// basic positioning
|
|
57
|
+
'absolute left-0 top-xs left-auto z-[calc(100000-var(--toast-index))] mr-0 w-full origin-top',
|
|
58
|
+
'h-[--height]',
|
|
59
|
+
'flex flex-col gap-xs items-center',
|
|
60
|
+
// other properties
|
|
61
|
+
'select-none',
|
|
62
|
+
// animation and interaction
|
|
63
|
+
'translate-x-[--toast-swipe-movement-x] translate-y-[calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--peek))+(var(--shrink)*var(--height)))] scale-[var(--scale)]',
|
|
64
|
+
'[transition:transform_0.5s_cubic-bezier(0.22,1,0.36,1),opacity_0.5s,height_0.15s]',
|
|
65
|
+
// ::after
|
|
66
|
+
'after:(absolute top-full left-0 h-[calc(var(--gap)+1px)] w-full content-empty)',
|
|
67
|
+
// starting style
|
|
68
|
+
'data-[starting-style]:(-translate-y-150%)',
|
|
69
|
+
// limited
|
|
70
|
+
'data-[limited]:opacity-0',
|
|
71
|
+
//expanded
|
|
72
|
+
'data-[expanded]:(h-[--toast-height] translate-x-[--toast-swipe-movement-x] translate-y-[--offset-y] scale-100)',
|
|
73
|
+
// ending styles
|
|
74
|
+
'data-[ending-style]:(opacity-0)',
|
|
75
|
+
// natural or close button
|
|
76
|
+
'[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:(-translate-y-150% scale-90 opacity-50)',
|
|
77
|
+
// swiping down
|
|
78
|
+
'data-[ending-style]:data-[swipe-direction=down]:(translate-y-[calc(var(--toast-swipe-movement-y)+150%)])',
|
|
79
|
+
'data-[expanded]:data-[ending-style]:data-[swipe-direction=down]:(translate-y-[calc(var(--toast-swipe-movement-y)+150%)])',
|
|
80
|
+
// swiping left
|
|
81
|
+
'data-[ending-style]:data-[swipe-direction=left]:(translate-x-[calc(var(--toast-swipe-movement-x)-150%)] translate-y-[var(--offset-y)])',
|
|
82
|
+
'data-[expanded]:data-[ending-style]:data-[swipe-direction=left]:(translate-x-[calc(var(--toast-swipe-movement-x)-150%)] translate-y-[var(--offset-y)])',
|
|
83
|
+
// swiping right
|
|
84
|
+
'data-[ending-style]:data-[swipe-direction=right]:(translate-x-[calc(var(--toast-swipe-movement-x)+150%)] translate-y-[var(--offset-y)])',
|
|
85
|
+
'data-[expanded]:data-[ending-style]:data-[swipe-direction=right]:(translate-x-[calc(var(--toast-swipe-movement-x)+150%)] translate-y-[var(--offset-y)])',
|
|
86
|
+
// swiping up
|
|
87
|
+
'data-[ending-style]:data-[swipe-direction=up]:(translate-y-[calc(var(--toast-swipe-movement-y)-150%)])',
|
|
88
|
+
'data-[expanded]:data-[ending-style]:data-[swipe-direction=up]:(translate-y-[calc(var(--toast-swipe-movement-y)-150%)])',
|
|
89
|
+
// themeing
|
|
90
|
+
{
|
|
91
|
+
'palette-success': toast.type === 'success',
|
|
92
|
+
'palette-attention': toast.type === 'error',
|
|
93
|
+
'palette-info': toast.type === 'blank',
|
|
94
|
+
},
|
|
22
95
|
mode === 'dark' ? 'override-light' : 'override-dark',
|
|
23
|
-
props.className,
|
|
24
96
|
)}
|
|
25
|
-
onMouseEnter={startPause}
|
|
26
|
-
onMouseLeave={endPause}
|
|
27
97
|
>
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
98
|
+
<Toast.Content className="[&[data-behind]:not([data-expanded])]:pointer-events-none flex flex-col gap-2px max-w-sm">
|
|
99
|
+
<div
|
|
100
|
+
className={clsx(
|
|
101
|
+
'layer-components:(bg-main-wash color-black rounded-md b-1 b-solid b-black shadow-md pl-md pr-sm py-sm relative)',
|
|
102
|
+
'layer-components:(flex flex-row gap-sm)',
|
|
103
|
+
'[[data-behind]:not([data-expanded])_&]:(bg-darken-2 max-h-[--height])',
|
|
104
|
+
)}
|
|
105
|
+
>
|
|
106
|
+
<div
|
|
107
|
+
className={clsx(
|
|
108
|
+
'flex flex-row gap-xs items-center',
|
|
109
|
+
'[[data-behind]:not([data-expanded])_&]:(opacity-0) [[data-expanded]_&]:(opacity-100) transition-opacity [transition-duration:250ms]',
|
|
110
|
+
)}
|
|
111
|
+
>
|
|
112
|
+
<div className="flex flex-col gap-xs">
|
|
113
|
+
<Toast.Title className="text-sm leading-tight font-bold m-0" />
|
|
114
|
+
<div className="flex gap-sm">
|
|
115
|
+
{toast.data?.loading ? (
|
|
116
|
+
<Spinner size={15} className="relative top-2px" />
|
|
117
|
+
) : toast.type === 'success' ? (
|
|
118
|
+
<Icon
|
|
119
|
+
name="check"
|
|
120
|
+
color="success"
|
|
121
|
+
className="relative top-2px"
|
|
122
|
+
/>
|
|
123
|
+
) : toast.type === 'error' ? (
|
|
124
|
+
<Icon
|
|
125
|
+
name="warning"
|
|
126
|
+
color="attention"
|
|
127
|
+
className="relative top-2px"
|
|
128
|
+
/>
|
|
129
|
+
) : null}
|
|
130
|
+
<Toast.Description className="text-sm m-0" />
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
<Toast.Close
|
|
134
|
+
className="mb-auto [[data-behind]:not([data-expanded])_&]:(invisible)"
|
|
135
|
+
aria-label="Close"
|
|
136
|
+
render={
|
|
137
|
+
<Button size="small" emphasis="ghost">
|
|
138
|
+
<Icon name="x" />
|
|
139
|
+
</Button>
|
|
140
|
+
}
|
|
141
|
+
/>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
{toast.data?.actions && (
|
|
145
|
+
<div className="flex gap-xxs items-center ml-auto [[data-behind]:not([data-expanded])_&]:(opacity-0) transition-opacity">
|
|
146
|
+
{toast.data.actions.toReversed().map((action, index: number) => (
|
|
147
|
+
<Toast.Action
|
|
148
|
+
key={index}
|
|
149
|
+
className="text-xs"
|
|
150
|
+
onClick={action.onClick}
|
|
151
|
+
render={
|
|
152
|
+
<Button
|
|
153
|
+
size="small"
|
|
154
|
+
emphasis={action.emphasis}
|
|
155
|
+
color={action.color}
|
|
156
|
+
/>
|
|
65
157
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
);
|
|
75
|
-
}
|
|
158
|
+
>
|
|
159
|
+
{action.label}
|
|
160
|
+
</Toast.Action>
|
|
161
|
+
))}
|
|
162
|
+
</div>
|
|
163
|
+
)}
|
|
164
|
+
</Toast.Content>
|
|
165
|
+
</Toast.Root>
|
|
166
|
+
));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export interface CustomToastData {
|
|
170
|
+
actions?: {
|
|
171
|
+
label: ReactNode;
|
|
172
|
+
onClick: () => void;
|
|
173
|
+
emphasis?: ButtonProps['emphasis'];
|
|
174
|
+
color?: ButtonProps['color'];
|
|
175
|
+
}[];
|
|
176
|
+
loading?: boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface ToastOptions extends ToastManagerAddOptions<CustomToastData> {
|
|
180
|
+
/** @deprecated - use timeout */
|
|
181
|
+
duration?: number;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function baseToast(
|
|
185
|
+
messageOrOptions: string | ToastOptions,
|
|
186
|
+
maybeOptions?: ToastOptions,
|
|
187
|
+
) {
|
|
188
|
+
const description =
|
|
189
|
+
typeof messageOrOptions === 'string' ? messageOrOptions : undefined;
|
|
190
|
+
const options =
|
|
191
|
+
typeof messageOrOptions === 'string' ? maybeOptions : messageOrOptions;
|
|
192
|
+
const extraOptions =
|
|
193
|
+
typeof messageOrOptions === 'string' && maybeOptions ? maybeOptions : {};
|
|
194
|
+
|
|
195
|
+
const finalOptions = {
|
|
196
|
+
description,
|
|
197
|
+
timeout:
|
|
198
|
+
options?.duration ??
|
|
199
|
+
extraOptions?.duration ??
|
|
200
|
+
options?.timeout ??
|
|
201
|
+
extraOptions?.timeout,
|
|
202
|
+
...options,
|
|
203
|
+
...extraOptions,
|
|
204
|
+
};
|
|
205
|
+
if (options?.id) {
|
|
206
|
+
manager.update<CustomToastData>(options.id, finalOptions);
|
|
207
|
+
return options.id;
|
|
208
|
+
}
|
|
209
|
+
return manager.add(finalOptions);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export const toast = Object.assign(baseToast, {
|
|
213
|
+
success(
|
|
214
|
+
messageOrOptions: string | ToastOptions,
|
|
215
|
+
maybeOptions?: ToastOptions,
|
|
216
|
+
) {
|
|
217
|
+
return baseToast(messageOrOptions, {
|
|
218
|
+
type: 'success',
|
|
219
|
+
...maybeOptions,
|
|
220
|
+
});
|
|
221
|
+
},
|
|
222
|
+
error(messageOrOptions: string | ToastOptions, maybeOptions?: ToastOptions) {
|
|
223
|
+
return baseToast(messageOrOptions, {
|
|
224
|
+
type: 'error',
|
|
225
|
+
...maybeOptions,
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
promise: function <T>(
|
|
229
|
+
promise: Promise<T>,
|
|
230
|
+
options: ToastManagerPromiseOptions<T, CustomToastData>,
|
|
231
|
+
) {
|
|
232
|
+
return manager.promise(promise, options);
|
|
233
|
+
},
|
|
234
|
+
loading: function (
|
|
235
|
+
messageOrOptions: string | ToastOptions,
|
|
236
|
+
maybeOptions?: ToastOptions,
|
|
237
|
+
) {
|
|
238
|
+
const id = baseToast(messageOrOptions, {
|
|
239
|
+
timeout: 0,
|
|
240
|
+
data: { loading: true },
|
|
241
|
+
...maybeOptions,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
id,
|
|
246
|
+
complete: (
|
|
247
|
+
messageOrOptions: string | ToastOptions,
|
|
248
|
+
maybeOptions?: ToastOptions,
|
|
249
|
+
) => {
|
|
250
|
+
baseToast(messageOrOptions, {
|
|
251
|
+
id,
|
|
252
|
+
data: { loading: false },
|
|
253
|
+
...maybeOptions,
|
|
254
|
+
});
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
export type * from '@base-ui/react/toast';
|
|
261
|
+
export { Toast };
|
|
@@ -136,8 +136,10 @@ export class ViewportState extends EventSubscriber<ViewportEvents> {
|
|
|
136
136
|
this._center = this.getCanvasCenter();
|
|
137
137
|
|
|
138
138
|
this.bindRoot(boundElement ?? null);
|
|
139
|
-
document
|
|
140
|
-
|
|
139
|
+
if (typeof document !== 'undefined') {
|
|
140
|
+
document.addEventListener('gesturestart', preventDefault);
|
|
141
|
+
document.addEventListener('gesturechange', preventDefault);
|
|
142
|
+
}
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
private setBoundElementSize = (size: Size, offset?: Vector2) => {
|
|
@@ -368,8 +370,10 @@ export class ViewportState extends EventSubscriber<ViewportEvents> {
|
|
|
368
370
|
}
|
|
369
371
|
|
|
370
372
|
dispose = () => {
|
|
371
|
-
document
|
|
372
|
-
|
|
373
|
+
if (typeof document !== 'undefined') {
|
|
374
|
+
document.removeEventListener('gesturestart', preventDefault);
|
|
375
|
+
document.removeEventListener('gesturechange', preventDefault);
|
|
376
|
+
}
|
|
373
377
|
};
|
|
374
378
|
|
|
375
379
|
updateConfig = (config: Partial<ViewportConfig>) => {
|
|
@@ -3,7 +3,7 @@ import { PaletteName } from '../uno/index.js';
|
|
|
3
3
|
|
|
4
4
|
export function useOverrideTheme(theme: PaletteName | null | undefined) {
|
|
5
5
|
useLayoutEffect(() => {
|
|
6
|
-
if (!theme) {
|
|
6
|
+
if (!theme || typeof document === 'undefined') {
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
9
|
document.body.classList.add(`theme-override-${theme}`);
|
package/src/hooks/useSize.ts
CHANGED
|
@@ -107,7 +107,7 @@ export function useBounds<E extends HTMLElement>(
|
|
|
107
107
|
|
|
108
108
|
export function useBoundsCssVars<E extends HTMLElement>(
|
|
109
109
|
debounceMs?: number,
|
|
110
|
-
applyToRef?: RefObject<HTMLElement>,
|
|
110
|
+
applyToRef?: RefObject<HTMLElement | null>,
|
|
111
111
|
propertyNames?: {
|
|
112
112
|
left: string;
|
|
113
113
|
top: string;
|
|
@@ -18,6 +18,9 @@ if (typeof document !== 'undefined') {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function changeThemeColor(color: string) {
|
|
21
|
+
if (typeof document === 'undefined') {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
21
24
|
// evaluate css var if necessary
|
|
22
25
|
if (color.startsWith('var(')) {
|
|
23
26
|
const root = document.documentElement;
|