@particle-network/ui-react 0.4.0-beta.18 → 0.4.0-beta.19

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.
@@ -1,15 +1,28 @@
1
1
  declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
2
- fullWidth?: boolean | undefined;
2
+ className?: string | undefined;
3
+ size?: "md" | "lg" | undefined;
4
+ color?: "default" | "success" | "primary" | "secondary" | "warning" | "danger" | undefined;
5
+ radius?: "none" | "sm" | "md" | "lg" | undefined;
6
+ disableAnimation?: boolean | undefined;
7
+ shadow?: "none" | "sm" | "md" | "lg" | undefined;
8
+ "aria-label"?: string | undefined;
9
+ "aria-labelledby"?: string | undefined;
10
+ "aria-describedby"?: string | undefined;
11
+ "aria-details"?: string | undefined;
12
+ slot?: any;
13
+ style?: import("react").CSSProperties | undefined;
14
+ summary?: string | undefined;
15
+ title?: string | undefined;
3
16
  ref?: import("@heroui/react-utils").ReactRef<HTMLElement | null> | undefined;
4
- children?: ((string | number | bigint | boolean | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | import("react").ReactPortal | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | null) & [import("react").ReactElement<import("@react-types/table").TableHeaderProps<object>, string | import("react").JSXElementConstructor<any>>, import("react").ReactElement<import("@react-types/table").TableBodyProps<object>, string | import("react").JSXElementConstructor<any>>]) | undefined;
5
17
  defaultChecked?: any;
6
18
  defaultValue?: any;
19
+ as?: import("@heroui/system-rsc").As<any> | undefined;
20
+ key?: import("react").Key | null | undefined;
7
21
  suppressContentEditableWarning?: boolean | undefined;
8
22
  suppressHydrationWarning?: boolean | undefined;
9
23
  accessKey?: string | undefined;
10
24
  autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | (string & {}) | undefined;
11
25
  autoFocus?: boolean | undefined;
12
- className?: string | undefined;
13
26
  contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
14
27
  contextMenu?: string | undefined;
15
28
  dir?: string | undefined;
@@ -19,11 +32,8 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
19
32
  id?: string | undefined;
20
33
  lang?: string | undefined;
21
34
  nonce?: string | undefined;
22
- slot?: any;
23
35
  spellCheck?: (boolean | "true" | "false") | undefined;
24
- style?: import("react").CSSProperties | undefined;
25
36
  tabIndex?: number | undefined;
26
- title?: string | undefined;
27
37
  translate?: "yes" | "no" | undefined;
28
38
  radioGroup?: string | undefined;
29
39
  role?: import("react").AriaRole | undefined;
@@ -40,7 +50,6 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
40
50
  vocab?: string | undefined;
41
51
  autoCorrect?: string | undefined;
42
52
  autoSave?: string | undefined;
43
- color?: "default" | "success" | "secondary" | "primary" | "danger" | "warning" | undefined;
44
53
  itemProp?: string | undefined;
45
54
  itemScope?: boolean | undefined;
46
55
  itemType?: string | undefined;
@@ -53,7 +62,7 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
53
62
  popoverTargetAction?: "toggle" | "show" | "hide" | undefined;
54
63
  popoverTarget?: string | undefined;
55
64
  inert?: boolean | undefined;
56
- inputMode?: "search" | "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | undefined;
65
+ inputMode?: "search" | "text" | "none" | "tel" | "url" | "email" | "numeric" | "decimal" | undefined;
57
66
  is?: string | undefined;
58
67
  exportparts?: string | undefined;
59
68
  part?: string | undefined;
@@ -69,28 +78,24 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
69
78
  "aria-colindextext"?: string | undefined;
70
79
  "aria-colspan"?: number | undefined;
71
80
  "aria-controls"?: string | undefined;
72
- "aria-current"?: boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time" | undefined;
73
- "aria-describedby"?: string | undefined;
81
+ "aria-current"?: boolean | "time" | "true" | "false" | "page" | "step" | "location" | "date" | undefined;
74
82
  "aria-description"?: string | undefined;
75
- "aria-details"?: string | undefined;
76
83
  "aria-disabled"?: (boolean | "true" | "false") | undefined;
77
84
  "aria-dropeffect"?: "link" | "none" | "copy" | "execute" | "move" | "popup" | undefined;
78
85
  "aria-errormessage"?: string | undefined;
79
86
  "aria-expanded"?: (boolean | "true" | "false") | undefined;
80
87
  "aria-flowto"?: string | undefined;
81
88
  "aria-grabbed"?: (boolean | "true" | "false") | undefined;
82
- "aria-haspopup"?: boolean | "true" | "false" | "dialog" | "grid" | "listbox" | "menu" | "tree" | undefined;
89
+ "aria-haspopup"?: boolean | "dialog" | "menu" | "true" | "false" | "grid" | "listbox" | "tree" | undefined;
83
90
  "aria-hidden"?: (boolean | "true" | "false") | undefined;
84
91
  "aria-invalid"?: boolean | "true" | "false" | "grammar" | "spelling" | undefined;
85
92
  "aria-keyshortcuts"?: string | undefined;
86
- "aria-label"?: string | undefined;
87
- "aria-labelledby"?: string | undefined;
88
93
  "aria-level"?: number | undefined;
89
94
  "aria-live"?: "off" | "assertive" | "polite" | undefined;
90
95
  "aria-modal"?: (boolean | "true" | "false") | undefined;
91
96
  "aria-multiline"?: (boolean | "true" | "false") | undefined;
92
97
  "aria-multiselectable"?: (boolean | "true" | "false") | undefined;
93
- "aria-orientation"?: "vertical" | "horizontal" | undefined;
98
+ "aria-orientation"?: "horizontal" | "vertical" | undefined;
94
99
  "aria-owns"?: string | undefined;
95
100
  "aria-placeholder"?: string | undefined;
96
101
  "aria-posinset"?: number | undefined;
@@ -110,6 +115,7 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
110
115
  "aria-valuemin"?: number | undefined;
111
116
  "aria-valuenow"?: number | undefined;
112
117
  "aria-valuetext"?: string | undefined;
118
+ children?: ((string | number | bigint | boolean | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | import("react").ReactPortal | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | null) & [import("react").ReactElement<import("@react-types/table").TableHeaderProps<object>, string | import("react").JSXElementConstructor<any>>, import("react").ReactElement<import("@react-types/table").TableBodyProps<object>, string | import("react").JSXElementConstructor<any>>]) | undefined;
113
119
  dangerouslySetInnerHTML?: {
114
120
  __html: string | TrustedHTML;
115
121
  } | undefined;
@@ -281,28 +287,22 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
281
287
  onTransitionRunCapture?: import("react").TransitionEventHandler<HTMLTableElement> | undefined;
282
288
  onTransitionStart?: import("react").TransitionEventHandler<HTMLTableElement> | undefined;
283
289
  onTransitionStartCapture?: import("react").TransitionEventHandler<HTMLTableElement> | undefined;
284
- align?: "start" | "end" | "center" | undefined;
285
- size?: "md" | "lg" | undefined;
286
- width?: string | number | undefined;
287
- radius?: "sm" | "md" | "lg" | "none" | undefined;
290
+ classNames?: import("@heroui/theme").SlotsToClasses<"base" | "table" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "wrapper" | "sortIcon" | "emptyWrapper" | "loadingWrapper"> | undefined;
291
+ align?: "center" | "start" | "end" | undefined;
292
+ fullWidth?: boolean | undefined;
288
293
  layout?: "auto" | "fixed" | undefined;
289
- border?: number | undefined;
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;
292
- disableAnimation?: boolean | undefined;
293
- summary?: string | undefined;
294
- as?: import("@heroui/system-rsc").As<any> | undefined;
294
+ width?: string | number | undefined;
295
295
  baseRef?: import("@heroui/react-utils").ReactRef<HTMLElement | null> | undefined;
296
+ scrollRef?: import("@react-types/shared").RefObject<HTMLElement | null> | undefined;
297
+ border?: number | undefined;
296
298
  disallowEmptySelection?: boolean | undefined;
297
299
  onSelectionChange?: ((keys: import("@react-types/shared").Selection) => void) | undefined;
298
300
  disabledKeys?: Iterable<import("@react-types/shared").Key> | undefined;
299
- scrollRef?: import("@react-types/shared").RefObject<HTMLElement | null> | undefined;
300
301
  isVirtualized?: boolean | undefined;
301
- shadow?: "sm" | "md" | "lg" | "none" | undefined;
302
302
  topContent?: import("react").ReactNode;
303
303
  bottomContent?: import("react").ReactNode;
304
304
  keyboardDelegate?: import("@react-types/shared").KeyboardDelegate | undefined;
305
- selectionBehavior?: "replace" | "toggle" | undefined;
305
+ selectionBehavior?: "toggle" | "replace" | undefined;
306
306
  shouldSelectOnPressUp?: boolean | undefined;
307
307
  escapeKeyBehavior?: "none" | "clearSelection" | undefined;
308
308
  selectionMode?: import("@react-types/shared").SelectionMode | undefined;
@@ -321,7 +321,7 @@ declare const ExtendedTable: import("react").ForwardRefExoticComponent<Omit<{
321
321
  isMultiSelectable?: boolean | undefined;
322
322
  layoutDelegate?: import("@react-types/shared").LayoutDelegate | undefined;
323
323
  disallowTypeAhead?: boolean | undefined;
324
- focusMode?: "row" | "cell" | undefined;
324
+ focusMode?: "cell" | "row" | undefined;
325
325
  getRowText?: ((key: import("@react-types/shared").Key) => string) | undefined;
326
326
  onRowAction?: (((key: import("react").Key) => void) & ((key: import("@react-types/shared").Key) => void)) | undefined;
327
327
  onCellAction?: (((key: import("react").Key) => void) & ((key: import("@react-types/shared").Key) => void)) | undefined;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import ExtendedTabs from './tabs.extend';
3
3
  export type UXTabsProps = React.ComponentPropsWithRef<typeof ExtendedTabs>;
4
- export declare const UXTabs: React.ForwardRefExoticComponent<Omit<Omit<import("@heroui/tabs").TabsProps, "color" | "variant"> & {
4
+ export declare const UXTabs: React.ForwardRefExoticComponent<Omit<Omit<import("@heroui/tabs").TabsProps, "variant" | "color"> & {
5
5
  variant?: "solid" | "light" | "text" | "switch";
6
6
  color?: "default" | "primary" | "success" | "warning" | "danger" | "bullish" | "bearish";
7
7
  }, "ref"> & React.RefAttributes<HTMLDivElement>>;
@@ -9,15 +9,15 @@ const ThemeItem = ({ id, zhName, enName, isSelected, onClick })=>{
9
9
  return /*#__PURE__*/ jsxs(VStack, {
10
10
  center: true,
11
11
  gap: 2,
12
- className: cn('cursor-pointer hover:scale-105 transition-all duration-300', id),
12
+ className: cn('cursor-pointer', id),
13
13
  onClick: onClick,
14
14
  children: [
15
15
  /*#__PURE__*/ jsx("div", {
16
- className: cn('rounded-medium border-2', isSelected ? 'border-primary' : 'border-transparent'),
16
+ className: cn('rounded-medium border-2 hover:scale-105 transition-all duration-300', isSelected ? 'border-primary' : 'border-transparent'),
17
17
  children: /*#__PURE__*/ jsxs("svg", {
18
18
  xmlns: "http://www.w3.org/2000/svg",
19
- width: "180",
20
- height: "106.5",
19
+ width: "120",
20
+ height: "71",
21
21
  viewBox: "0 0 120 71",
22
22
  fill: "none",
23
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
4
  import { ChartColorSwitchIcon } from "@particle-network/icons/web";
6
5
  import { themeData } from "@particle-network/ui-shared";
7
6
  import { useI18n } from "../../hooks/index.js";
8
- import { Flex, HStack, VStack } from "../layout/index.js";
7
+ import { HStack, VStack } from "../layout/index.js";
9
8
  import { Text } from "../typography/Text.js";
10
9
  import { UXButton } from "../UXButton/index.js";
11
10
  import { UXDivider } from "../UXDivider/index.js";
11
+ import { UXDrawer } from "../UXDrawer/index.js";
12
12
  import { UXInput } from "../UXInput/index.js";
13
13
  import { UXSpinner } from "../UXSpinner/index.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, fontLoadError } = useTheme();
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__*/ jsx(Drawer, {
35
+ return /*#__PURE__*/ jsxs(UXDrawer, {
36
36
  isOpen: isOpen,
37
37
  backdrop: "transparent",
38
- onOpenChange: handleOpenChange,
39
- ...props,
40
- children: /*#__PURE__*/ jsxs(DrawerContent, {
38
+ title: i18n.theme.title,
39
+ footer: /*#__PURE__*/ jsxs(HStack, {
40
+ fullWidth: true,
41
+ gap: "lg",
41
42
  children: [
42
- /*#__PURE__*/ jsx(DrawerHeader, {
43
- className: "flex flex-col gap-1",
44
- children: i18n.theme.title
43
+ /*#__PURE__*/ jsx(UXButton, {
44
+ fullWidth: true,
45
+ size: "lg",
46
+ onPress: handleReset,
47
+ children: i18n.theme.reset
45
48
  }),
46
- /*#__PURE__*/ jsxs(DrawerBody, {
47
- children: [
48
- /*#__PURE__*/ jsx(Flex, {
49
- wrap: true,
50
- justify: "between",
51
- className: "gap-y-5",
52
- children: themeData.map((theme)=>/*#__PURE__*/ jsx(ThemeItem, {
53
- isSelected: selectedTheme.id === theme.id,
54
- onClick: ()=>setSelectedTheme(theme),
55
- ...theme
56
- }, theme.id))
57
- }),
58
- /*#__PURE__*/ jsx(UXDivider, {
59
- className: "my-lg"
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
- /*#__PURE__*/ jsxs(VStack, {
62
- gap: "md",
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__*/ jsx(Text, {
65
- body1Bold: true,
66
- children: i18n.theme.font.title
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(UXInput, {
69
- isClearable: true,
70
- startContent: 'loading' === fontLoadStatus && /*#__PURE__*/ jsx(UXSpinner, {
71
- size: 18
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 })=>{
@@ -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;
@@ -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
1
  import { type ThemeItemType } from '@particle-network/ui-shared';
2
- import { type FontLoadStatus } from './use-theme-store';
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
  };
@@ -2,7 +2,18 @@ import { useEffect } from "react";
2
2
  import { themeKeys } from "@particle-network/ui-shared";
3
3
  import { useDebounceFn } from "ahooks";
4
4
  import { useThemeStore } from "./use-theme-store.js";
5
- 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 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;
@@ -21,50 +32,21 @@ const extractFontFamilyFromLink = (link)=>{
21
32
  const url = new URL(link);
22
33
  const familyParam = url.searchParams.get('family');
23
34
  if (!familyParam) return null;
24
- const fontName = familyParam.split(':')[0].replace(/\+/g, ' ');
25
- return fontName;
35
+ const firstFamily = familyParam.split('&family=')[0].split(':')[0].replace(/\+/g, ' ');
36
+ return firstFamily;
26
37
  } catch {
27
38
  return null;
28
39
  }
29
40
  };
30
- const loadGoogleFont = (link, options)=>{
31
- const { setFontLoadStatus, setFontLoadError, setFontName } = options;
41
+ const applyFont = (fontName)=>{
32
42
  if ('undefined' == typeof window) return;
33
- const existingLink = document.getElementById('ux-google-font-link');
34
- if (existingLink) existingLink.remove();
35
- if (!link?.trim()) {
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 {
36
47
  document.documentElement.style.setProperty('--ux-font-family', DEFAULT_FONT_FAMILY);
37
48
  document.body.style.fontFamily = DEFAULT_FONT_FAMILY;
38
- setFontLoadStatus('idle');
39
- setFontLoadError(null);
40
- setFontName('');
41
- return;
42
49
  }
43
- setFontLoadStatus('loading');
44
- setFontLoadError(null);
45
- const linkElement = document.createElement('link');
46
- linkElement.id = 'ux-google-font-link';
47
- linkElement.rel = 'stylesheet';
48
- linkElement.href = link;
49
- linkElement.onload = ()=>{
50
- setFontLoadStatus('success');
51
- setFontLoadError(null);
52
- const fontFamily = extractFontFamilyFromLink(link);
53
- if (fontFamily) {
54
- document.documentElement.style.setProperty('--ux-font-family', `"${fontFamily}", ${DEFAULT_FONT_FAMILY}`);
55
- document.body.style.fontFamily = `"${fontFamily}", ${DEFAULT_FONT_FAMILY}`;
56
- setFontName(fontFamily);
57
- }
58
- };
59
- linkElement.onerror = ()=>{
60
- const errorMessage = '字体加载失败,请检查链接是否正确';
61
- setFontLoadStatus('error');
62
- setFontLoadError(errorMessage);
63
- setFontName('');
64
- document.documentElement.style.setProperty('--ux-font-family', DEFAULT_FONT_FAMILY);
65
- document.body.style.fontFamily = DEFAULT_FONT_FAMILY;
66
- };
67
- document.head.appendChild(linkElement);
68
50
  };
69
51
  const useTheme = ()=>{
70
52
  const selectedTheme = useThemeStore((state)=>state.selectedTheme);
@@ -73,24 +55,55 @@ const useTheme = ()=>{
73
55
  const savedFontLink = useThemeStore((state)=>state.savedFontLink);
74
56
  const fontName = useThemeStore((state)=>state.fontName);
75
57
  const fontLoadStatus = useThemeStore((state)=>state.fontLoadStatus);
76
- const fontLoadError = useThemeStore((state)=>state.fontLoadError);
77
58
  const storeSetSelectedTheme = useThemeStore((state)=>state.setSelectedTheme);
78
59
  const storeSetSavedTheme = useThemeStore((state)=>state.setSavedTheme);
79
60
  const storeSetSelectedFontLink = useThemeStore((state)=>state.setSelectedFontLink);
80
61
  const storeSetSavedFontLink = useThemeStore((state)=>state.setSavedFontLink);
81
62
  const storeSetFontLoadStatus = useThemeStore((state)=>state.setFontLoadStatus);
82
- const storeSetFontLoadError = useThemeStore((state)=>state.setFontLoadError);
83
63
  const storeSetFontName = useThemeStore((state)=>state.setFontName);
84
- const { run: debouncedLoadGoogleFont } = useDebounceFn((link)=>loadGoogleFont(link, {
85
- setFontLoadStatus: storeSetFontLoadStatus,
86
- setFontLoadError: storeSetFontLoadError,
87
- setFontName: storeSetFontName
88
- }), {
89
- wait: 500
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
90
92
  });
93
+ useEffect(()=>{
94
+ preloadFonts();
95
+ }, []);
96
+ useEffect(()=>{
97
+ if (!selectedFontLink.trim()) {
98
+ storeSetFontLoadStatus('idle');
99
+ storeSetFontName('');
100
+ }
101
+ }, [
102
+ selectedFontLink
103
+ ]);
91
104
  useEffect(()=>{
92
105
  applyTheme(savedTheme);
93
- debouncedLoadGoogleFont(savedFontLink);
106
+ debouncedApplyFont(savedFontLink, savedTheme.fontName);
94
107
  }, [
95
108
  savedTheme,
96
109
  savedFontLink
@@ -98,6 +111,7 @@ const useTheme = ()=>{
98
111
  const setSelectedTheme = (theme)=>{
99
112
  storeSetSelectedTheme(theme);
100
113
  applyTheme(theme);
114
+ debouncedApplyFont(selectedFontLink, theme.fontName);
101
115
  };
102
116
  const setSavedTheme = (theme)=>{
103
117
  storeSetSavedTheme(theme);
@@ -105,11 +119,11 @@ const useTheme = ()=>{
105
119
  };
106
120
  const setSelectedFontLink = (link)=>{
107
121
  storeSetSelectedFontLink(link);
108
- debouncedLoadGoogleFont(link);
122
+ debouncedApplyFont(link, selectedTheme.fontName);
109
123
  };
110
124
  const setSavedFontLink = (link)=>{
111
125
  storeSetSavedFontLink(link);
112
- debouncedLoadGoogleFont(link);
126
+ debouncedApplyFont(link, savedTheme.fontName);
113
127
  };
114
128
  return {
115
129
  selectedTheme,
@@ -121,7 +135,6 @@ const useTheme = ()=>{
121
135
  savedFontLink,
122
136
  setSavedFontLink,
123
137
  fontLoadStatus,
124
- fontLoadError,
125
138
  fontName
126
139
  };
127
140
  };
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { ToastProps } from '@heroui/toast';
3
+ export { addToast, closeAll, closeToast, getToastQueue, isToastClosing } from '@heroui/toast';
3
4
  export type UXToastType = 'success' | 'error' | 'loading' | 'info';
4
5
  export type UXToastProps = Partial<ToastProps> & {
5
6
  type: UXToastType;
@@ -1,5 +1,5 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { ToastProvider, addToast, closeAll, closeToast } from "@heroui/toast";
2
+ import { ToastProvider, addToast, closeAll, closeToast, getToastQueue, isToastClosing } from "@heroui/toast";
3
3
  import CircleCheckIcon from "@particle-network/icons/web/CircleCheckIcon";
4
4
  import CircleCloseIcon from "@particle-network/icons/web/CircleCloseIcon";
5
5
  import CloseIcon from "@particle-network/icons/web/CloseIcon";
@@ -106,4 +106,4 @@ const toast = {
106
106
  closeAll: closeAll,
107
107
  close: closeToast
108
108
  };
109
- export { UXToastProvider, toast };
109
+ export { UXToastProvider, addToast, closeAll, closeToast, getToastQueue, isToastClosing, toast };