@scripso-homepad/ui 0.4.9 → 0.4.10
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/index.cjs +123 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +123 -84
- package/dist/index.js.map +1 -1
- package/dist/web/index.cjs +413 -22
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.css +161 -0
- package/dist/web/index.css.map +1 -1
- package/dist/web/index.d.cts +48 -1
- package/dist/web/index.d.ts +48 -1
- package/dist/web/index.js +406 -23
- package/dist/web/index.js.map +1 -1
- package/package.json +9 -3
- package/src/components/DatePicker.tsx +37 -3
- package/src/web/components/Drawer.stories.tsx +234 -0
- package/src/web/components/Drawer.tsx +169 -0
- package/src/web/components/HistoryTimeline.tsx +46 -0
- package/src/web/components/Modal.tsx +5 -5
- package/src/web/components/TableActionButton.tsx +3 -3
- package/src/web/components/Toaster.stories.tsx +106 -0
- package/src/web/components/Toaster.tsx +92 -0
- package/src/web/components/ToasterProvider.tsx +6 -0
- package/src/web/components/drawer-scroll.css +41 -0
- package/src/web/components/sonner-toast.css +141 -0
- package/src/web/icons/TimelineCheckIcon.tsx +24 -0
- package/src/web/icons/ToastIcons.tsx +119 -0
- package/src/web/index.ts +20 -0
- package/src/web/mutation-toast.ts +33 -0
- package/src/web/toast.ts +1 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
import { WebLayoutCanvas } from '../layout/story-helpers';
|
|
5
|
+
import { toast } from '../toast';
|
|
6
|
+
|
|
7
|
+
import { Toaster } from './Toaster';
|
|
8
|
+
|
|
9
|
+
const toastCopy = {
|
|
10
|
+
title: 'Title',
|
|
11
|
+
description: 'Description',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: 'Web Components/Toaster',
|
|
16
|
+
component: Toaster,
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: 'fullscreen',
|
|
19
|
+
webLayout: true,
|
|
20
|
+
},
|
|
21
|
+
} satisfies Meta<typeof Toaster>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof meta>;
|
|
25
|
+
|
|
26
|
+
function ToastTriggerPanel() {
|
|
27
|
+
return (
|
|
28
|
+
<WebLayoutCanvas className="min-h-screen bg-storm-gray-100 p-6">
|
|
29
|
+
<div className="mx-auto flex w-full max-w-md flex-col gap-3 rounded-2xl border border-storm-gray-50 bg-white p-6 shadow-sm">
|
|
30
|
+
<h2 className="font-sans text-lg font-bold text-slate-blue">Toast preview</h2>
|
|
31
|
+
<p className="font-sans text-sm text-storm-gray-400">
|
|
32
|
+
Click a button to show a toast in the bottom-right corner.
|
|
33
|
+
</p>
|
|
34
|
+
<div className="flex flex-col gap-2">
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
className="rounded-xl border border-storm-gray-50 px-4 py-2 text-left text-sm font-medium text-slate-blue transition-colors hover:bg-storm-gray-0"
|
|
38
|
+
onClick={() => toast.success(toastCopy.title, { description: toastCopy.description })}
|
|
39
|
+
>
|
|
40
|
+
Success
|
|
41
|
+
</button>
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
className="rounded-xl border border-storm-gray-50 px-4 py-2 text-left text-sm font-medium text-slate-blue transition-colors hover:bg-storm-gray-0"
|
|
45
|
+
onClick={() => toast.error(toastCopy.title, { description: toastCopy.description })}
|
|
46
|
+
>
|
|
47
|
+
Error
|
|
48
|
+
</button>
|
|
49
|
+
<button
|
|
50
|
+
type="button"
|
|
51
|
+
className="rounded-xl border border-storm-gray-50 px-4 py-2 text-left text-sm font-medium text-slate-blue transition-colors hover:bg-storm-gray-0"
|
|
52
|
+
onClick={() => toast.warning(toastCopy.title, { description: toastCopy.description })}
|
|
53
|
+
>
|
|
54
|
+
Warning
|
|
55
|
+
</button>
|
|
56
|
+
<button
|
|
57
|
+
type="button"
|
|
58
|
+
className="rounded-xl border border-storm-gray-50 px-4 py-2 text-left text-sm font-medium text-slate-blue transition-colors hover:bg-storm-gray-0"
|
|
59
|
+
onClick={() => toast.info(toastCopy.title, { description: toastCopy.description })}
|
|
60
|
+
>
|
|
61
|
+
Info
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<Toaster />
|
|
66
|
+
</WebLayoutCanvas>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function AllTypesStory() {
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
toast.success(toastCopy.title, { description: toastCopy.description });
|
|
73
|
+
toast.error(toastCopy.title, { description: toastCopy.description });
|
|
74
|
+
toast.warning(toastCopy.title, { description: toastCopy.description });
|
|
75
|
+
toast.info(toastCopy.title, { description: toastCopy.description });
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<WebLayoutCanvas className="min-h-screen bg-storm-gray-100">
|
|
80
|
+
<Toaster />
|
|
81
|
+
</WebLayoutCanvas>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const Interactive: Story = {
|
|
86
|
+
render: () => <ToastTriggerPanel />,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const AllTypes: Story = {
|
|
90
|
+
render: () => <AllTypesStory />,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const TitleOnly: Story = {
|
|
94
|
+
render: () => (
|
|
95
|
+
<WebLayoutCanvas className="min-h-screen bg-storm-gray-100 p-6">
|
|
96
|
+
<button
|
|
97
|
+
type="button"
|
|
98
|
+
className="rounded-xl border border-storm-gray-50 bg-white px-4 py-2 text-sm font-medium text-slate-blue"
|
|
99
|
+
onClick={() => toast.success('Request approved.')}
|
|
100
|
+
>
|
|
101
|
+
Show title-only toast
|
|
102
|
+
</button>
|
|
103
|
+
<Toaster />
|
|
104
|
+
</WebLayoutCanvas>
|
|
105
|
+
),
|
|
106
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { Toaster as SonnerToaster, type ToasterProps } from 'sonner';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ToastCloseIcon,
|
|
6
|
+
ToastErrorIcon,
|
|
7
|
+
ToastInfoIcon,
|
|
8
|
+
ToastSuccessIcon,
|
|
9
|
+
ToastWarningIcon,
|
|
10
|
+
} from '../icons/ToastIcons';
|
|
11
|
+
|
|
12
|
+
import 'sonner/dist/styles.css';
|
|
13
|
+
import './sonner-toast.css';
|
|
14
|
+
|
|
15
|
+
function ToastIconBadge({
|
|
16
|
+
tone,
|
|
17
|
+
children,
|
|
18
|
+
}: {
|
|
19
|
+
tone: 'success' | 'error' | 'warning' | 'info' | 'default';
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
}) {
|
|
22
|
+
return (
|
|
23
|
+
<div className={`homepad-toast__icon-badge homepad-toast__icon-badge--${tone}`}>
|
|
24
|
+
{children}
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const homepadToastIcons = {
|
|
30
|
+
success: (
|
|
31
|
+
<ToastIconBadge tone="success">
|
|
32
|
+
<ToastSuccessIcon />
|
|
33
|
+
</ToastIconBadge>
|
|
34
|
+
),
|
|
35
|
+
error: (
|
|
36
|
+
<ToastIconBadge tone="error">
|
|
37
|
+
<ToastErrorIcon />
|
|
38
|
+
</ToastIconBadge>
|
|
39
|
+
),
|
|
40
|
+
warning: (
|
|
41
|
+
<ToastIconBadge tone="warning">
|
|
42
|
+
<ToastWarningIcon />
|
|
43
|
+
</ToastIconBadge>
|
|
44
|
+
),
|
|
45
|
+
info: (
|
|
46
|
+
<ToastIconBadge tone="info">
|
|
47
|
+
<ToastInfoIcon />
|
|
48
|
+
</ToastIconBadge>
|
|
49
|
+
),
|
|
50
|
+
close: <ToastCloseIcon />,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type HomepadToasterProps = Omit<ToasterProps, 'richColors'>;
|
|
54
|
+
|
|
55
|
+
export function Toaster({
|
|
56
|
+
className,
|
|
57
|
+
position = 'bottom-right',
|
|
58
|
+
theme = 'light',
|
|
59
|
+
closeButton = true,
|
|
60
|
+
gap = 12,
|
|
61
|
+
offset = 20,
|
|
62
|
+
toastOptions,
|
|
63
|
+
icons,
|
|
64
|
+
...props
|
|
65
|
+
}: HomepadToasterProps) {
|
|
66
|
+
return (
|
|
67
|
+
<SonnerToaster
|
|
68
|
+
className={['homepad-toaster', className].filter(Boolean).join(' ')}
|
|
69
|
+
theme={theme}
|
|
70
|
+
position={position}
|
|
71
|
+
closeButton={closeButton}
|
|
72
|
+
gap={gap}
|
|
73
|
+
offset={offset}
|
|
74
|
+
mobileOffset={8}
|
|
75
|
+
icons={{ ...homepadToastIcons, ...icons }}
|
|
76
|
+
toastOptions={{
|
|
77
|
+
duration: 4000,
|
|
78
|
+
classNames: {
|
|
79
|
+
toast: 'homepad-toast',
|
|
80
|
+
title: 'homepad-toast__title',
|
|
81
|
+
description: 'homepad-toast__description',
|
|
82
|
+
content: 'homepad-toast__content',
|
|
83
|
+
icon: 'homepad-toast__icon',
|
|
84
|
+
closeButton: 'homepad-toast__close',
|
|
85
|
+
...toastOptions?.classNames,
|
|
86
|
+
},
|
|
87
|
+
...toastOptions,
|
|
88
|
+
}}
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
.drawer-scroll-area {
|
|
2
|
+
scrollbar-color: var(--color-storm-gray-200, #d5d9dd) transparent;
|
|
3
|
+
scrollbar-width: thin;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.drawer-scroll-area::-webkit-scrollbar {
|
|
7
|
+
width: 8px;
|
|
8
|
+
-webkit-appearance: none;
|
|
9
|
+
appearance: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.drawer-scroll-area::-webkit-scrollbar-button,
|
|
13
|
+
.drawer-scroll-area::-webkit-scrollbar-button:single-button,
|
|
14
|
+
.drawer-scroll-area::-webkit-scrollbar-button:double-button,
|
|
15
|
+
.drawer-scroll-area::-webkit-scrollbar-button:vertical:decrement,
|
|
16
|
+
.drawer-scroll-area::-webkit-scrollbar-button:vertical:increment,
|
|
17
|
+
.drawer-scroll-area::-webkit-scrollbar-button:vertical:start:decrement,
|
|
18
|
+
.drawer-scroll-area::-webkit-scrollbar-button:vertical:end:increment,
|
|
19
|
+
.drawer-scroll-area::-webkit-scrollbar-button:start:decrement,
|
|
20
|
+
.drawer-scroll-area::-webkit-scrollbar-button:end:increment,
|
|
21
|
+
.drawer-scroll-area::-webkit-scrollbar-button:decrement,
|
|
22
|
+
.drawer-scroll-area::-webkit-scrollbar-button:increment {
|
|
23
|
+
display: none;
|
|
24
|
+
width: 0;
|
|
25
|
+
height: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.drawer-scroll-area::-webkit-scrollbar-track {
|
|
29
|
+
background: transparent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.drawer-scroll-area::-webkit-scrollbar-thumb {
|
|
33
|
+
background-color: var(--color-storm-gray-200, #d5d9dd);
|
|
34
|
+
border-radius: 9999px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@media (max-width: 767px) {
|
|
38
|
+
.drawer-scroll-area::-webkit-scrollbar {
|
|
39
|
+
width: 4px;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
.homepad-toaster {
|
|
2
|
+
--width: 409px;
|
|
3
|
+
--gap: 12px;
|
|
4
|
+
--border-radius: 20px;
|
|
5
|
+
font-family: var(--font-sans, 'Noto Sans Armenian', ui-sans-serif, system-ui, sans-serif);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.homepad-toaster [data-sonner-toast][data-styled='true'] {
|
|
9
|
+
align-items: center;
|
|
10
|
+
gap: 16px;
|
|
11
|
+
width: 409px;
|
|
12
|
+
min-height: 72px;
|
|
13
|
+
height: auto;
|
|
14
|
+
padding: 12px 44px 12px 12px;
|
|
15
|
+
background: #fff;
|
|
16
|
+
border: 1px solid var(--color-storm-gray-50, #eceef0);
|
|
17
|
+
border-radius: 20px;
|
|
18
|
+
box-shadow: 0 0 20px 0 #0000000d;
|
|
19
|
+
color: var(--color-slate-blue, #182e3c);
|
|
20
|
+
overflow: visible;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.homepad-toaster [data-sonner-toast][data-styled='true'][data-front='true'] {
|
|
24
|
+
height: auto !important;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.homepad-toaster
|
|
28
|
+
[data-sonner-toast][data-styled='true'][data-mounted='true'][data-expanded='true'] {
|
|
29
|
+
height: auto !important;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.homepad-toaster [data-sonner-toast][data-styled='true'] [data-icon] {
|
|
33
|
+
width: auto;
|
|
34
|
+
height: auto;
|
|
35
|
+
margin: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.homepad-toaster [data-sonner-toast][data-styled='true'] [data-content] {
|
|
39
|
+
gap: 2px;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
flex: 1;
|
|
42
|
+
align-self: center;
|
|
43
|
+
overflow: visible;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.homepad-toaster .homepad-toast__title {
|
|
47
|
+
font-family: var(--font-sans, 'Noto Sans Armenian', ui-sans-serif, system-ui, sans-serif);
|
|
48
|
+
font-size: 14px;
|
|
49
|
+
font-weight: 700;
|
|
50
|
+
line-height: 22px;
|
|
51
|
+
letter-spacing: 0;
|
|
52
|
+
color: var(--color-slate-blue, #182e3c);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.homepad-toaster .homepad-toast__description {
|
|
56
|
+
font-family: var(--font-sans, 'Noto Sans Armenian', ui-sans-serif, system-ui, sans-serif);
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
font-weight: 400;
|
|
59
|
+
line-height: 1.4;
|
|
60
|
+
letter-spacing: 0;
|
|
61
|
+
color: var(--color-slate-blue, #182e3c);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.homepad-toaster .homepad-toast__icon-badge {
|
|
65
|
+
display: flex;
|
|
66
|
+
width: 48px;
|
|
67
|
+
height: 48px;
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
padding: 12px;
|
|
72
|
+
border-radius: 12px;
|
|
73
|
+
box-sizing: border-box;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.homepad-toaster .homepad-toast__icon-badge svg {
|
|
77
|
+
width: 24px;
|
|
78
|
+
height: 24px;
|
|
79
|
+
margin: 0;
|
|
80
|
+
flex-shrink: 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.homepad-toaster .homepad-toast__icon-badge--success {
|
|
84
|
+
background: var(--color-emerald-green-0, #f0fbf5);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.homepad-toaster .homepad-toast__icon-badge--error {
|
|
88
|
+
background: var(--color-ruby-red-0, #fff5f6);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.homepad-toaster .homepad-toast__icon-badge--warning {
|
|
92
|
+
background: #f2a8001a;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.homepad-toaster .homepad-toast__icon-badge--info,
|
|
96
|
+
.homepad-toaster .homepad-toast__icon-badge--default {
|
|
97
|
+
background: #0f52c71a;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.homepad-toaster [data-sonner-toast][data-styled='true'] [data-close-button] {
|
|
101
|
+
top: 50%;
|
|
102
|
+
right: 12px;
|
|
103
|
+
left: auto;
|
|
104
|
+
width: 20px;
|
|
105
|
+
height: 20px;
|
|
106
|
+
transform: translateY(-50%);
|
|
107
|
+
border: 0;
|
|
108
|
+
background: transparent;
|
|
109
|
+
box-shadow: none;
|
|
110
|
+
cursor: pointer;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.homepad-toaster [data-sonner-toast][data-styled='true']:hover [data-close-button]:hover {
|
|
114
|
+
background: transparent;
|
|
115
|
+
border-color: transparent;
|
|
116
|
+
cursor: pointer;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.homepad-toaster [data-sonner-toast][data-styled='true'] [data-close-button] svg {
|
|
120
|
+
width: 20px;
|
|
121
|
+
height: 20px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@media (max-width: 767px) {
|
|
125
|
+
.homepad-toaster {
|
|
126
|
+
--width: calc(100vw - 16px);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.homepad-toaster[data-sonner-toaster] {
|
|
130
|
+
right: var(--mobile-offset-right, 8px);
|
|
131
|
+
left: var(--mobile-offset-left, 8px);
|
|
132
|
+
width: calc(100vw - 16px);
|
|
133
|
+
max-width: calc(100vw - 16px);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.homepad-toaster [data-sonner-toast][data-styled='true'] {
|
|
137
|
+
right: 0;
|
|
138
|
+
left: 0;
|
|
139
|
+
width: 100%;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SVGProps } from 'react';
|
|
2
|
+
|
|
3
|
+
export function TimelineCheckIcon({ className, ...props }: SVGProps<SVGSVGElement>) {
|
|
4
|
+
return (
|
|
5
|
+
<svg
|
|
6
|
+
width="16"
|
|
7
|
+
height="16"
|
|
8
|
+
viewBox="0 0 16 16"
|
|
9
|
+
fill="none"
|
|
10
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
11
|
+
className={className}
|
|
12
|
+
aria-hidden
|
|
13
|
+
{...props}
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
d="M13.3346 4L6.0013 11.3333L2.66797 8"
|
|
17
|
+
stroke="#279D54"
|
|
18
|
+
strokeWidth="1.5"
|
|
19
|
+
strokeLinecap="round"
|
|
20
|
+
strokeLinejoin="round"
|
|
21
|
+
/>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { SVGProps } from 'react';
|
|
2
|
+
|
|
3
|
+
function ToastCloseIcon(props: SVGProps<SVGSVGElement>) {
|
|
4
|
+
return (
|
|
5
|
+
<svg
|
|
6
|
+
width="20"
|
|
7
|
+
height="20"
|
|
8
|
+
viewBox="0 0 20 20"
|
|
9
|
+
fill="none"
|
|
10
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
11
|
+
aria-hidden
|
|
12
|
+
{...props}
|
|
13
|
+
>
|
|
14
|
+
<path
|
|
15
|
+
d="M15 5L5 15M5 5L15 15"
|
|
16
|
+
stroke="#B5BCC1"
|
|
17
|
+
strokeWidth="2"
|
|
18
|
+
strokeLinecap="round"
|
|
19
|
+
strokeLinejoin="round"
|
|
20
|
+
/>
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function ToastSuccessIcon(props: SVGProps<SVGSVGElement>) {
|
|
26
|
+
return (
|
|
27
|
+
<svg
|
|
28
|
+
width="24"
|
|
29
|
+
height="24"
|
|
30
|
+
viewBox="0 0 24 24"
|
|
31
|
+
fill="none"
|
|
32
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
33
|
+
aria-hidden
|
|
34
|
+
{...props}
|
|
35
|
+
>
|
|
36
|
+
<path
|
|
37
|
+
d="M20 6L9 17L4 12"
|
|
38
|
+
stroke="#279D54"
|
|
39
|
+
strokeWidth="2"
|
|
40
|
+
strokeLinecap="round"
|
|
41
|
+
strokeLinejoin="round"
|
|
42
|
+
/>
|
|
43
|
+
</svg>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function ToastErrorIcon(props: SVGProps<SVGSVGElement>) {
|
|
48
|
+
return (
|
|
49
|
+
<svg
|
|
50
|
+
width="24"
|
|
51
|
+
height="24"
|
|
52
|
+
viewBox="0 0 24 24"
|
|
53
|
+
fill="none"
|
|
54
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
55
|
+
aria-hidden
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
<path
|
|
59
|
+
d="M18 6L6 18M6 6L18 18"
|
|
60
|
+
stroke="#AE0011"
|
|
61
|
+
strokeWidth="2"
|
|
62
|
+
strokeLinecap="round"
|
|
63
|
+
strokeLinejoin="round"
|
|
64
|
+
/>
|
|
65
|
+
</svg>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function ToastWarningIcon(props: SVGProps<SVGSVGElement>) {
|
|
70
|
+
return (
|
|
71
|
+
<svg
|
|
72
|
+
width="24"
|
|
73
|
+
height="24"
|
|
74
|
+
viewBox="0 0 24 24"
|
|
75
|
+
fill="none"
|
|
76
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
77
|
+
aria-hidden
|
|
78
|
+
{...props}
|
|
79
|
+
>
|
|
80
|
+
<path
|
|
81
|
+
d="M12.0001 9.00022V13.0002M12.0001 17.0002H12.0101M21.7301 18.0002L13.7301 4.00022C13.5556 3.69243 13.3027 3.43641 12.997 3.25829C12.6913 3.08017 12.3438 2.98633 11.9901 2.98633C11.6363 2.98633 11.2888 3.08017 10.9831 3.25829C10.6774 3.43641 10.4245 3.69243 10.2501 4.00022L2.25005 18.0002C2.07373 18.3056 1.98128 18.6521 1.98206 19.0047C1.98284 19.3573 2.07683 19.7035 2.2545 20.008C2.43217 20.3126 2.6872 20.5648 2.99375 20.7391C3.30029 20.9133 3.64746 21.0034 4.00005 21.0002H20.0001C20.351 20.9999 20.6956 20.9072 20.9993 20.7315C21.3031 20.5558 21.5553 20.3033 21.7306 19.9993C21.9059 19.6954 21.9981 19.3506 21.998 18.9997C21.9979 18.6488 21.9055 18.3041 21.7301 18.0002Z"
|
|
82
|
+
stroke="#F2A800"
|
|
83
|
+
strokeWidth="2"
|
|
84
|
+
strokeLinecap="round"
|
|
85
|
+
strokeLinejoin="round"
|
|
86
|
+
/>
|
|
87
|
+
</svg>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function ToastInfoIcon(props: SVGProps<SVGSVGElement>) {
|
|
92
|
+
return (
|
|
93
|
+
<svg
|
|
94
|
+
width="24"
|
|
95
|
+
height="24"
|
|
96
|
+
viewBox="0 0 24 24"
|
|
97
|
+
fill="none"
|
|
98
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
99
|
+
aria-hidden
|
|
100
|
+
{...props}
|
|
101
|
+
>
|
|
102
|
+
<path
|
|
103
|
+
d="M12 16V12M12 8H12.01M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z"
|
|
104
|
+
stroke="#0F52C7"
|
|
105
|
+
strokeWidth="2"
|
|
106
|
+
strokeLinecap="round"
|
|
107
|
+
strokeLinejoin="round"
|
|
108
|
+
/>
|
|
109
|
+
</svg>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export {
|
|
114
|
+
ToastCloseIcon,
|
|
115
|
+
ToastErrorIcon,
|
|
116
|
+
ToastInfoIcon,
|
|
117
|
+
ToastSuccessIcon,
|
|
118
|
+
ToastWarningIcon,
|
|
119
|
+
};
|
package/src/web/index.ts
CHANGED
|
@@ -99,6 +99,26 @@ export type { TableIconTextProps } from './components/TableIconText';
|
|
|
99
99
|
export { Modal } from './components/Modal';
|
|
100
100
|
export type { ModalFooterAlign, ModalFooterLayout, ModalProps } from './components/Modal';
|
|
101
101
|
|
|
102
|
+
export { Drawer } from './components/Drawer';
|
|
103
|
+
export type { DrawerProps } from './components/Drawer';
|
|
104
|
+
|
|
105
|
+
export { HistoryTimeline } from './components/HistoryTimeline';
|
|
106
|
+
export type { HistoryTimelineItem, HistoryTimelineProps } from './components/HistoryTimeline';
|
|
107
|
+
|
|
108
|
+
export { Toaster } from './components/Toaster';
|
|
109
|
+
export type { HomepadToasterProps } from './components/Toaster';
|
|
110
|
+
|
|
111
|
+
export { ToasterProvider } from './components/ToasterProvider';
|
|
112
|
+
|
|
113
|
+
export { toast } from './toast';
|
|
114
|
+
|
|
115
|
+
export {
|
|
116
|
+
runMutationWithToast,
|
|
117
|
+
type MutationToastMessages,
|
|
118
|
+
type MutationToastResult,
|
|
119
|
+
type RunMutationWithToastOptions,
|
|
120
|
+
} from './mutation-toast';
|
|
121
|
+
|
|
102
122
|
export { ConfirmModal } from './components/ConfirmModal';
|
|
103
123
|
export type { ConfirmModalProps } from './components/ConfirmModal';
|
|
104
124
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { toast } from './toast';
|
|
2
|
+
|
|
3
|
+
export type MutationToastMessages = {
|
|
4
|
+
success: string;
|
|
5
|
+
error: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type MutationToastResult = {
|
|
9
|
+
success: boolean;
|
|
10
|
+
errorMessage?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type RunMutationWithToastOptions = {
|
|
14
|
+
getErrorMessage?: (error: unknown) => string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export async function runMutationWithToast(
|
|
18
|
+
action: () => Promise<unknown>,
|
|
19
|
+
messages: MutationToastMessages,
|
|
20
|
+
options?: RunMutationWithToastOptions,
|
|
21
|
+
): Promise<MutationToastResult> {
|
|
22
|
+
try {
|
|
23
|
+
await action();
|
|
24
|
+
toast.success(messages.success);
|
|
25
|
+
|
|
26
|
+
return { success: true };
|
|
27
|
+
} catch (error) {
|
|
28
|
+
const errorMessage = options?.getErrorMessage?.(error) ?? messages.error;
|
|
29
|
+
toast.error(errorMessage);
|
|
30
|
+
|
|
31
|
+
return { success: false, errorMessage };
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/web/toast.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { toast } from 'sonner';
|