@particle-network/ui-react 0.4.0-beta.2 → 0.4.0-beta.20
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/components/ProgressWrapper/index.d.ts +1 -1
- package/dist/components/ProgressWrapper/index.js +18 -3
- package/dist/components/UXAutocomplete/index.d.ts +5 -0
- package/dist/components/UXAutocomplete/index.js +72 -0
- package/dist/components/UXDrawer/index.d.ts +9 -0
- package/dist/components/UXDrawer/index.js +89 -0
- package/dist/components/UXDropdown/dropdown-item.js +1 -1
- package/dist/components/UXEmpty/index.js +3 -1
- package/dist/components/UXInput/index.d.ts +28 -28
- package/dist/components/UXInput/input.extend.d.ts +28 -28
- package/dist/components/UXModal/index.js +3 -1
- package/dist/components/UXSelect/index.js +2 -2
- package/dist/components/UXSwitch/index.d.ts +17 -17
- package/dist/components/UXSwitch/switch.extend.d.ts +17 -17
- package/dist/components/UXTable/index.d.ts +17 -17
- package/dist/components/UXTable/table.extend.d.ts +17 -17
- package/dist/components/UXTabs/tabs.classes.js +7 -7
- package/dist/components/UXThemeSwitch/index.d.ts +0 -1
- package/dist/components/UXThemeSwitch/index.js +0 -1
- package/dist/components/UXThemeSwitch/theme-item.d.ts +1 -1
- package/dist/components/UXThemeSwitch/theme-item.js +5 -4
- package/dist/components/UXThemeSwitch/theme-switch.js +72 -86
- package/dist/components/UXThemeSwitch/use-color-scheme.d.ts +1 -1
- package/dist/components/UXThemeSwitch/use-theme-color.d.ts +1 -19
- package/dist/components/UXThemeSwitch/use-theme-store.d.ts +1 -6
- package/dist/components/UXThemeSwitch/use-theme-store.js +2 -6
- package/dist/components/UXThemeSwitch/use-theme.d.ts +2 -4
- package/dist/components/UXThemeSwitch/use-theme.js +65 -50
- package/dist/components/UXToast/index.d.ts +7 -4
- package/dist/components/UXToast/index.js +21 -17
- package/dist/components/UXTooltip/tooltip.extend.d.ts +19 -19
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -0
- package/package.json +6 -7
- package/tailwind-preset.js +162 -63
- package/dist/components/UXThemeSwitch/theme-data.d.ts +0 -29
- package/dist/components/UXThemeSwitch/theme-data.js +0 -304
|
@@ -40,7 +40,7 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
|
|
|
40
40
|
vocab?: string | undefined;
|
|
41
41
|
autoCorrect?: string | undefined;
|
|
42
42
|
autoSave?: string | undefined;
|
|
43
|
-
color?: "default" | "
|
|
43
|
+
color?: "default" | "success" | "secondary" | "primary" | "danger" | "warning" | undefined;
|
|
44
44
|
itemProp?: string | undefined;
|
|
45
45
|
itemScope?: boolean | undefined;
|
|
46
46
|
itemType?: string | undefined;
|
|
@@ -288,32 +288,32 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
|
|
|
288
288
|
layout?: "auto" | "fixed" | undefined;
|
|
289
289
|
border?: number | undefined;
|
|
290
290
|
key?: import("react").Key | null | undefined;
|
|
291
|
+
classNames?: import("@heroui/theme").SlotsToClasses<"table" | "base" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "wrapper" | "sortIcon" | "emptyWrapper" | "loadingWrapper"> | undefined;
|
|
291
292
|
disableAnimation?: boolean | undefined;
|
|
292
|
-
shadow?: "sm" | "md" | "lg" | "none" | undefined;
|
|
293
293
|
summary?: string | undefined;
|
|
294
294
|
as?: import("@heroui/system-rsc").As<any> | undefined;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
rules?: "none" | "all" | "rows" | "groups" | "columns" | undefined;
|
|
300
|
-
classNames?: import("@heroui/theme").SlotsToClasses<"table" | "base" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "wrapper" | "sortIcon" | "emptyWrapper" | "loadingWrapper"> | undefined;
|
|
301
|
-
topContent?: import("react").ReactNode;
|
|
302
|
-
bottomContent?: import("react").ReactNode;
|
|
295
|
+
baseRef?: import("@heroui/react-utils").ReactRef<HTMLElement | null> | undefined;
|
|
296
|
+
disallowEmptySelection?: boolean | undefined;
|
|
297
|
+
onSelectionChange?: ((keys: import("@react-types/shared").Selection) => void) | undefined;
|
|
298
|
+
disabledKeys?: Iterable<import("@react-types/shared").Key> | undefined;
|
|
303
299
|
scrollRef?: import("@react-types/shared").RefObject<HTMLElement | null> | undefined;
|
|
304
300
|
isVirtualized?: boolean | undefined;
|
|
301
|
+
shadow?: "sm" | "md" | "lg" | "none" | undefined;
|
|
302
|
+
topContent?: import("react").ReactNode;
|
|
303
|
+
bottomContent?: import("react").ReactNode;
|
|
304
|
+
keyboardDelegate?: import("@react-types/shared").KeyboardDelegate | undefined;
|
|
305
|
+
selectionBehavior?: "replace" | "toggle" | undefined;
|
|
306
|
+
shouldSelectOnPressUp?: boolean | undefined;
|
|
305
307
|
escapeKeyBehavior?: "none" | "clearSelection" | undefined;
|
|
306
|
-
disabledKeys?: Iterable<import("@react-types/shared").Key> | undefined;
|
|
307
308
|
selectionMode?: import("@react-types/shared").SelectionMode | undefined;
|
|
308
|
-
disallowEmptySelection?: boolean | undefined;
|
|
309
309
|
selectedKeys?: "all" | Iterable<import("@react-types/shared").Key> | undefined;
|
|
310
310
|
defaultSelectedKeys?: "all" | Iterable<import("@react-types/shared").Key> | undefined;
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
bgcolor?: string | undefined;
|
|
312
|
+
cellPadding?: string | number | undefined;
|
|
313
|
+
cellSpacing?: string | number | undefined;
|
|
314
|
+
frame?: boolean | undefined;
|
|
315
|
+
rules?: "none" | "all" | "rows" | "groups" | "columns" | undefined;
|
|
313
316
|
isCompact?: boolean | undefined;
|
|
314
|
-
keyboardDelegate?: import("@react-types/shared").KeyboardDelegate | undefined;
|
|
315
|
-
selectionBehavior?: "replace" | "toggle" | undefined;
|
|
316
|
-
shouldSelectOnPressUp?: boolean | undefined;
|
|
317
317
|
hideHeader?: boolean | undefined;
|
|
318
318
|
isStriped?: boolean | undefined;
|
|
319
319
|
isHeaderSticky?: boolean | undefined;
|
|
@@ -3,7 +3,7 @@ const tabsClasses = {
|
|
|
3
3
|
variants: {
|
|
4
4
|
variant: {
|
|
5
5
|
solid: {
|
|
6
|
-
tabList: 'gap-0 bg-background-
|
|
6
|
+
tabList: 'gap-0 bg-background-200',
|
|
7
7
|
tab: 'py-0 !outline-none',
|
|
8
8
|
cursor: 'shadow-none inset-0',
|
|
9
9
|
tabContent: 'text-foreground-300 font-medium'
|
|
@@ -252,9 +252,9 @@ const tabsClasses = {
|
|
|
252
252
|
color: 'default',
|
|
253
253
|
class: {
|
|
254
254
|
cursor: [
|
|
255
|
-
'bg-
|
|
255
|
+
'!bg-tertiary'
|
|
256
256
|
],
|
|
257
|
-
tabContent: 'group-data-[selected=true]:text-
|
|
257
|
+
tabContent: 'group-data-[selected=true]:text-tertiary-foreground'
|
|
258
258
|
}
|
|
259
259
|
},
|
|
260
260
|
{
|
|
@@ -264,9 +264,9 @@ const tabsClasses = {
|
|
|
264
264
|
color: 'default',
|
|
265
265
|
class: {
|
|
266
266
|
cursor: [
|
|
267
|
-
'bg-
|
|
267
|
+
'!bg-tertiary'
|
|
268
268
|
],
|
|
269
|
-
tabContent: 'group-data-[selected=true]:text-
|
|
269
|
+
tabContent: 'group-data-[selected=true]:text-tertiary-foreground'
|
|
270
270
|
}
|
|
271
271
|
},
|
|
272
272
|
{
|
|
@@ -276,9 +276,9 @@ const tabsClasses = {
|
|
|
276
276
|
color: 'default',
|
|
277
277
|
class: {
|
|
278
278
|
cursor: [
|
|
279
|
-
'bg-
|
|
279
|
+
'!bg-tertiary'
|
|
280
280
|
],
|
|
281
|
-
tabContent: 'group-data-[selected=true]:text-
|
|
281
|
+
tabContent: 'group-data-[selected=true]:text-tertiary-foreground'
|
|
282
282
|
}
|
|
283
283
|
},
|
|
284
284
|
{
|
|
@@ -8,15 +8,16 @@ const ThemeItem = ({ id, zhName, enName, isSelected, onClick })=>{
|
|
|
8
8
|
const lang = useLang();
|
|
9
9
|
return /*#__PURE__*/ jsxs(VStack, {
|
|
10
10
|
center: true,
|
|
11
|
-
|
|
11
|
+
gap: 2,
|
|
12
|
+
className: cn('cursor-pointer', id),
|
|
12
13
|
onClick: onClick,
|
|
13
14
|
children: [
|
|
14
15
|
/*#__PURE__*/ jsx("div", {
|
|
15
|
-
className: cn('rounded-
|
|
16
|
+
className: cn('rounded-medium border-2 hover:scale-105 transition-all duration-300', isSelected ? 'border-primary' : 'border-transparent'),
|
|
16
17
|
children: /*#__PURE__*/ jsxs("svg", {
|
|
17
18
|
xmlns: "http://www.w3.org/2000/svg",
|
|
18
|
-
width: "
|
|
19
|
-
height: "
|
|
19
|
+
width: "120",
|
|
20
|
+
height: "71",
|
|
20
21
|
viewBox: "0 0 120 71",
|
|
21
22
|
fill: "none",
|
|
22
23
|
children: [
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import "react";
|
|
3
|
-
import { Drawer, DrawerBody, DrawerContent, DrawerFooter, DrawerHeader } from "@heroui/drawer";
|
|
4
3
|
import { useDisclosure } from "@heroui/use-disclosure";
|
|
5
|
-
import {
|
|
4
|
+
import { ChartColorSwitchIcon } from "@particle-network/icons/web";
|
|
5
|
+
import { themeData } from "@particle-network/ui-shared";
|
|
6
6
|
import { useI18n } from "../../hooks/index.js";
|
|
7
|
-
import {
|
|
7
|
+
import { HStack, VStack } from "../layout/index.js";
|
|
8
8
|
import { Text } from "../typography/Text.js";
|
|
9
9
|
import { UXButton } from "../UXButton/index.js";
|
|
10
10
|
import { UXDivider } from "../UXDivider/index.js";
|
|
11
|
+
import { UXDrawer } from "../UXDrawer/index.js";
|
|
11
12
|
import { UXInput } from "../UXInput/index.js";
|
|
12
13
|
import { UXSpinner } from "../UXSpinner/index.js";
|
|
13
|
-
import { themeData } from "./theme-data.js";
|
|
14
14
|
import { ThemeItem } from "./theme-item.js";
|
|
15
15
|
import { useTheme } from "./use-theme.js";
|
|
16
16
|
const UXThemeSwitchDrawer = ({ isOpen, onClose, onOpenChange, ...props })=>{
|
|
17
17
|
const i18n = useI18n();
|
|
18
|
-
const { selectedTheme, setSelectedTheme, savedTheme, setSavedTheme, selectedFontLink, setSelectedFontLink, savedFontLink, setSavedFontLink, fontName, fontLoadStatus
|
|
18
|
+
const { selectedTheme, setSelectedTheme, savedTheme, setSavedTheme, selectedFontLink, setSelectedFontLink, savedFontLink, setSavedFontLink, fontName, fontLoadStatus } = useTheme();
|
|
19
19
|
const handleOpenChange = (_isOpen)=>{
|
|
20
20
|
onOpenChange?.(_isOpen);
|
|
21
21
|
if (!_isOpen) {
|
|
@@ -32,96 +32,82 @@ const UXThemeSwitchDrawer = ({ isOpen, onClose, onOpenChange, ...props })=>{
|
|
|
32
32
|
setSelectedTheme(savedTheme);
|
|
33
33
|
setSelectedFontLink(savedFontLink);
|
|
34
34
|
};
|
|
35
|
-
return /*#__PURE__*/
|
|
35
|
+
return /*#__PURE__*/ jsxs(UXDrawer, {
|
|
36
36
|
isOpen: isOpen,
|
|
37
37
|
backdrop: "transparent",
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
title: i18n.theme.title,
|
|
39
|
+
footer: /*#__PURE__*/ jsxs(HStack, {
|
|
40
|
+
fullWidth: true,
|
|
41
|
+
gap: "lg",
|
|
41
42
|
children: [
|
|
42
|
-
/*#__PURE__*/ jsx(
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
/*#__PURE__*/ jsx(UXButton, {
|
|
44
|
+
fullWidth: true,
|
|
45
|
+
size: "lg",
|
|
46
|
+
onPress: handleReset,
|
|
47
|
+
children: i18n.theme.reset
|
|
45
48
|
}),
|
|
46
|
-
/*#__PURE__*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
/*#__PURE__*/ jsx(UXButton, {
|
|
50
|
+
fullWidth: true,
|
|
51
|
+
isDisabled: 'error' === fontLoadStatus,
|
|
52
|
+
size: "lg",
|
|
53
|
+
color: "primary",
|
|
54
|
+
onPress: handleApplyTheme,
|
|
55
|
+
children: i18n.theme.apply
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
}),
|
|
59
|
+
onOpenChange: handleOpenChange,
|
|
60
|
+
...props,
|
|
61
|
+
children: [
|
|
62
|
+
/*#__PURE__*/ jsx("div", {
|
|
63
|
+
className: "grid grid-cols-3 gap-y-5",
|
|
64
|
+
children: themeData.map((theme)=>/*#__PURE__*/ jsx(ThemeItem, {
|
|
65
|
+
isSelected: selectedTheme.id === theme.id,
|
|
66
|
+
onClick: ()=>setSelectedTheme(theme),
|
|
67
|
+
...theme
|
|
68
|
+
}, theme.id))
|
|
69
|
+
}),
|
|
70
|
+
/*#__PURE__*/ jsx(UXDivider, {
|
|
71
|
+
className: "my-lg"
|
|
72
|
+
}),
|
|
73
|
+
/*#__PURE__*/ jsxs(VStack, {
|
|
74
|
+
gap: "md",
|
|
75
|
+
children: [
|
|
76
|
+
/*#__PURE__*/ jsx(Text, {
|
|
77
|
+
body1Bold: true,
|
|
78
|
+
children: i18n.theme.font.title
|
|
79
|
+
}),
|
|
80
|
+
/*#__PURE__*/ jsx(UXInput, {
|
|
81
|
+
isClearable: true,
|
|
82
|
+
startContent: 'loading' === fontLoadStatus && /*#__PURE__*/ jsx(UXSpinner, {
|
|
83
|
+
size: 18
|
|
60
84
|
}),
|
|
61
|
-
|
|
62
|
-
|
|
85
|
+
isInvalid: 'error' === fontLoadStatus,
|
|
86
|
+
className: "w-full",
|
|
87
|
+
placeholder: i18n.theme.font.placeholder,
|
|
88
|
+
value: selectedFontLink,
|
|
89
|
+
description: /*#__PURE__*/ jsxs(Fragment, {
|
|
63
90
|
children: [
|
|
64
|
-
/*#__PURE__*/
|
|
65
|
-
|
|
66
|
-
|
|
91
|
+
'success' === fontLoadStatus && /*#__PURE__*/ jsxs(Text, {
|
|
92
|
+
body3Bold: true,
|
|
93
|
+
color: "success",
|
|
94
|
+
children: [
|
|
95
|
+
i18n.theme.font.success,
|
|
96
|
+
fontName
|
|
97
|
+
]
|
|
67
98
|
}),
|
|
68
|
-
/*#__PURE__*/ jsx(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}),
|
|
73
|
-
isInvalid: 'error' === fontLoadStatus,
|
|
74
|
-
className: "w-full",
|
|
75
|
-
placeholder: i18n.theme.font.placeholder,
|
|
76
|
-
value: selectedFontLink,
|
|
77
|
-
description: /*#__PURE__*/ jsxs(Fragment, {
|
|
78
|
-
children: [
|
|
79
|
-
'success' === fontLoadStatus && /*#__PURE__*/ jsxs(Text, {
|
|
80
|
-
body3Bold: true,
|
|
81
|
-
color: "success",
|
|
82
|
-
children: [
|
|
83
|
-
i18n.theme.font.success,
|
|
84
|
-
fontName
|
|
85
|
-
]
|
|
86
|
-
}),
|
|
87
|
-
'error' === fontLoadStatus && fontLoadError && /*#__PURE__*/ jsx(Text, {
|
|
88
|
-
body3Bold: true,
|
|
89
|
-
color: "danger",
|
|
90
|
-
children: fontLoadError
|
|
91
|
-
})
|
|
92
|
-
]
|
|
93
|
-
}),
|
|
94
|
-
onValueChange: setSelectedFontLink
|
|
99
|
+
'error' === fontLoadStatus && /*#__PURE__*/ jsx(Text, {
|
|
100
|
+
body3Bold: true,
|
|
101
|
+
color: "danger",
|
|
102
|
+
children: i18n.theme.font.error
|
|
95
103
|
})
|
|
96
104
|
]
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
}),
|
|
100
|
-
/*#__PURE__*/ jsx(DrawerFooter, {
|
|
101
|
-
className: "mb-8",
|
|
102
|
-
children: /*#__PURE__*/ jsxs(HStack, {
|
|
103
|
-
fullWidth: true,
|
|
104
|
-
gap: "lg",
|
|
105
|
-
children: [
|
|
106
|
-
/*#__PURE__*/ jsx(UXButton, {
|
|
107
|
-
fullWidth: true,
|
|
108
|
-
size: "lg",
|
|
109
|
-
onPress: handleReset,
|
|
110
|
-
children: i18n.theme.reset
|
|
111
|
-
}),
|
|
112
|
-
/*#__PURE__*/ jsx(UXButton, {
|
|
113
|
-
fullWidth: true,
|
|
114
|
-
isDisabled: 'error' === fontLoadStatus,
|
|
115
|
-
size: "lg",
|
|
116
|
-
color: "primary",
|
|
117
|
-
onPress: handleApplyTheme,
|
|
118
|
-
children: i18n.theme.apply
|
|
119
|
-
})
|
|
120
|
-
]
|
|
105
|
+
}),
|
|
106
|
+
onValueChange: setSelectedFontLink
|
|
121
107
|
})
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
108
|
+
]
|
|
109
|
+
})
|
|
110
|
+
]
|
|
125
111
|
});
|
|
126
112
|
};
|
|
127
113
|
const UXThemeSwitch = ({ children })=>{
|
|
@@ -132,7 +118,7 @@ const UXThemeSwitch = ({ children })=>{
|
|
|
132
118
|
isIconOnly: true,
|
|
133
119
|
variant: "light",
|
|
134
120
|
onPress: onOpen,
|
|
135
|
-
children: /*#__PURE__*/ jsx(
|
|
121
|
+
children: /*#__PURE__*/ jsx(ChartColorSwitchIcon, {})
|
|
136
122
|
});
|
|
137
123
|
};
|
|
138
124
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
@@ -1,19 +1 @@
|
|
|
1
|
-
export declare const useThemeColor: () =>
|
|
2
|
-
foreground: string;
|
|
3
|
-
secondary: string;
|
|
4
|
-
tertiary: string;
|
|
5
|
-
primary: string;
|
|
6
|
-
success: string;
|
|
7
|
-
danger: string;
|
|
8
|
-
alert: string;
|
|
9
|
-
warning: string;
|
|
10
|
-
gold: string;
|
|
11
|
-
background: string;
|
|
12
|
-
'background-200': string;
|
|
13
|
-
'background-300': string;
|
|
14
|
-
'background-400': string;
|
|
15
|
-
overlay: string;
|
|
16
|
-
divider: string;
|
|
17
|
-
bullish: string;
|
|
18
|
-
bearish: string;
|
|
19
|
-
};
|
|
1
|
+
export declare const useThemeColor: () => Record<import("@particle-network/ui-shared").UXColor, string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ThemeItemType } from '
|
|
1
|
+
import { type ThemeItemType } from '@particle-network/ui-shared';
|
|
2
2
|
export type FontLoadStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
3
3
|
interface State {
|
|
4
4
|
/**
|
|
@@ -25,10 +25,6 @@ interface State {
|
|
|
25
25
|
* 字体加载状态
|
|
26
26
|
*/
|
|
27
27
|
fontLoadStatus: FontLoadStatus;
|
|
28
|
-
/**
|
|
29
|
-
* 字体加载错误信息
|
|
30
|
-
*/
|
|
31
|
-
fontLoadError: string | null;
|
|
32
28
|
}
|
|
33
29
|
interface Actions {
|
|
34
30
|
setSelectedTheme: (theme: ThemeItemType) => void;
|
|
@@ -36,7 +32,6 @@ interface Actions {
|
|
|
36
32
|
setSelectedFontLink: (link: string) => void;
|
|
37
33
|
setSavedFontLink: (link: string) => void;
|
|
38
34
|
setFontLoadStatus: (status: FontLoadStatus) => void;
|
|
39
|
-
setFontLoadError: (error: string | null) => void;
|
|
40
35
|
setFontName: (name: string) => void;
|
|
41
36
|
}
|
|
42
37
|
type ThemeStore = State & Actions;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { themeData } from "@particle-network/ui-shared";
|
|
1
2
|
import { create } from "zustand";
|
|
2
3
|
import { createJSONStorage, persist } from "zustand/middleware";
|
|
3
|
-
import { themeData } from "./theme-data.js";
|
|
4
4
|
const useThemeStore = create()(persist((set)=>({
|
|
5
5
|
selectedTheme: themeData["0"],
|
|
6
6
|
savedTheme: themeData["0"],
|
|
@@ -8,7 +8,6 @@ const useThemeStore = create()(persist((set)=>({
|
|
|
8
8
|
savedFontLink: '',
|
|
9
9
|
fontName: '',
|
|
10
10
|
fontLoadStatus: 'idle',
|
|
11
|
-
fontLoadError: null,
|
|
12
11
|
setSelectedTheme: (theme)=>set({
|
|
13
12
|
selectedTheme: theme
|
|
14
13
|
}),
|
|
@@ -24,14 +23,11 @@ const useThemeStore = create()(persist((set)=>({
|
|
|
24
23
|
setFontLoadStatus: (status)=>set({
|
|
25
24
|
fontLoadStatus: status
|
|
26
25
|
}),
|
|
27
|
-
setFontLoadError: (error)=>set({
|
|
28
|
-
fontLoadError: error
|
|
29
|
-
}),
|
|
30
26
|
setFontName: (name)=>set({
|
|
31
27
|
fontName: name
|
|
32
28
|
})
|
|
33
29
|
}), {
|
|
34
|
-
name: 'ux-theme',
|
|
30
|
+
name: 'ux-theme-1',
|
|
35
31
|
storage: createJSONStorage(()=>'undefined' != typeof window ? window.localStorage : {}),
|
|
36
32
|
partialize: (state)=>({
|
|
37
33
|
selectedTheme: state.selectedTheme,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { type ThemeItemType } from '
|
|
2
|
-
import { type FontLoadStatus } from './use-theme-store';
|
|
1
|
+
import { type ThemeItemType } from '@particle-network/ui-shared';
|
|
3
2
|
/**
|
|
4
3
|
* UX 主题管理 Hook
|
|
5
4
|
*/
|
|
@@ -12,7 +11,6 @@ export declare const useTheme: () => {
|
|
|
12
11
|
setSelectedFontLink: (link: string) => void;
|
|
13
12
|
savedFontLink: string;
|
|
14
13
|
setSavedFontLink: (link: string) => void;
|
|
15
|
-
fontLoadStatus: FontLoadStatus;
|
|
16
|
-
fontLoadError: string | null;
|
|
14
|
+
fontLoadStatus: import("./use-theme-store").FontLoadStatus;
|
|
17
15
|
fontName: string;
|
|
18
16
|
};
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
|
+
import { themeKeys } from "@particle-network/ui-shared";
|
|
2
3
|
import { useDebounceFn } from "ahooks";
|
|
3
|
-
import { themeKeys } from "./theme-data.js";
|
|
4
4
|
import { useThemeStore } from "./use-theme-store.js";
|
|
5
|
-
const DEFAULT_FONT_FAMILY = '
|
|
5
|
+
const DEFAULT_FONT_FAMILY = 'Inter,system-ui,sans-serif,"Microsoft YaHei"';
|
|
6
|
+
const PRELOAD_FONTS_URL = 'https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=IBM+Plex+Sans:ital,wght@0,100..700;1,100..700&display=swap';
|
|
7
|
+
const preloadFonts = ()=>{
|
|
8
|
+
if ('undefined' == typeof window) return;
|
|
9
|
+
const existingLink = document.getElementById('ux-preload-fonts-link');
|
|
10
|
+
if (existingLink) return;
|
|
11
|
+
const linkElement = document.createElement('link');
|
|
12
|
+
linkElement.id = 'ux-preload-fonts-link';
|
|
13
|
+
linkElement.rel = 'stylesheet';
|
|
14
|
+
linkElement.href = PRELOAD_FONTS_URL;
|
|
15
|
+
document.head.appendChild(linkElement);
|
|
16
|
+
};
|
|
6
17
|
const applyTheme = (theme)=>{
|
|
7
18
|
if ('undefined' == typeof window) return;
|
|
8
19
|
const root = document.documentElement;
|
|
@@ -11,6 +22,8 @@ const applyTheme = (theme)=>{
|
|
|
11
22
|
themeKeys.forEach((key)=>{
|
|
12
23
|
root.classList.remove(key);
|
|
13
24
|
});
|
|
25
|
+
root.classList.remove('dark');
|
|
26
|
+
root.classList.remove('light');
|
|
14
27
|
root.classList.add(theme.id);
|
|
15
28
|
};
|
|
16
29
|
const extractFontFamilyFromLink = (link)=>{
|
|
@@ -19,50 +32,21 @@ const extractFontFamilyFromLink = (link)=>{
|
|
|
19
32
|
const url = new URL(link);
|
|
20
33
|
const familyParam = url.searchParams.get('family');
|
|
21
34
|
if (!familyParam) return null;
|
|
22
|
-
const
|
|
23
|
-
return
|
|
35
|
+
const firstFamily = familyParam.split('&family=')[0].split(':')[0].replace(/\+/g, ' ');
|
|
36
|
+
return firstFamily;
|
|
24
37
|
} catch {
|
|
25
38
|
return null;
|
|
26
39
|
}
|
|
27
40
|
};
|
|
28
|
-
const
|
|
29
|
-
const { setFontLoadStatus, setFontLoadError, setFontName } = options;
|
|
41
|
+
const applyFont = (fontName)=>{
|
|
30
42
|
if ('undefined' == typeof window) return;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
if (fontName) {
|
|
44
|
+
document.documentElement.style.setProperty('--ux-font-family', `"${fontName}", ${DEFAULT_FONT_FAMILY}`);
|
|
45
|
+
document.body.style.fontFamily = `"${fontName}", ${DEFAULT_FONT_FAMILY}`;
|
|
46
|
+
} else {
|
|
34
47
|
document.documentElement.style.setProperty('--ux-font-family', DEFAULT_FONT_FAMILY);
|
|
35
48
|
document.body.style.fontFamily = DEFAULT_FONT_FAMILY;
|
|
36
|
-
setFontLoadStatus('idle');
|
|
37
|
-
setFontLoadError(null);
|
|
38
|
-
setFontName('');
|
|
39
|
-
return;
|
|
40
49
|
}
|
|
41
|
-
setFontLoadStatus('loading');
|
|
42
|
-
setFontLoadError(null);
|
|
43
|
-
const linkElement = document.createElement('link');
|
|
44
|
-
linkElement.id = 'ux-google-font-link';
|
|
45
|
-
linkElement.rel = 'stylesheet';
|
|
46
|
-
linkElement.href = link;
|
|
47
|
-
linkElement.onload = ()=>{
|
|
48
|
-
setFontLoadStatus('success');
|
|
49
|
-
setFontLoadError(null);
|
|
50
|
-
const fontFamily = extractFontFamilyFromLink(link);
|
|
51
|
-
if (fontFamily) {
|
|
52
|
-
document.documentElement.style.setProperty('--ux-font-family', `"${fontFamily}", ${DEFAULT_FONT_FAMILY}`);
|
|
53
|
-
document.body.style.fontFamily = `"${fontFamily}", ${DEFAULT_FONT_FAMILY}`;
|
|
54
|
-
setFontName(fontFamily);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
linkElement.onerror = ()=>{
|
|
58
|
-
const errorMessage = '字体加载失败,请检查链接是否正确';
|
|
59
|
-
setFontLoadStatus('error');
|
|
60
|
-
setFontLoadError(errorMessage);
|
|
61
|
-
setFontName('');
|
|
62
|
-
document.documentElement.style.setProperty('--ux-font-family', DEFAULT_FONT_FAMILY);
|
|
63
|
-
document.body.style.fontFamily = DEFAULT_FONT_FAMILY;
|
|
64
|
-
};
|
|
65
|
-
document.head.appendChild(linkElement);
|
|
66
50
|
};
|
|
67
51
|
const useTheme = ()=>{
|
|
68
52
|
const selectedTheme = useThemeStore((state)=>state.selectedTheme);
|
|
@@ -71,24 +55,55 @@ const useTheme = ()=>{
|
|
|
71
55
|
const savedFontLink = useThemeStore((state)=>state.savedFontLink);
|
|
72
56
|
const fontName = useThemeStore((state)=>state.fontName);
|
|
73
57
|
const fontLoadStatus = useThemeStore((state)=>state.fontLoadStatus);
|
|
74
|
-
const fontLoadError = useThemeStore((state)=>state.fontLoadError);
|
|
75
58
|
const storeSetSelectedTheme = useThemeStore((state)=>state.setSelectedTheme);
|
|
76
59
|
const storeSetSavedTheme = useThemeStore((state)=>state.setSavedTheme);
|
|
77
60
|
const storeSetSelectedFontLink = useThemeStore((state)=>state.setSelectedFontLink);
|
|
78
61
|
const storeSetSavedFontLink = useThemeStore((state)=>state.setSavedFontLink);
|
|
79
62
|
const storeSetFontLoadStatus = useThemeStore((state)=>state.setFontLoadStatus);
|
|
80
|
-
const storeSetFontLoadError = useThemeStore((state)=>state.setFontLoadError);
|
|
81
63
|
const storeSetFontName = useThemeStore((state)=>state.setFontName);
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
64
|
+
const applyFontWithStatus = (customFontLink, themeFontName)=>{
|
|
65
|
+
if ('undefined' == typeof window) return;
|
|
66
|
+
const isCustomFont = !!customFontLink?.trim();
|
|
67
|
+
if (!isCustomFont) return void applyFont(themeFontName);
|
|
68
|
+
const existingLink = document.getElementById('ux-google-font-link');
|
|
69
|
+
if (existingLink) existingLink.remove();
|
|
70
|
+
storeSetFontLoadStatus('loading');
|
|
71
|
+
const linkElement = document.createElement('link');
|
|
72
|
+
linkElement.id = 'ux-google-font-link';
|
|
73
|
+
linkElement.rel = 'stylesheet';
|
|
74
|
+
linkElement.href = customFontLink;
|
|
75
|
+
linkElement.onload = ()=>{
|
|
76
|
+
storeSetFontLoadStatus('success');
|
|
77
|
+
const fontFamily = extractFontFamilyFromLink(customFontLink);
|
|
78
|
+
if (fontFamily) {
|
|
79
|
+
applyFont(fontFamily);
|
|
80
|
+
storeSetFontName(fontFamily);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
linkElement.onerror = ()=>{
|
|
84
|
+
storeSetFontLoadStatus('error');
|
|
85
|
+
storeSetFontName('');
|
|
86
|
+
applyFont(themeFontName);
|
|
87
|
+
};
|
|
88
|
+
document.head.appendChild(linkElement);
|
|
89
|
+
};
|
|
90
|
+
const { run: debouncedApplyFont } = useDebounceFn((customFontLink, themeFontName)=>applyFontWithStatus(customFontLink, themeFontName), {
|
|
91
|
+
wait: 300
|
|
88
92
|
});
|
|
93
|
+
useEffect(()=>{
|
|
94
|
+
preloadFonts();
|
|
95
|
+
}, []);
|
|
96
|
+
useEffect(()=>{
|
|
97
|
+
if (!selectedFontLink.trim()) {
|
|
98
|
+
storeSetFontLoadStatus('idle');
|
|
99
|
+
storeSetFontName('');
|
|
100
|
+
}
|
|
101
|
+
}, [
|
|
102
|
+
selectedFontLink
|
|
103
|
+
]);
|
|
89
104
|
useEffect(()=>{
|
|
90
105
|
applyTheme(savedTheme);
|
|
91
|
-
|
|
106
|
+
debouncedApplyFont(savedFontLink, savedTheme.fontName);
|
|
92
107
|
}, [
|
|
93
108
|
savedTheme,
|
|
94
109
|
savedFontLink
|
|
@@ -96,6 +111,7 @@ const useTheme = ()=>{
|
|
|
96
111
|
const setSelectedTheme = (theme)=>{
|
|
97
112
|
storeSetSelectedTheme(theme);
|
|
98
113
|
applyTheme(theme);
|
|
114
|
+
debouncedApplyFont(selectedFontLink, theme.fontName);
|
|
99
115
|
};
|
|
100
116
|
const setSavedTheme = (theme)=>{
|
|
101
117
|
storeSetSavedTheme(theme);
|
|
@@ -103,11 +119,11 @@ const useTheme = ()=>{
|
|
|
103
119
|
};
|
|
104
120
|
const setSelectedFontLink = (link)=>{
|
|
105
121
|
storeSetSelectedFontLink(link);
|
|
106
|
-
|
|
122
|
+
debouncedApplyFont(link, selectedTheme.fontName);
|
|
107
123
|
};
|
|
108
124
|
const setSavedFontLink = (link)=>{
|
|
109
125
|
storeSetSavedFontLink(link);
|
|
110
|
-
|
|
126
|
+
debouncedApplyFont(link, savedTheme.fontName);
|
|
111
127
|
};
|
|
112
128
|
return {
|
|
113
129
|
selectedTheme,
|
|
@@ -119,7 +135,6 @@ const useTheme = ()=>{
|
|
|
119
135
|
savedFontLink,
|
|
120
136
|
setSavedFontLink,
|
|
121
137
|
fontLoadStatus,
|
|
122
|
-
fontLoadError,
|
|
123
138
|
fontName
|
|
124
139
|
};
|
|
125
140
|
};
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
import type { ToastProps } from '@heroui/toast';
|
|
2
|
-
export
|
|
3
|
+
export { addToast, closeAll, closeToast, getToastQueue, isToastClosing } from '@heroui/toast';
|
|
4
|
+
export type UXToastType = 'success' | 'error' | 'loading' | 'info';
|
|
3
5
|
export type UXToastProps = Partial<ToastProps> & {
|
|
4
6
|
type: UXToastType;
|
|
5
7
|
};
|
|
6
8
|
export declare const UXToastProvider: () => import("react/jsx-runtime").JSX.Element;
|
|
7
9
|
export declare const toast: {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
info: (message: ReactNode, props?: Partial<ToastProps>) => string | null;
|
|
11
|
+
success: (message: ReactNode, props?: Partial<ToastProps>) => string | null;
|
|
12
|
+
error: (message: ReactNode, props?: Partial<ToastProps>) => string | null;
|
|
13
|
+
loading: (message: ReactNode, props?: Partial<ToastProps>) => string | null;
|
|
11
14
|
show: (props?: Partial<ToastProps> & {
|
|
12
15
|
type: UXToastType;
|
|
13
16
|
}) => string | null;
|