myshell-react-lib 0.1.5 → 0.1.7

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.
Files changed (147) hide show
  1. package/dist/index.cjs +50 -2
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1 -2
  4. package/dist/index.d.ts +1 -2
  5. package/dist/index.js +6 -1
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -2
  8. package/src/common/assets/audio-playing.json +0 -3657
  9. package/src/common/constants/constants.ts +0 -24
  10. package/src/common/constants/types/common.ts +0 -10
  11. package/src/common/hooks/useAudioPlayer.tsx +0 -198
  12. package/src/common/hooks/useDevice.ts +0 -26
  13. package/src/common/hooks/useNativeBridge.ts +0 -42
  14. package/src/common/hooks/useNotification.tsx +0 -179
  15. package/src/common/hooks/useWindowWidth.ts +0 -19
  16. package/src/common/utils/common-helper.ts +0 -81
  17. package/src/components/ItemDemo.tsx +0 -15
  18. package/src/components/accordion.tsx +0 -126
  19. package/src/components/alert-dialog.tsx +0 -148
  20. package/src/components/alert.tsx +0 -65
  21. package/src/components/aspect-ratio.tsx +0 -7
  22. package/src/components/audio-player.tsx +0 -60
  23. package/src/components/audio-playing.tsx +0 -33
  24. package/src/components/avatar.tsx +0 -133
  25. package/src/components/badge.tsx +0 -67
  26. package/src/components/button/button.styles.ts +0 -258
  27. package/src/components/button/button.tsx +0 -215
  28. package/src/components/button/icon-button.styles.ts +0 -103
  29. package/src/components/button/icon-button.tsx +0 -100
  30. package/src/components/button/index.tsx +0 -3
  31. package/src/components/button/link-button.tsx +0 -184
  32. package/src/components/cascader.tsx +0 -175
  33. package/src/components/checkbox.tsx +0 -135
  34. package/src/components/command.tsx +0 -155
  35. package/src/components/context-menu.tsx +0 -198
  36. package/src/components/count-down.tsx +0 -83
  37. package/src/components/custom-notification.tsx +0 -95
  38. package/src/components/dialog.tsx +0 -158
  39. package/src/components/drawer.tsx +0 -116
  40. package/src/components/dropdown-menu.tsx +0 -196
  41. package/src/components/energy-progress.tsx +0 -55
  42. package/src/components/form.tsx +0 -201
  43. package/src/components/group.tsx +0 -9
  44. package/src/components/guide.tsx +0 -243
  45. package/src/components/icon.tsx +0 -96
  46. package/src/components/icons/index.tsx +0 -13
  47. package/src/components/icons/outline/ArrowLeftIcon.tsx +0 -28
  48. package/src/components/icons/outline/ArrowUpTrayIcon.tsx +0 -28
  49. package/src/components/icons/outline/CheckCircleIcon.tsx +0 -27
  50. package/src/components/icons/outline/ConfigIcon.tsx +0 -42
  51. package/src/components/icons/outline/DownIcon.tsx +0 -18
  52. package/src/components/icons/outline/FilterIcon.tsx +0 -20
  53. package/src/components/icons/outline/PencilSquareIcon.tsx +0 -28
  54. package/src/components/icons/outline/WindowIcon.tsx +0 -26
  55. package/src/components/icons/solid/CaretDownIcon.tsx +0 -22
  56. package/src/components/icons/solid/CodeIcon.tsx +0 -25
  57. package/src/components/icons/solid/DragIcon.tsx +0 -24
  58. package/src/components/icons/solid/PhoneIcon.tsx +0 -29
  59. package/src/components/icons/solid/RectangleGroupIcon.tsx +0 -26
  60. package/src/components/image.tsx +0 -152
  61. package/src/components/input.tsx +0 -118
  62. package/src/components/label.tsx +0 -26
  63. package/src/components/link.tsx +0 -123
  64. package/src/components/marquee/index.css +0 -15
  65. package/src/components/marquee/marquee.tsx +0 -220
  66. package/src/components/masonry.tsx +0 -138
  67. package/src/components/menubar.tsx +0 -234
  68. package/src/components/mobile/m-tooltip.tsx +0 -34
  69. package/src/components/modal.tsx +0 -561
  70. package/src/components/navigation-bar.tsx +0 -100
  71. package/src/components/number-input.tsx +0 -143
  72. package/src/components/page-content.tsx +0 -16
  73. package/src/components/popover.tsx +0 -191
  74. package/src/components/progress.tsx +0 -80
  75. package/src/components/radio-group.tsx +0 -44
  76. package/src/components/scroll-area.tsx +0 -49
  77. package/src/components/search-bar.tsx +0 -140
  78. package/src/components/secondary-navigation-bar.tsx +0 -328
  79. package/src/components/select.tsx +0 -273
  80. package/src/components/separator.tsx +0 -31
  81. package/src/components/sheet.tsx +0 -143
  82. package/src/components/skeleton.tsx +0 -20
  83. package/src/components/slider.tsx +0 -160
  84. package/src/components/spinner.tsx +0 -50
  85. package/src/components/swiper/index.module.scss +0 -88
  86. package/src/components/swiper/index.tsx +0 -319
  87. package/src/components/switch.tsx +0 -67
  88. package/src/components/tabs.tsx +0 -325
  89. package/src/components/textarea.tsx +0 -71
  90. package/src/components/toast/toast.tsx +0 -182
  91. package/src/components/toast/toaster.tsx +0 -160
  92. package/src/components/toast/use-toast.tsx +0 -248
  93. package/src/components/toggle-group.tsx +0 -64
  94. package/src/components/toggle.tsx +0 -46
  95. package/src/components/tooltip.tsx +0 -283
  96. package/src/components/typography.tsx +0 -437
  97. package/src/index.ts +0 -70
  98. package/src/lib/utils.ts +0 -62
  99. package/src/stories/Accordion.stories.tsx +0 -64
  100. package/src/stories/AccordionItem.stories.tsx +0 -48
  101. package/src/stories/Avatar.stories.ts +0 -58
  102. package/src/stories/Badge.stories.tsx +0 -40
  103. package/src/stories/BannerSwiper.stories.tsx +0 -102
  104. package/src/stories/Button.stories.tsx +0 -543
  105. package/src/stories/Checkbox.stories.tsx +0 -161
  106. package/src/stories/Configure.mdx +0 -341
  107. package/src/stories/CssProperties.mdx +0 -30
  108. package/src/stories/Description.stories.ts +0 -70
  109. package/src/stories/Display.stories.ts +0 -64
  110. package/src/stories/FeaturedSwiper.stories.tsx +0 -6978
  111. package/src/stories/GridSwiper.stories.tsx +0 -1407
  112. package/src/stories/Guide.stories.tsx +0 -247
  113. package/src/stories/Heading.stories.ts +0 -89
  114. package/src/stories/Icon.stories.ts +0 -77
  115. package/src/stories/IconButton.stories.tsx +0 -301
  116. package/src/stories/IconTextButton.stories.ts +0 -59
  117. package/src/stories/Image.stories.ts +0 -55
  118. package/src/stories/Input.stories.tsx +0 -203
  119. package/src/stories/Modal.stories.tsx +0 -144
  120. package/src/stories/NavigationBar.stories.tsx +0 -81
  121. package/src/stories/Notification.stories.tsx +0 -276
  122. package/src/stories/Popover.stories.tsx +0 -100
  123. package/src/stories/SearchBar.stories.ts +0 -43
  124. package/src/stories/SecondaryNavigationBar.stories.tsx +0 -199
  125. package/src/stories/Select.stories.tsx +0 -107
  126. package/src/stories/Separator.stories.tsx +0 -49
  127. package/src/stories/Spinner.stories.tsx +0 -48
  128. package/src/stories/SubHeading.stories.ts +0 -64
  129. package/src/stories/Swich.stories.tsx +0 -69
  130. package/src/stories/Tabs.stories.tsx +0 -90
  131. package/src/stories/Text.stories.ts +0 -78
  132. package/src/stories/Textarea.stories.tsx +0 -155
  133. package/src/stories/Toast.stories.tsx +0 -424
  134. package/src/stories/Tooltip.stories.tsx +0 -244
  135. package/src/stories/ViewAutoSwiper.stories.tsx +0 -1408
  136. package/src/styles/components-dark.scss +0 -212
  137. package/src/styles/components-light.scss +0 -210
  138. package/src/styles/design-dark.scss +0 -330
  139. package/src/styles/design-light.scss +0 -345
  140. package/src/styles/design2-dark.scss +0 -319
  141. package/src/styles/design2-light.scss +0 -364
  142. package/src/styles/font.css +0 -19
  143. package/src/styles/global.scss +0 -251
  144. package/src/styles/md-viewer.scss +0 -155
  145. package/src/styles/new-tokens.scss +0 -255
  146. package/src/styles/tokens.scss +0 -401
  147. package/src/types/scss.d.ts +0 -24
@@ -1,71 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { cn } from '@/lib/utils';
4
-
5
- import { Text } from './typography';
6
-
7
- export type TextareaProps =
8
- React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
9
- maxLengthClassName?: string;
10
- };
11
- const Textarea = React.forwardRef<
12
- HTMLTextAreaElement,
13
- TextareaProps & { error?: string }
14
- >(
15
- (
16
- { className, maxLength, value, error, maxLengthClassName, ...props },
17
- ref
18
- ) => {
19
- return (
20
- <div>
21
- <div className="relative">
22
- <textarea
23
- className={cn(
24
- 'w-full min-h-[123px] p-3 pb-10 rounded-lg border border-Colors-Border-Default bg-Colors-Background-Normal-Primary-Active ',
25
- 'text-sm text-Colors-Text-Default placeholder:text-Colors-Text-Subtlest ring-offset-cc-Focus-Rings-Brand-default',
26
- 'hover:border-hovered bg-cc-Input-bg-default hover:bg-cc-Input-bg-hover disabled:bg-cc-Input-bg-disabled aria-[invalid=true]:border-Colors-Border-Critical aria-[invalid=true]:hover:bg-Colors-Background-Critical-Subtle',
27
- 'aria-[invalid=true]:focus-visible:ring-error file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-Colors-Text-Subtler',
28
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cc-Focus-Rings-Brand-default focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-30',
29
- (maxLength && (value?.toString()?.length || 0) > maxLength) ||
30
- error
31
- ? 'border-Colors-Border-Critical hover:bg-Colors-Background-Critical-Subtle focus-visible:ring-error'
32
- : '',
33
- className
34
- )}
35
- ref={ref}
36
- maxLength={maxLength}
37
- value={value}
38
- {...props}
39
- />
40
- {maxLength ? (
41
- <div
42
- className={cn(
43
- 'absolute text-right bottom-5 right-4 border-Colors-Border-Default',
44
- maxLengthClassName
45
- )}
46
- >
47
- <Text size="sm" color="subtlest">{`${
48
- value?.toString()?.length || 0
49
- }/${maxLength}`}</Text>
50
- </div>
51
- ) : null}
52
- </div>
53
- {error && (
54
- <div className="w-full">
55
- <Text
56
- className="text-wrap"
57
- size="sm"
58
- weight="regular"
59
- color="critical"
60
- >
61
- {error}
62
- </Text>
63
- </div>
64
- )}
65
- </div>
66
- );
67
- }
68
- );
69
- Textarea.displayName = 'Textarea';
70
-
71
- export { Textarea };
@@ -1,182 +0,0 @@
1
- 'use client';
2
-
3
- import * as ToastPrimitives from '@radix-ui/react-toast';
4
- import { cva, type VariantProps } from 'class-variance-authority';
5
- import * as React from 'react';
6
- import { cn } from '@/lib/utils';
7
- import XMarkIcon from '@heroicons/react/24/outline/esm/XMarkIcon';
8
-
9
- const ToastProvider = ToastPrimitives.Provider;
10
-
11
- const viewportPositionVariants = cva(
12
- 'fixed z-[1000001] flex max-h-screen w-full p-0 gap-2',
13
- {
14
- variants: {
15
- position: {
16
- 'top-left': 'top-6 left-6 flex-col items-start',
17
- 'top-center': 'top-6 left-1/2 -translate-x-1/2 flex-col items-center',
18
- 'top-right': 'top-6 right-6 flex-col items-end',
19
- 'bottom-left': 'bottom-6 left-6 flex-col-reverse items-start',
20
- 'bottom-center':
21
- 'bottom-6 left-1/2 -translate-x-1/2 flex-col-reverse items-center',
22
- 'bottom-right': 'bottom-6 right-6 flex-col-reverse items-end',
23
- 'left-center': 'left-6 top-1/2 -translate-y-1/2 flex-row items-center',
24
- 'right-center':
25
- 'right-6 top-1/2 -translate-y-1/2 flex-row-reverse items-center',
26
- },
27
- },
28
- defaultVariants: {
29
- position: 'top-right',
30
- },
31
- }
32
- );
33
-
34
- interface ToastViewportProps
35
- extends React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport> {
36
- position?:
37
- | 'top-left'
38
- | 'top-center'
39
- | 'top-right'
40
- | 'bottom-left'
41
- | 'bottom-center'
42
- | 'bottom-right'
43
- | 'left-center'
44
- | 'right-center';
45
- }
46
-
47
- const ToastViewport = React.forwardRef<
48
- React.ElementRef<typeof ToastPrimitives.Viewport>,
49
- ToastViewportProps
50
- >(({ className, position, ...props }, ref) => (
51
- <ToastPrimitives.Viewport
52
- ref={ref}
53
- className={cn(viewportPositionVariants({ position }), className)}
54
- {...props}
55
- />
56
- ));
57
- ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
58
-
59
- const toastVariants = cva(
60
- 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border border-Colors-Border-Opaque p-6 pr-8 shadow-modal-default transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 max-w-md',
61
- {
62
- variants: {
63
- variant: {
64
- info: 'bg-Colors-Background-Normal-Primary-Default p-4',
65
- warning: 'bg-Colors-Background-Normal-Primary-Default p-4',
66
- error: 'bg-Colors-Background-Normal-Primary-Default p-4',
67
- success: 'bg-Colors-Background-Normal-Primary-Default p-4',
68
- },
69
- position: {
70
- 'top-left':
71
- 'data-[state=open]:slide-in-from-left-full data-[state=closed]:slide-out-to-left-full',
72
- 'top-center':
73
- 'data-[state=open]:slide-in-from-top-full data-[state=closed]:slide-out-to-top-full',
74
- 'top-right':
75
- 'data-[state=open]:slide-in-from-right-full data-[state=closed]:slide-out-to-right-full',
76
- 'bottom-left':
77
- 'data-[state=open]:slide-in-from-left-full data-[state=closed]:slide-out-to-left-full',
78
- 'bottom-center':
79
- 'data-[state=open]:slide-in-from-bottom-full data-[state=closed]:slide-out-to-bottom-full',
80
- 'bottom-right':
81
- 'data-[state=open]:slide-in-from-right-full data-[state=closed]:slide-out-to-right-full',
82
- 'left-center':
83
- 'data-[state=open]:slide-in-from-left-full data-[state=closed]:slide-out-to-left-full',
84
- 'right-center':
85
- 'data-[state=open]:slide-in-from-right-full data-[state=closed]:slide-out-to-right-full',
86
- },
87
- },
88
- defaultVariants: {
89
- variant: 'info',
90
- position: 'top-right',
91
- },
92
- }
93
- );
94
-
95
- const Toast = React.forwardRef<
96
- React.ElementRef<typeof ToastPrimitives.Root>,
97
- React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
98
- VariantProps<typeof toastVariants>
99
- >(({ className, variant, position, ...props }, ref) => {
100
- return (
101
- <ToastPrimitives.Root
102
- ref={ref}
103
- className={cn(toastVariants({ variant, position }), className)}
104
- data-position={position}
105
- {...props}
106
- />
107
- );
108
- });
109
- Toast.displayName = ToastPrimitives.Root.displayName;
110
-
111
- const ToastAction = React.forwardRef<
112
- React.ElementRef<typeof ToastPrimitives.Action>,
113
- React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
114
- >(({ className, ...props }, ref) => (
115
- <ToastPrimitives.Action
116
- ref={ref}
117
- className={cn(
118
- 'inline-flex h-8 shrink-0 items-center justify-center rounded-md border border-slate-200 bg-transparent px-3 text-sm font-medium ring-offset-white transition-colors hover:bg-slate-100 focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-slate-100/40 group-[.destructive]:hover:border-red-500/30 group-[.destructive]:hover:bg-red-500 group-[.destructive]:hover:text-slate-50 group-[.destructive]:focus:ring-red-500 dark:border-slate-800 dark:ring-offset-slate-950 dark:hover:bg-slate-800 dark:focus:ring-slate-300 dark:group-[.destructive]:border-slate-800/40 dark:group-[.destructive]:hover:border-red-900/30 dark:group-[.destructive]:hover:bg-red-900 dark:group-[.destructive]:hover:text-slate-50 dark:group-[.destructive]:focus:ring-red-900',
119
- className
120
- )}
121
- {...props}
122
- />
123
- ));
124
- ToastAction.displayName = ToastPrimitives.Action.displayName;
125
-
126
- const ToastClose = React.forwardRef<
127
- React.ElementRef<typeof ToastPrimitives.Close>,
128
- React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
129
- >(({ className, ...props }, ref) => (
130
- <ToastPrimitives.Close
131
- ref={ref}
132
- className={cn(
133
- 'absolute right-4 top-4 rounded-md p-1 text-slate-950/50 transition-opacity hover:text-slate-950 outline-none focus:outline-none focus:ring-2 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600 dark:text-slate-50/50 dark:hover:text-slate-50',
134
- className
135
- )}
136
- toast-close=""
137
- {...props}
138
- >
139
- <XMarkIcon className="h-5 w-5" />
140
- </ToastPrimitives.Close>
141
- ));
142
- ToastClose.displayName = ToastPrimitives.Close.displayName;
143
-
144
- const ToastTitle = React.forwardRef<
145
- React.ElementRef<typeof ToastPrimitives.Title>,
146
- React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
147
- >(({ className, ...props }, ref) => (
148
- <ToastPrimitives.Title
149
- ref={ref}
150
- className={cn('text-sm font-semibold', className)}
151
- {...props}
152
- />
153
- ));
154
- ToastTitle.displayName = ToastPrimitives.Title.displayName;
155
-
156
- const ToastDescription = React.forwardRef<
157
- React.ElementRef<typeof ToastPrimitives.Description>,
158
- React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
159
- >(({ className, ...props }, ref) => (
160
- <ToastPrimitives.Description
161
- ref={ref}
162
- className={cn('text-sm opacity-90', className)}
163
- {...props}
164
- />
165
- ));
166
- ToastDescription.displayName = ToastPrimitives.Description.displayName;
167
-
168
- type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
169
-
170
- type ToastActionElement = React.ReactElement<typeof ToastAction>;
171
-
172
- export {
173
- type ToastProps,
174
- type ToastActionElement,
175
- ToastProvider,
176
- ToastViewport,
177
- Toast,
178
- ToastTitle,
179
- ToastDescription,
180
- ToastClose,
181
- ToastAction,
182
- };
@@ -1,160 +0,0 @@
1
- 'use client';
2
-
3
- import CheckCircleIcon from '@heroicons/react/24/outline/esm/CheckCircleIcon';
4
- import ExclamationCircleIcon from '@heroicons/react/24/outline/esm/ExclamationCircleIcon';
5
- import InformationCircleIcon from '@heroicons/react/24/outline/esm/InformationCircleIcon';
6
- import XCircleIcon from '@heroicons/react/24/outline/esm/XCircleIcon';
7
-
8
- import {
9
- Toast,
10
- ToastClose,
11
- ToastDescription,
12
- ToastProvider,
13
- ToastTitle,
14
- ToastViewport,
15
- } from './toast';
16
- import { useToast } from './use-toast';
17
- import { cn } from '@/lib/utils';
18
- import React from 'react';
19
-
20
- type ToastVariant = 'info' | 'success' | 'warning' | 'error' | null | undefined;
21
-
22
- export interface ToasterProps {
23
- position?:
24
- | 'top-left'
25
- | 'top-center'
26
- | 'top-right'
27
- | 'bottom-left'
28
- | 'bottom-center'
29
- | 'bottom-right'
30
- | 'left-center'
31
- | 'right-center';
32
- }
33
-
34
- export function Toaster({ position = 'top-right' }: ToasterProps = {}) {
35
- const { toasts } = useToast();
36
-
37
- // 按位置分组
38
- const positionGroups = React.useMemo(() => {
39
- const groups: Record<string, typeof toasts> = {};
40
-
41
- const allPositions = [
42
- 'top-left',
43
- 'top-center',
44
- 'top-right',
45
- 'bottom-left',
46
- 'bottom-center',
47
- 'bottom-right',
48
- 'left-center',
49
- 'right-center',
50
- ];
51
-
52
- // 初始化所有位置组
53
- allPositions.forEach((pos) => {
54
- groups[pos] = [];
55
- });
56
-
57
- // 将每个Toast按其position分组,如果没有指定则使用默认位置
58
- toasts.forEach((toast) => {
59
- const toastPosition = toast.position || position;
60
- if (groups[toastPosition]) {
61
- groups[toastPosition].push(toast);
62
- } else {
63
- // 如果位置不在预定义列表中,则使用默认位置
64
- groups[position].push(toast);
65
- }
66
- });
67
-
68
- return groups;
69
- }, [toasts, position]);
70
-
71
- const renderToast = (toast: any) => {
72
- const {
73
- id,
74
- title,
75
- description,
76
- action,
77
- variant,
78
- position: toastPosition,
79
- } = toast;
80
-
81
- const renderIcon = (variant: ToastVariant) => {
82
- switch (variant) {
83
- case 'info':
84
- return (
85
- <InformationCircleIcon className="h-6 w-6 text-cc-Icon-Featured-icon-fg-Info" />
86
- );
87
- case 'success':
88
- return (
89
- <CheckCircleIcon className="h-6 w-6 text-cc-Icon-Featured-icon-fg-Success" />
90
- );
91
- case 'warning':
92
- return (
93
- <ExclamationCircleIcon className="h-6 w-6 text-cc-Icon-Featured-icon-fg-Warning" />
94
- );
95
- case 'error':
96
- return (
97
- <XCircleIcon className="h-6 w-6 text-cc-Icon-Featured-icon-fg-Error" />
98
- );
99
- }
100
- };
101
-
102
- const getBackgroundColor = (variant: ToastVariant) => {
103
- switch (variant) {
104
- case 'info':
105
- return 'bg-Colors-Background-Info-Default';
106
- case 'success':
107
- return 'bg-Colors-Background-Success-Default';
108
- case 'warning':
109
- return 'bg-Colors-Background-Warning-Default';
110
- case 'error':
111
- return 'bg-Colors-Background-Critical-Default';
112
- }
113
- };
114
-
115
- return (
116
- <Toast key={id} {...toast} position={toastPosition}>
117
- <div className="flex flex-col gap-3">
118
- <div className="flex items-start gap-3">
119
- <div
120
- className={cn(
121
- 'flex h-10 w-10 flex-shrink-0 flex-grow-0 items-center justify-center rounded-full',
122
- getBackgroundColor(variant)
123
- )}
124
- >
125
- {renderIcon(variant)}
126
- </div>
127
- <div className="grid gap-1">
128
- {title && (
129
- <ToastTitle className="text-base text-Colors-Text-Default">
130
- {title}
131
- </ToastTitle>
132
- )}
133
- {description && (
134
- <ToastDescription className="text-sm text-Colors-Text-Subtle">
135
- {description}
136
- </ToastDescription>
137
- )}
138
- {action}
139
- </div>
140
- </div>
141
- </div>
142
- <ToastClose />
143
- </Toast>
144
- );
145
- };
146
-
147
- return (
148
- <ToastProvider>
149
- {/* 为每个位置渲染一个ToastViewport */}
150
- {Object.entries(positionGroups).map(([pos, toastsForPosition]) => (
151
- <React.Fragment key={pos}>
152
- {toastsForPosition.map(renderToast)}
153
- {toastsForPosition.length > 0 && (
154
- <ToastViewport position={pos as any} />
155
- )}
156
- </React.Fragment>
157
- ))}
158
- </ToastProvider>
159
- );
160
- }
@@ -1,248 +0,0 @@
1
- 'use client';
2
-
3
- // Inspired by react-hot-toast library
4
- import * as React from 'react';
5
- import { ToastActionElement, ToastProps } from './toast';
6
- import { Text } from '../typography';
7
- import Link from '../link';
8
- const TOAST_LIMIT = 8;
9
- const TOAST_REMOVE_DELAY = 1000;
10
-
11
- type ToasterToast = ToastProps & {
12
- id: string;
13
- title?: React.ReactNode;
14
- description?: React.ReactNode;
15
- action?: ToastActionElement;
16
- };
17
-
18
- const actionTypes = {
19
- ADD_TOAST: 'ADD_TOAST',
20
- UPDATE_TOAST: 'UPDATE_TOAST',
21
- DISMISS_TOAST: 'DISMISS_TOAST',
22
- REMOVE_TOAST: 'REMOVE_TOAST',
23
- } as const;
24
-
25
- let count = 0;
26
-
27
- function genId() {
28
- count = (count + 1) % Number.MAX_SAFE_INTEGER;
29
-
30
- return count.toString();
31
- }
32
-
33
- type ActionType = typeof actionTypes;
34
-
35
- type Action =
36
- | {
37
- type: ActionType['ADD_TOAST'];
38
- toast: ToasterToast;
39
- }
40
- | {
41
- type: ActionType['UPDATE_TOAST'];
42
- toast: Partial<ToasterToast>;
43
- }
44
- | {
45
- type: ActionType['DISMISS_TOAST'];
46
- toastId?: ToasterToast['id'];
47
- }
48
- | {
49
- type: ActionType['REMOVE_TOAST'];
50
- toastId?: ToasterToast['id'];
51
- };
52
-
53
- interface State {
54
- toasts: ToasterToast[];
55
- }
56
-
57
- const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
58
-
59
- const addToRemoveQueue = (toastId: string) => {
60
- if (toastTimeouts.has(toastId)) {
61
- return;
62
- }
63
-
64
- const timeout = setTimeout(() => {
65
- toastTimeouts.delete(toastId);
66
- dispatch({
67
- type: 'REMOVE_TOAST',
68
- toastId,
69
- });
70
- }, TOAST_REMOVE_DELAY);
71
-
72
- toastTimeouts.set(toastId, timeout);
73
- };
74
-
75
- export const reducer = (state: State, action: Action): State => {
76
- switch (action.type) {
77
- case 'ADD_TOAST':
78
- return {
79
- ...state,
80
- toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
81
- };
82
-
83
- case 'UPDATE_TOAST':
84
- return {
85
- ...state,
86
- toasts: state.toasts.map((t) =>
87
- t.id === action.toast.id ? { ...t, ...action.toast } : t
88
- ),
89
- };
90
-
91
- case 'DISMISS_TOAST': {
92
- const { toastId } = action;
93
-
94
- // ! Side effects ! - This could be extracted into a dismissToast() action,
95
- // but I'll keep it here for simplicity
96
- if (toastId) {
97
- addToRemoveQueue(toastId);
98
- } else {
99
- state.toasts.forEach((toast) => {
100
- addToRemoveQueue(toast.id);
101
- });
102
- }
103
-
104
- return {
105
- ...state,
106
- toasts: state.toasts.map((t) =>
107
- t.id === toastId || toastId === undefined
108
- ? {
109
- ...t,
110
- open: false,
111
- }
112
- : t
113
- ),
114
- };
115
- }
116
- case 'REMOVE_TOAST':
117
- if (action.toastId === undefined) {
118
- return {
119
- ...state,
120
- toasts: [],
121
- };
122
- }
123
-
124
- return {
125
- ...state,
126
- toasts: state.toasts.filter((t) => t.id !== action.toastId),
127
- };
128
- }
129
- };
130
-
131
- const listeners: Array<(state: State) => void> = [];
132
-
133
- let memoryState: State = { toasts: [] };
134
-
135
- function dispatch(action: Action) {
136
- memoryState = reducer(memoryState, action);
137
- listeners.forEach((listener) => {
138
- listener(memoryState);
139
- });
140
- }
141
-
142
- type Toast = Omit<ToasterToast, 'id'> & {
143
- actions?: {
144
- dismissText?: string;
145
- view?: string;
146
- viewUrl?: string;
147
- };
148
- toastId?: string;
149
- position?:
150
- | 'top-left'
151
- | 'top-center'
152
- | 'top-right'
153
- | 'bottom-left'
154
- | 'bottom-center'
155
- | 'bottom-right'
156
- | 'left-center'
157
- | 'right-center';
158
- };
159
-
160
- function toast({ actions, toastId, position, ...props }: Toast) {
161
- const id = toastId || genId();
162
-
163
- const update = (props: ToasterToast) =>
164
- dispatch({
165
- type: 'UPDATE_TOAST',
166
- toast: { ...props, id },
167
- });
168
- const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id });
169
-
170
- dispatch({
171
- type: 'ADD_TOAST',
172
- toast: {
173
- ...props,
174
- position,
175
- ...(actions && {
176
- action: (
177
- <div className="flex justify-start items-center gap-2">
178
- {actions?.dismissText && (
179
- <Text
180
- size="sm"
181
- weight="medium"
182
- color="brand"
183
- className="cursor-pointer"
184
- onClick={() => {
185
- dismiss();
186
- }}
187
- >
188
- {actions?.dismissText}
189
- </Text>
190
- )}
191
- {actions?.view && actions.viewUrl && (
192
- <Link
193
- href={actions.viewUrl}
194
- target="_blank"
195
- rel="noreferrer noopener"
196
- >
197
- <div className="flex items-center gap-1.5">
198
- <Text
199
- size="sm"
200
- weight="medium"
201
- color="default"
202
- className="cursor-pointer"
203
- >
204
- {actions.view}
205
- </Text>
206
- </div>
207
- </Link>
208
- )}
209
- </div>
210
- ),
211
- }),
212
- id,
213
- open: true,
214
- onOpenChange: (open) => {
215
- if (!open) dismiss();
216
- },
217
- },
218
- });
219
-
220
- return {
221
- id,
222
- dismiss,
223
- update,
224
- };
225
- }
226
-
227
- function useToast() {
228
- const [state, setState] = React.useState<State>(memoryState);
229
-
230
- React.useEffect(() => {
231
- listeners.push(setState);
232
-
233
- return () => {
234
- const index = listeners.indexOf(setState);
235
- if (index > -1) {
236
- listeners.splice(index, 1);
237
- }
238
- };
239
- }, [state]);
240
-
241
- return {
242
- ...state,
243
- toast,
244
- dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
245
- };
246
- }
247
-
248
- export { toast, useToast };