@particle-network/ui-react 0.3.2 → 0.4.0-beta.0
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/UXEmpty/index.js +1 -1
- package/dist/components/UXInput/index.d.ts +1 -1
- package/dist/components/UXInput/input.extend.d.ts +1 -1
- package/dist/components/UXThemeSwitch/index.d.ts +3 -0
- package/dist/components/UXThemeSwitch/index.js +3 -0
- package/dist/components/UXThemeSwitch/theme-data.d.ts +28 -0
- package/dist/components/UXThemeSwitch/theme-data.js +304 -0
- package/dist/components/UXThemeSwitch/theme-item.d.ts +7 -0
- package/dist/components/UXThemeSwitch/theme-item.js +136 -0
- package/dist/components/UXThemeSwitch/theme-switch.d.ts +5 -0
- package/dist/components/UXThemeSwitch/theme-switch.js +121 -0
- package/dist/components/UXThemeSwitch/use-theme-store.d.ts +40 -0
- package/dist/components/UXThemeSwitch/use-theme-store.js +25 -0
- package/dist/components/UXThemeSwitch/use-theme.d.ts +14 -0
- package/dist/components/UXThemeSwitch/use-theme.js +90 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/hooks/useI18n.d.ts +9 -0
- package/dist/hooks/useI18n.js +18 -0
- package/dist/utils/input-classes.d.ts +0 -32
- package/dist/utils/input-classes.js +5 -23
- package/package.json +4 -3
- package/tailwind-preset.js +804 -44
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ThemeItemType } from './theme-data';
|
|
2
|
+
interface State {
|
|
3
|
+
/**
|
|
4
|
+
* 临时选中的 theme(用于预览)
|
|
5
|
+
*/
|
|
6
|
+
selectedTheme: ThemeItemType;
|
|
7
|
+
/**
|
|
8
|
+
* 保存的主题
|
|
9
|
+
*/
|
|
10
|
+
savedTheme: ThemeItemType;
|
|
11
|
+
/**
|
|
12
|
+
* 临时输入的字体链接(用于预览)
|
|
13
|
+
*/
|
|
14
|
+
selectedFontLink: string;
|
|
15
|
+
/**
|
|
16
|
+
* 保存的字体链接
|
|
17
|
+
*/
|
|
18
|
+
savedFontLink: string;
|
|
19
|
+
}
|
|
20
|
+
interface Actions {
|
|
21
|
+
setSelectedTheme: (theme: ThemeItemType) => void;
|
|
22
|
+
setSavedTheme: (theme: ThemeItemType) => void;
|
|
23
|
+
setSelectedFontLink: (link: string) => void;
|
|
24
|
+
setSavedFontLink: (link: string) => void;
|
|
25
|
+
}
|
|
26
|
+
type ThemeStore = State & Actions;
|
|
27
|
+
export declare const useThemeStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<ThemeStore>, "setState" | "persist"> & {
|
|
28
|
+
setState(partial: ThemeStore | Partial<ThemeStore> | ((state: ThemeStore) => ThemeStore | Partial<ThemeStore>), replace?: false | undefined): unknown;
|
|
29
|
+
setState(state: ThemeStore | ((state: ThemeStore) => ThemeStore), replace: true): unknown;
|
|
30
|
+
persist: {
|
|
31
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ThemeStore, unknown, unknown>>) => void;
|
|
32
|
+
clearStorage: () => void;
|
|
33
|
+
rehydrate: () => Promise<void> | void;
|
|
34
|
+
hasHydrated: () => boolean;
|
|
35
|
+
onHydrate: (fn: (state: ThemeStore) => void) => () => void;
|
|
36
|
+
onFinishHydration: (fn: (state: ThemeStore) => void) => () => void;
|
|
37
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<ThemeStore, unknown, unknown>>;
|
|
38
|
+
};
|
|
39
|
+
}>;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
import { createJSONStorage, persist } from "zustand/middleware";
|
|
3
|
+
import { themeData } from "./theme-data.js";
|
|
4
|
+
const useThemeStore = create()(persist((set)=>({
|
|
5
|
+
selectedTheme: themeData["0"],
|
|
6
|
+
savedTheme: themeData["0"],
|
|
7
|
+
selectedFontLink: '',
|
|
8
|
+
savedFontLink: '',
|
|
9
|
+
setSelectedTheme: (theme)=>set({
|
|
10
|
+
selectedTheme: theme
|
|
11
|
+
}),
|
|
12
|
+
setSavedTheme: (theme)=>set({
|
|
13
|
+
savedTheme: theme
|
|
14
|
+
}),
|
|
15
|
+
setSelectedFontLink: (link)=>set({
|
|
16
|
+
selectedFontLink: link
|
|
17
|
+
}),
|
|
18
|
+
setSavedFontLink: (link)=>set({
|
|
19
|
+
savedFontLink: link
|
|
20
|
+
})
|
|
21
|
+
}), {
|
|
22
|
+
name: 'ux-theme',
|
|
23
|
+
storage: createJSONStorage(()=>'undefined' != typeof window ? window.localStorage : {})
|
|
24
|
+
}));
|
|
25
|
+
export { useThemeStore };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ThemeItemType } from './theme-data';
|
|
2
|
+
/**
|
|
3
|
+
* UX 主题管理 Hook
|
|
4
|
+
*/
|
|
5
|
+
export declare const useTheme: () => {
|
|
6
|
+
selectedTheme: ThemeItemType;
|
|
7
|
+
setSelectedTheme: (theme: ThemeItemType) => void;
|
|
8
|
+
savedTheme: ThemeItemType;
|
|
9
|
+
setSavedTheme: (theme: ThemeItemType) => void;
|
|
10
|
+
selectedFontLink: string;
|
|
11
|
+
setSelectedFontLink: (link: string) => void;
|
|
12
|
+
savedFontLink: string;
|
|
13
|
+
setSavedFontLink: (link: string) => void;
|
|
14
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { themeKeys } from "./theme-data.js";
|
|
3
|
+
import { useThemeStore } from "./use-theme-store.js";
|
|
4
|
+
const DEFAULT_FONT_FAMILY = 'ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji';
|
|
5
|
+
const applyTheme = (theme)=>{
|
|
6
|
+
if ('undefined' == typeof window) return;
|
|
7
|
+
const root = document.documentElement;
|
|
8
|
+
root.setAttribute('data-theme', theme.colorScheme);
|
|
9
|
+
root.setAttribute('data-prefers-color', theme.colorScheme);
|
|
10
|
+
themeKeys.forEach((key)=>{
|
|
11
|
+
root.classList.remove(key);
|
|
12
|
+
});
|
|
13
|
+
root.classList.add(theme.key);
|
|
14
|
+
};
|
|
15
|
+
const extractFontFamilyFromLink = (link)=>{
|
|
16
|
+
if (!link) return null;
|
|
17
|
+
try {
|
|
18
|
+
const url = new URL(link);
|
|
19
|
+
const familyParam = url.searchParams.get('family');
|
|
20
|
+
if (!familyParam) return null;
|
|
21
|
+
const fontName = familyParam.split(':')[0].replace(/\+/g, ' ');
|
|
22
|
+
return fontName;
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const loadGoogleFont = (link)=>{
|
|
28
|
+
if ('undefined' == typeof window) return;
|
|
29
|
+
const existingLink = document.getElementById('ux-google-font-link');
|
|
30
|
+
if (existingLink) existingLink.remove();
|
|
31
|
+
if (!link?.trim()) {
|
|
32
|
+
document.documentElement.style.setProperty('--ux-font-family', DEFAULT_FONT_FAMILY);
|
|
33
|
+
document.body.style.fontFamily = DEFAULT_FONT_FAMILY;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const linkElement = document.createElement('link');
|
|
37
|
+
linkElement.id = 'ux-google-font-link';
|
|
38
|
+
linkElement.rel = 'stylesheet';
|
|
39
|
+
linkElement.href = link;
|
|
40
|
+
document.head.appendChild(linkElement);
|
|
41
|
+
const fontFamily = extractFontFamilyFromLink(link);
|
|
42
|
+
if (fontFamily) {
|
|
43
|
+
document.documentElement.style.setProperty('--ux-font-family', `"${fontFamily}", ${DEFAULT_FONT_FAMILY}`);
|
|
44
|
+
document.body.style.fontFamily = `"${fontFamily}", ${DEFAULT_FONT_FAMILY}`;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const useTheme = ()=>{
|
|
48
|
+
const selectedTheme = useThemeStore((state)=>state.selectedTheme);
|
|
49
|
+
const savedTheme = useThemeStore((state)=>state.savedTheme);
|
|
50
|
+
const selectedFontLink = useThemeStore((state)=>state.selectedFontLink);
|
|
51
|
+
const savedFontLink = useThemeStore((state)=>state.savedFontLink);
|
|
52
|
+
const storeSetSelectedTheme = useThemeStore((state)=>state.setSelectedTheme);
|
|
53
|
+
const storeSetSavedTheme = useThemeStore((state)=>state.setSavedTheme);
|
|
54
|
+
const storeSetSelectedFontLink = useThemeStore((state)=>state.setSelectedFontLink);
|
|
55
|
+
const storeSetSavedFontLink = useThemeStore((state)=>state.setSavedFontLink);
|
|
56
|
+
useEffect(()=>{
|
|
57
|
+
applyTheme(savedTheme);
|
|
58
|
+
loadGoogleFont(savedFontLink);
|
|
59
|
+
}, [
|
|
60
|
+
savedTheme,
|
|
61
|
+
savedFontLink
|
|
62
|
+
]);
|
|
63
|
+
const setSelectedTheme = (theme)=>{
|
|
64
|
+
storeSetSelectedTheme(theme);
|
|
65
|
+
applyTheme(theme);
|
|
66
|
+
};
|
|
67
|
+
const setSavedTheme = (theme)=>{
|
|
68
|
+
storeSetSavedTheme(theme);
|
|
69
|
+
applyTheme(theme);
|
|
70
|
+
};
|
|
71
|
+
const setSelectedFontLink = (link)=>{
|
|
72
|
+
storeSetSelectedFontLink(link);
|
|
73
|
+
loadGoogleFont(link);
|
|
74
|
+
};
|
|
75
|
+
const setSavedFontLink = (link)=>{
|
|
76
|
+
storeSetSavedFontLink(link);
|
|
77
|
+
loadGoogleFont(link);
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
selectedTheme,
|
|
81
|
+
setSelectedTheme,
|
|
82
|
+
savedTheme,
|
|
83
|
+
setSavedTheme,
|
|
84
|
+
selectedFontLink,
|
|
85
|
+
setSelectedFontLink,
|
|
86
|
+
savedFontLink,
|
|
87
|
+
setSavedFontLink
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
export { useTheme };
|
package/dist/components/index.js
CHANGED
|
@@ -24,5 +24,6 @@ export * from "./UXSwitch/index.js";
|
|
|
24
24
|
export * from "./UXTable/index.js";
|
|
25
25
|
export * from "./UXTabs/index.js";
|
|
26
26
|
export * from "./UXTextarea/index.js";
|
|
27
|
+
export * from "./UXThemeSwitch/index.js";
|
|
27
28
|
export * from "./UXToast/index.js";
|
|
28
29
|
export * from "./UXTooltip/index.js";
|
package/dist/hooks/useI18n.d.ts
CHANGED
package/dist/hooks/useI18n.js
CHANGED
|
@@ -8,6 +8,15 @@ const en = {
|
|
|
8
8
|
success: 'Copied successfully!',
|
|
9
9
|
error: 'Copy failed: ',
|
|
10
10
|
address: 'Address copied: '
|
|
11
|
+
},
|
|
12
|
+
theme: {
|
|
13
|
+
title: 'Theme',
|
|
14
|
+
reset: 'Reset',
|
|
15
|
+
apply: 'Apply Theme',
|
|
16
|
+
font: {
|
|
17
|
+
title: 'Custom Font',
|
|
18
|
+
placeholder: 'Enter Google Fonts link'
|
|
19
|
+
}
|
|
11
20
|
}
|
|
12
21
|
};
|
|
13
22
|
const zh = {
|
|
@@ -19,6 +28,15 @@ const zh = {
|
|
|
19
28
|
success: '复制成功!',
|
|
20
29
|
error: '复制失败:',
|
|
21
30
|
address: '地址已复制:'
|
|
31
|
+
},
|
|
32
|
+
theme: {
|
|
33
|
+
title: '主题',
|
|
34
|
+
reset: '重置',
|
|
35
|
+
apply: '应用主题',
|
|
36
|
+
font: {
|
|
37
|
+
title: '自定义字体',
|
|
38
|
+
placeholder: '输入 Google Fonts 链接'
|
|
39
|
+
}
|
|
22
40
|
}
|
|
23
41
|
};
|
|
24
42
|
const useI18n = ()=>{
|
|
@@ -263,38 +263,6 @@ export declare const inputClasses: {
|
|
|
263
263
|
labelPlacement?: undefined;
|
|
264
264
|
radius?: undefined;
|
|
265
265
|
isMultiline?: undefined;
|
|
266
|
-
} | {
|
|
267
|
-
isInvalid: boolean;
|
|
268
|
-
variant: string;
|
|
269
|
-
class: {
|
|
270
|
-
inputWrapper: string[];
|
|
271
|
-
label?: undefined;
|
|
272
|
-
input?: undefined;
|
|
273
|
-
innerWrapper?: undefined;
|
|
274
|
-
stepperButton?: undefined;
|
|
275
|
-
};
|
|
276
|
-
size?: undefined;
|
|
277
|
-
color?: undefined;
|
|
278
|
-
labelPlacement?: undefined;
|
|
279
|
-
radius?: undefined;
|
|
280
|
-
disableAnimation?: undefined;
|
|
281
|
-
isMultiline?: undefined;
|
|
282
|
-
} | {
|
|
283
|
-
isInvalid: boolean;
|
|
284
|
-
variant: string;
|
|
285
|
-
class: {
|
|
286
|
-
inputWrapper: string;
|
|
287
|
-
label?: undefined;
|
|
288
|
-
input?: undefined;
|
|
289
|
-
innerWrapper?: undefined;
|
|
290
|
-
stepperButton?: undefined;
|
|
291
|
-
};
|
|
292
|
-
size?: undefined;
|
|
293
|
-
color?: undefined;
|
|
294
|
-
labelPlacement?: undefined;
|
|
295
|
-
radius?: undefined;
|
|
296
|
-
disableAnimation?: undefined;
|
|
297
|
-
isMultiline?: undefined;
|
|
298
266
|
} | {
|
|
299
267
|
labelPlacement: string;
|
|
300
268
|
size: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const inputClasses = {
|
|
2
2
|
defaultVariants: {
|
|
3
3
|
variant: 'flat',
|
|
4
|
-
color: '
|
|
4
|
+
color: 'default',
|
|
5
5
|
size: 'md',
|
|
6
6
|
fullWidth: true,
|
|
7
7
|
labelPlacement: 'outside',
|
|
@@ -75,19 +75,19 @@ const inputClasses = {
|
|
|
75
75
|
size: {
|
|
76
76
|
sm: {
|
|
77
77
|
label: 'text-tiny text-foreground-300',
|
|
78
|
-
inputWrapper: 'text-tiny h-6 min-h-6 px-2 rounded-small',
|
|
78
|
+
inputWrapper: 'text-tiny h-6 min-h-6 px-2.5 rounded-small',
|
|
79
79
|
input: 'text-tiny',
|
|
80
80
|
clearButton: 'text-medium'
|
|
81
81
|
},
|
|
82
82
|
md: {
|
|
83
83
|
label: 'text-tiny text-foreground-300',
|
|
84
|
-
inputWrapper: 'text-tiny h-[30px] min-h-[30px] rounded-small',
|
|
84
|
+
inputWrapper: 'text-tiny h-[30px] min-h-[30px] rounded-small px-2.5',
|
|
85
85
|
input: 'text-tiny',
|
|
86
86
|
clearButton: 'text-large'
|
|
87
87
|
},
|
|
88
88
|
lg: {
|
|
89
89
|
label: 'text-small text-foreground-300',
|
|
90
|
-
inputWrapper: 'text-small h-11 min-h-11 rounded-medium',
|
|
90
|
+
inputWrapper: 'text-small h-11 min-h-11 rounded-medium px-2.5',
|
|
91
91
|
input: 'text-small',
|
|
92
92
|
clearButton: 'text-large'
|
|
93
93
|
}
|
|
@@ -141,7 +141,7 @@ const inputClasses = {
|
|
|
141
141
|
},
|
|
142
142
|
isInvalid: {
|
|
143
143
|
true: {
|
|
144
|
-
inputWrapper: 'group-data-[focus=true]
|
|
144
|
+
inputWrapper: 'border border-danger caret-danger !bg-background group-data-[focus=true]:!bg-background group-data-[hover=true]:!bg-background',
|
|
145
145
|
label: 'text-danger',
|
|
146
146
|
input: 'placeholder:text-danger text-danger'
|
|
147
147
|
}
|
|
@@ -389,24 +389,6 @@ const inputClasses = {
|
|
|
389
389
|
inputWrapper: 'transition-colors motion-reduce:transition-none'
|
|
390
390
|
}
|
|
391
391
|
},
|
|
392
|
-
{
|
|
393
|
-
isInvalid: true,
|
|
394
|
-
variant: 'flat',
|
|
395
|
-
class: {
|
|
396
|
-
inputWrapper: [
|
|
397
|
-
'!bg-danger-50',
|
|
398
|
-
'data-[hover=true]:!bg-danger-100',
|
|
399
|
-
'group-data-[focus=true]:!bg-danger-50'
|
|
400
|
-
]
|
|
401
|
-
}
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
isInvalid: true,
|
|
405
|
-
variant: 'bordered',
|
|
406
|
-
class: {
|
|
407
|
-
inputWrapper: '!border-danger group-data-[focus=true]:!border-danger'
|
|
408
|
-
}
|
|
409
|
-
},
|
|
410
392
|
{
|
|
411
393
|
labelPlacement: 'inside',
|
|
412
394
|
size: 'sm',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-network/ui-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -49,8 +49,9 @@
|
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"ahooks": "^3.9.4",
|
|
51
51
|
"copy-to-clipboard": "^3.3.3",
|
|
52
|
-
"
|
|
53
|
-
"@particle-network/icons": "0.3.1"
|
|
52
|
+
"zustand": "^5.0.8",
|
|
53
|
+
"@particle-network/icons": "0.3.1",
|
|
54
|
+
"@particle-network/ui-shared": "0.2.0"
|
|
54
55
|
},
|
|
55
56
|
"scripts": {
|
|
56
57
|
"build": "rslib build",
|