@sruim/nexus-design 0.0.1

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 (92) hide show
  1. package/README.md +195 -0
  2. package/dist/assets/grid.webp.js +3 -0
  3. package/dist/components/credits-button/index.d.ts +8 -0
  4. package/dist/components/credits-button/index.js +40 -0
  5. package/dist/components/icon/index.d.ts +7 -0
  6. package/dist/components/icon/index.js +32 -0
  7. package/dist/components/icon-button/index.d.ts +9 -0
  8. package/dist/components/icon-button/index.js +36 -0
  9. package/dist/components/img-uploader/index.d.ts +19 -0
  10. package/dist/components/img-uploader/index.js +107 -0
  11. package/dist/components/img-viewer/index.d.ts +16 -0
  12. package/dist/components/img-viewer/index.js +80 -0
  13. package/dist/components/index.d.ts +9 -0
  14. package/dist/components/loadable/index.d.ts +8 -0
  15. package/dist/components/loadable/index.js +67 -0
  16. package/dist/components/loading/assets/loading.webp.js +3 -0
  17. package/dist/components/loading/index.d.ts +16 -0
  18. package/dist/components/loading/index.js +85 -0
  19. package/dist/components/model-uploader/index.d.ts +17 -0
  20. package/dist/components/model-uploader/index.js +93 -0
  21. package/dist/components/tree/index.d.ts +14 -0
  22. package/dist/components/tree/index.js +50 -0
  23. package/dist/components/tree/node.d.ts +23 -0
  24. package/dist/components/tree/node.js +185 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +43 -0
  27. package/dist/style.css +1193 -0
  28. package/dist/theme.d.ts +2 -0
  29. package/dist/theme.js +96 -0
  30. package/dist/tokens/materials.d.ts +4 -0
  31. package/dist/tokens/materials.js +4 -0
  32. package/dist/tokens/nexus.d.ts +51 -0
  33. package/dist/tokens/nexus.js +42 -0
  34. package/dist/ui/avatar/index.d.ts +11 -0
  35. package/dist/ui/avatar/index.js +55 -0
  36. package/dist/ui/badge/index.d.ts +2 -0
  37. package/dist/ui/badge/index.js +45 -0
  38. package/dist/ui/button.d.ts +8 -0
  39. package/dist/ui/button.js +61 -0
  40. package/dist/ui/carousel/index.d.ts +43 -0
  41. package/dist/ui/carousel/index.js +186 -0
  42. package/dist/ui/checkbox/index.d.ts +4 -0
  43. package/dist/ui/checkbox/index.js +34 -0
  44. package/dist/ui/collapsible/index.d.ts +9 -0
  45. package/dist/ui/collapsible/index.js +7 -0
  46. package/dist/ui/dialog/confirm.d.ts +20 -0
  47. package/dist/ui/dialog/confirm.js +80 -0
  48. package/dist/ui/dialog/dialog.d.ts +26 -0
  49. package/dist/ui/dialog/dialog.js +97 -0
  50. package/dist/ui/dialog/index.d.ts +2 -0
  51. package/dist/ui/drawer.d.ts +22 -0
  52. package/dist/ui/drawer.js +98 -0
  53. package/dist/ui/form.d.ts +33 -0
  54. package/dist/ui/form.js +138 -0
  55. package/dist/ui/index.d.ts +24 -0
  56. package/dist/ui/input-otp.d.ts +14 -0
  57. package/dist/ui/input-otp.js +73 -0
  58. package/dist/ui/label.d.ts +4 -0
  59. package/dist/ui/label.js +32 -0
  60. package/dist/ui/masonry/index.d.ts +13 -0
  61. package/dist/ui/masonry/index.js +45 -0
  62. package/dist/ui/popover/index.d.ts +15 -0
  63. package/dist/ui/popover/index.js +78 -0
  64. package/dist/ui/progress.d.ts +6 -0
  65. package/dist/ui/progress.js +48 -0
  66. package/dist/ui/select/index.d.ts +21 -0
  67. package/dist/ui/select/index.js +127 -0
  68. package/dist/ui/slider/index.d.ts +9 -0
  69. package/dist/ui/slider/index.js +87 -0
  70. package/dist/ui/snap-input.d.ts +7 -0
  71. package/dist/ui/snap-input.js +38 -0
  72. package/dist/ui/sonner.d.ts +5 -0
  73. package/dist/ui/sonner.js +50 -0
  74. package/dist/ui/switch.d.ts +4 -0
  75. package/dist/ui/switch.js +33 -0
  76. package/dist/ui/table/index.d.ts +22 -0
  77. package/dist/ui/table/index.js +70 -0
  78. package/dist/ui/tabs/index.d.ts +12 -0
  79. package/dist/ui/tabs/index.js +60 -0
  80. package/dist/ui/toggle/index.d.ts +2 -0
  81. package/dist/ui/toggle/toggle-group.d.ts +9 -0
  82. package/dist/ui/toggle/toggle-group.js +54 -0
  83. package/dist/ui/toggle/toggle.d.ts +11 -0
  84. package/dist/ui/toggle/toggle.js +45 -0
  85. package/dist/ui/tooltip/index.d.ts +17 -0
  86. package/dist/ui/tooltip/index.js +68 -0
  87. package/dist/utils/config.d.ts +2 -0
  88. package/dist/utils/config.js +48 -0
  89. package/dist/utils/index.d.ts +2 -0
  90. package/dist/utils/utils.d.ts +8 -0
  91. package/dist/utils/utils.js +91 -0
  92. package/package.json +148 -0
package/README.md ADDED
@@ -0,0 +1,195 @@
1
+ # Nexus Design System
2
+
3
+ A modern React component library built with Radix UI primitives and UnoCSS.
4
+
5
+ [中文文档](./README_CN.md) | [API Reference](./docs/api-reference.md)
6
+
7
+ ## Features
8
+
9
+ - **Radix UI Primitives** - Accessible, unstyled components as foundation
10
+ - **UnoCSS Styling** - Atomic CSS with custom theme tokens
11
+ - **TypeScript** - Full type safety with strict mode
12
+ - **Dark Theme** - Obsidian-based dark mode design
13
+ - **Glass Effects** - Frosted glass materials (FrostGlass, DeepGlass)
14
+ - **Compound Components** - Flexible composition patterns
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pnpm add @sruim/nexus-design
20
+ ```
21
+
22
+ **Peer Dependencies:**
23
+
24
+ ```bash
25
+ pnpm add react react-dom
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ### 1. Configure UnoCSS
31
+
32
+ ```typescript
33
+ // uno.config.ts
34
+ import { theme } from '@sruim/nexus-design/theme';
35
+ import { defineConfig, presetUno } from 'unocss';
36
+
37
+ export default defineConfig({
38
+ presets: [presetUno()],
39
+ theme,
40
+ });
41
+ ```
42
+
43
+ ### 2. Import Styles
44
+
45
+ ```typescript
46
+ // main.tsx
47
+ import '@sruim/nexus-design/style.css';
48
+ ```
49
+
50
+ ### 3. Setup Dialoger
51
+
52
+ Required for imperative dialog APIs (`Dialog.show`, `Confirm.show`):
53
+
54
+ ```tsx
55
+ import { Dialoger } from '@sruim/nexus-design/ui';
56
+
57
+ function App() {
58
+ return (
59
+ <>
60
+ <YourApp />
61
+ <Dialoger />
62
+ </>
63
+ );
64
+ }
65
+ ```
66
+
67
+ ### 4. Use Components
68
+
69
+ ```tsx
70
+ import { Button, Dialog, Select } from '@sruim/nexus-design/ui';
71
+ import { IconButton } from '@sruim/nexus-design/components';
72
+
73
+ function Example() {
74
+ return (
75
+ <div>
76
+ <Button variant="solid">Click Me</Button>
77
+ <IconButton icon="i-nexus:download" text="Download" />
78
+ </div>
79
+ );
80
+ }
81
+ ```
82
+
83
+ ## Import Paths
84
+
85
+ | Path | Description |
86
+ |------|-------------|
87
+ | `@sruim/nexus-design` | All exports |
88
+ | `@sruim/nexus-design/ui` | UI primitives (Button, Dialog, Select...) |
89
+ | `@sruim/nexus-design/components` | Composite components (Icon, IconButton...) |
90
+ | `@sruim/nexus-design/utils` | Utilities (cn, sleep, copy...) |
91
+ | `@sruim/nexus-design/theme` | UnoCSS theme configuration |
92
+ | `@sruim/nexus-design/style.css` | Global styles |
93
+
94
+ ## Components
95
+
96
+ ### UI Primitives
97
+
98
+ | Component | Description |
99
+ |-----------|-------------|
100
+ | `Button` | Primary button with solid/hollow/plain variants |
101
+ | `Dialog` | Modal dialog with imperative API |
102
+ | `Confirm` | Confirmation dialog |
103
+ | `Select` | Dropdown select |
104
+ | `Tabs` | Tab navigation |
105
+ | `Popover` | Floating popover |
106
+ | `Tooltip` | Hover tooltip |
107
+ | `Checkbox` | Checkbox input |
108
+ | `Switch` | Toggle switch |
109
+ | `Slider` | Range slider with optional input |
110
+ | `Progress` | Progress bar |
111
+ | `Toggle` | Toggle button |
112
+ | `ToggleGroup` | Toggle button group |
113
+ | `Avatar` | User avatar |
114
+ | `Badge` | Notification badge |
115
+ | `Drawer` | Bottom sheet drawer |
116
+ | `Form` | Form with Zod validation |
117
+
118
+ ### Composite Components
119
+
120
+ | Component | Description |
121
+ |-----------|-------------|
122
+ | `Icon` | UnoCSS icon wrapper |
123
+ | `IconButton` | Button with icon |
124
+ | `ImgUploader` | Image upload component |
125
+ | `ImgViewer` | Image viewer |
126
+ | `ModelUploader` | 3D model upload |
127
+ | `Tree` | Tree view |
128
+ | `Loading` | Loading indicator |
129
+ | `Loadable` | Async content wrapper |
130
+
131
+ ## Theme Tokens
132
+
133
+ ### Colors
134
+
135
+ ```tsx
136
+ // Dark backgrounds
137
+ bg-obsidian-100 // #020617
138
+ bg-obsidian-200 // #0F172A
139
+ bg-obsidian-300 // #1E293B
140
+
141
+ // Primary accent
142
+ bg-core-blue // #3B82F6
143
+
144
+ // Status
145
+ text-status-error // #F43F5E
146
+ text-status-success // #10B981
147
+ text-status-warning // #F59E0B
148
+
149
+ // Text
150
+ text-text-primary // #FFFFFF
151
+ text-text-secondary // #CBD5E1
152
+ text-text-disabled // #64748B
153
+ ```
154
+
155
+ ### Glass Materials
156
+
157
+ ```tsx
158
+ import { FrostGlass, DeepGlass } from '@sruim/nexus-design/tokens/materials';
159
+
160
+ // FrostGlass: backdrop-blur-12 bg-slate-900/70 border border-white/10
161
+ // DeepGlass: backdrop-blur-12 bg-slate-950/90
162
+ ```
163
+
164
+ ## Development
165
+
166
+ ```bash
167
+ # Install dependencies
168
+ pnpm install
169
+
170
+ # Start Storybook
171
+ pnpm storybook
172
+
173
+ # Build library
174
+ pnpm build
175
+
176
+ # Type check
177
+ pnpm typecheck
178
+
179
+ # Lint
180
+ pnpm lint
181
+ ```
182
+
183
+ ## Tech Stack
184
+
185
+ - React 19
186
+ - TypeScript 5.8
187
+ - Radix UI
188
+ - UnoCSS
189
+ - Vite
190
+ - Storybook
191
+ - Zod + React Hook Form
192
+
193
+ ## License
194
+
195
+ MIT
@@ -0,0 +1,3 @@
1
+ const grid = "data:image/webp;base64,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";
2
+
3
+ export { grid as default };
@@ -0,0 +1,8 @@
1
+ import { Button } from '../../ui';
2
+ interface Props extends Omit<React.ComponentProps<typeof Button>, 'children'> {
3
+ count?: number;
4
+ text?: string;
5
+ children?: React.ReactNode;
6
+ }
7
+ export declare const CreditsButton: React.FC<Props>;
8
+ export {};
@@ -0,0 +1,40 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import '@radix-ui/react-portal';
3
+ import '../../ui/avatar/index.js';
4
+ import '../../utils/config.js';
5
+ import { Button } from '../../ui/button.js';
6
+ import '../../ui/carousel/index.js';
7
+ import '../../ui/checkbox/index.js';
8
+ import '../../ui/collapsible/index.js';
9
+ import '../../ui/dialog/confirm.js';
10
+ import '../../ui/dialog/dialog.js';
11
+ import '../../ui/drawer.js';
12
+ import '../../ui/form.js';
13
+ import '../../ui/input-otp.js';
14
+ import '../../ui/label.js';
15
+ import 'react';
16
+ import '../../ui/popover/index.js';
17
+ import '../../ui/progress.js';
18
+ import '../../ui/select/index.js';
19
+ import '../../ui/slider/index.js';
20
+ import '../../ui/sonner.js';
21
+ import '../../ui/switch.js';
22
+ import '../../ui/table/index.js';
23
+ import '../../ui/tabs/index.js';
24
+ import '../../ui/toggle/toggle.js';
25
+ import '../../ui/toggle/toggle-group.js';
26
+ import '../../ui/tooltip/index.js';
27
+ import { Icon } from '../icon/index.js';
28
+
29
+ const CreditsButton = (props) => {
30
+ return /* @__PURE__ */ jsxs(Button, { variant: "solid", size: "large", ...props, children: [
31
+ props.children,
32
+ props.text,
33
+ props.count ? /* @__PURE__ */ jsxs("div", { className: "flex items-center pl-1.5", children: [
34
+ /* @__PURE__ */ jsx(Icon, { className: "size-5", icon: "i-nexus-bolt-monotone" }),
35
+ /* @__PURE__ */ jsx("span", { className: "pl-1.5", children: props.count })
36
+ ] }) : null
37
+ ] });
38
+ };
39
+
40
+ export { CreditsButton };
@@ -0,0 +1,7 @@
1
+ import { default as React } from 'react';
2
+ interface Props extends React.HTMLAttributes<HTMLDivElement> {
3
+ icon: string;
4
+ className?: string;
5
+ }
6
+ export declare const Icon: React.FC<Props>;
7
+ export {};
@@ -0,0 +1,32 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { cn } from '../../utils/config.js';
3
+ import '@radix-ui/react-portal';
4
+ import '../../ui/avatar/index.js';
5
+ import '../../ui/button.js';
6
+ import '../../ui/carousel/index.js';
7
+ import '../../ui/checkbox/index.js';
8
+ import '../../ui/collapsible/index.js';
9
+ import '../../ui/dialog/confirm.js';
10
+ import '../../ui/dialog/dialog.js';
11
+ import '../../ui/drawer.js';
12
+ import '../../ui/form.js';
13
+ import '../../ui/input-otp.js';
14
+ import '../../ui/label.js';
15
+ import 'react';
16
+ import '../../ui/popover/index.js';
17
+ import '../../ui/progress.js';
18
+ import '../../ui/select/index.js';
19
+ import '../../ui/slider/index.js';
20
+ import '../../ui/sonner.js';
21
+ import '../../ui/switch.js';
22
+ import '../../ui/table/index.js';
23
+ import '../../ui/tabs/index.js';
24
+ import '../../ui/toggle/toggle.js';
25
+ import '../../ui/toggle/toggle-group.js';
26
+ import '../../ui/tooltip/index.js';
27
+
28
+ const Icon = ({ icon, className, ...props }) => {
29
+ return /* @__PURE__ */ jsx("div", { className: cn(icon, "v-mid", className), ...props });
30
+ };
31
+
32
+ export { Icon };
@@ -0,0 +1,9 @@
1
+ import { Button } from '../../ui';
2
+ import { default as React } from 'react';
3
+ interface Props extends Omit<React.ComponentProps<typeof Button>, 'children'> {
4
+ icon?: string;
5
+ iconClassName?: string;
6
+ text?: string;
7
+ }
8
+ export declare const IconButton: React.FC<Props>;
9
+ export {};
@@ -0,0 +1,36 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import '@radix-ui/react-portal';
3
+ import '../../ui/avatar/index.js';
4
+ import { cn } from '../../utils/config.js';
5
+ import { Button } from '../../ui/button.js';
6
+ import '../../ui/carousel/index.js';
7
+ import '../../ui/checkbox/index.js';
8
+ import '../../ui/collapsible/index.js';
9
+ import '../../ui/dialog/confirm.js';
10
+ import '../../ui/dialog/dialog.js';
11
+ import '../../ui/drawer.js';
12
+ import '../../ui/form.js';
13
+ import '../../ui/input-otp.js';
14
+ import '../../ui/label.js';
15
+ import 'react';
16
+ import '../../ui/popover/index.js';
17
+ import '../../ui/progress.js';
18
+ import '../../ui/select/index.js';
19
+ import '../../ui/slider/index.js';
20
+ import '../../ui/sonner.js';
21
+ import '../../ui/switch.js';
22
+ import '../../ui/table/index.js';
23
+ import '../../ui/tabs/index.js';
24
+ import '../../ui/toggle/toggle.js';
25
+ import '../../ui/toggle/toggle-group.js';
26
+ import '../../ui/tooltip/index.js';
27
+ import { Icon } from '../icon/index.js';
28
+
29
+ const IconButton = ({ icon, text, iconClassName, ...props }) => {
30
+ return /* @__PURE__ */ jsxs(Button, { variant: "solid", size: "large", ...props, children: [
31
+ icon && /* @__PURE__ */ jsx(Icon, { className: cn("mr-1 size-5", iconClassName), icon }),
32
+ text
33
+ ] });
34
+ };
35
+
36
+ export { IconButton };
@@ -0,0 +1,19 @@
1
+ import { default as React } from 'react';
2
+ interface InputProps {
3
+ onChange: (file: File | File[]) => void;
4
+ multiple?: boolean;
5
+ }
6
+ interface Props {
7
+ className?: string;
8
+ icon?: string;
9
+ title?: string;
10
+ description?: string;
11
+ required?: boolean;
12
+ onChange: (file: File | File[]) => void;
13
+ multiple?: boolean;
14
+ }
15
+ interface IImgUploader extends React.FC<Props> {
16
+ Input: React.FC<InputProps>;
17
+ }
18
+ export declare const ImgUploader: IImgUploader;
19
+ export {};
@@ -0,0 +1,107 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { FrostGlass } from '../../tokens/materials.js';
3
+ import '@radix-ui/react-portal';
4
+ import '../../ui/avatar/index.js';
5
+ import { cn } from '../../utils/config.js';
6
+ import { checkSize, checkType } from '../../utils/utils.js';
7
+ import '../../ui/button.js';
8
+ import '../../ui/carousel/index.js';
9
+ import '../../ui/checkbox/index.js';
10
+ import '../../ui/collapsible/index.js';
11
+ import '../../ui/dialog/confirm.js';
12
+ import '../../ui/dialog/dialog.js';
13
+ import '../../ui/drawer.js';
14
+ import '../../ui/form.js';
15
+ import '../../ui/input-otp.js';
16
+ import '../../ui/label.js';
17
+ import { useState, useCallback } from 'react';
18
+ import '../../ui/popover/index.js';
19
+ import '../../ui/progress.js';
20
+ import '../../ui/select/index.js';
21
+ import '../../ui/slider/index.js';
22
+ import '../../ui/sonner.js';
23
+ import '../../ui/switch.js';
24
+ import '../../ui/table/index.js';
25
+ import '../../ui/tabs/index.js';
26
+ import '../../ui/toggle/toggle.js';
27
+ import '../../ui/toggle/toggle-group.js';
28
+ import '../../ui/tooltip/index.js';
29
+ import grid from '../../assets/grid.webp.js';
30
+ import { Icon } from '../icon/index.js';
31
+ import { toast } from 'sonner';
32
+
33
+ const Input = ({ onChange, multiple = false }) => {
34
+ const handleChange = (e) => {
35
+ const image = e.target.files?.[0];
36
+ if (!image) return;
37
+ if (!checkSize(image, 5)) {
38
+ toast.error("The uploaded file size cannot exceed 5 MB");
39
+ return;
40
+ }
41
+ if (!checkType(image, "image")) {
42
+ toast.error("This file type is not supported.");
43
+ return;
44
+ }
45
+ onChange(multiple ? Array.from(e.target.files || []) : image);
46
+ e.target.value = "";
47
+ };
48
+ return /* @__PURE__ */ jsx(
49
+ "input",
50
+ {
51
+ className: "absolute inset-0 cursor-pointer opacity-0",
52
+ type: "file",
53
+ max: 10,
54
+ multiple,
55
+ accept: "image/png,image/webp,image/jpg,image/jpeg",
56
+ onChange: handleChange
57
+ }
58
+ );
59
+ };
60
+ const BaseStyle = "relative size-full flex flex-col items-center justify-center overflow-hidden transition-colors duration-fast ease-smooth hover:bg-surface-hover";
61
+ const BorderStyle = "box-border border border-dashed border-white/20";
62
+ const DragOverStyle = cn("bg-core-blue/10 w-full hover:bg-core-blue/10", FrostGlass);
63
+ const ImgUploader = ({
64
+ className,
65
+ icon,
66
+ title,
67
+ description,
68
+ required,
69
+ onChange,
70
+ multiple
71
+ }) => {
72
+ const [isDragOver, setIsDragOver] = useState(false);
73
+ const handleDragEnter = useCallback(() => setIsDragOver(true), []);
74
+ const handleDragLeave = useCallback(() => setIsDragOver(false), []);
75
+ return /* @__PURE__ */ jsxs(
76
+ "div",
77
+ {
78
+ className: cn(BaseStyle, BorderStyle, className, isDragOver && DragOverStyle),
79
+ onDragOver: handleDragEnter,
80
+ onDragLeave: handleDragLeave,
81
+ onDrop: handleDragLeave,
82
+ children: [
83
+ icon && /* @__PURE__ */ jsx(Icon, { className: "size-5", icon }),
84
+ title && /* @__PURE__ */ jsx("div", { className: "my-1.5 max-w-2/3 w-37.5 text-center text-wrap text-2.5 text-text-primary", children: title }),
85
+ description && /* @__PURE__ */ jsx("div", { className: "max-w-2/3 w-37.5 text-center text-wrap text-2.5 text-text-secondary", children: description }),
86
+ required && /* @__PURE__ */ jsx(
87
+ Icon,
88
+ {
89
+ className: "absolute right-3 top-3 size-3 text-status-error",
90
+ icon: "i-nexus:required-monotone"
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsx(
94
+ "div",
95
+ {
96
+ className: "absolute left-0 top-0 z-0 size-full bg-contain bg-repeat",
97
+ style: { backgroundImage: `url(${grid})` }
98
+ }
99
+ ),
100
+ /* @__PURE__ */ jsx(Input, { onChange, multiple })
101
+ ]
102
+ }
103
+ );
104
+ };
105
+ ImgUploader.Input = Input;
106
+
107
+ export { ImgUploader };
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ type ImgSource = string | File;
3
+ interface ImgViewerProps {
4
+ className?: string;
5
+ src: ImgSource | ImgSource[];
6
+ children?: React.ReactNode;
7
+ }
8
+ interface ImgViewerComponent extends React.FC<ImgViewerProps> {
9
+ Delete: typeof Delete;
10
+ }
11
+ interface DeleteProps extends React.HTMLAttributes<HTMLButtonElement> {
12
+ onClick?: () => void;
13
+ }
14
+ declare const Delete: React.ForwardRefExoticComponent<DeleteProps & React.RefAttributes<HTMLButtonElement>>;
15
+ declare const ImgViewer: ImgViewerComponent;
16
+ export { ImgViewer };
@@ -0,0 +1,80 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { cn } from '../../utils/config.js';
3
+ import '@radix-ui/react-portal';
4
+ import '../../ui/avatar/index.js';
5
+ import '../../ui/button.js';
6
+ import '../../ui/carousel/index.js';
7
+ import '../../ui/checkbox/index.js';
8
+ import '../../ui/collapsible/index.js';
9
+ import '../../ui/dialog/confirm.js';
10
+ import '../../ui/dialog/dialog.js';
11
+ import '../../ui/drawer.js';
12
+ import '../../ui/form.js';
13
+ import '../../ui/input-otp.js';
14
+ import '../../ui/label.js';
15
+ import * as React from 'react';
16
+ import { useState, useEffect, useMemo } from 'react';
17
+ import '../../ui/popover/index.js';
18
+ import '../../ui/progress.js';
19
+ import '../../ui/select/index.js';
20
+ import '../../ui/slider/index.js';
21
+ import '../../ui/sonner.js';
22
+ import '../../ui/switch.js';
23
+ import '../../ui/table/index.js';
24
+ import '../../ui/tabs/index.js';
25
+ import '../../ui/toggle/toggle.js';
26
+ import '../../ui/toggle/toggle-group.js';
27
+ import '../../ui/tooltip/index.js';
28
+ import { Icon } from '../icon/index.js';
29
+
30
+ const BaseStyle = "group relative size-full overflow-hidden";
31
+ const BorderStyle = "box-border border border-white/8";
32
+ const Delete = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33
+ "button",
34
+ {
35
+ ref,
36
+ className: cn(
37
+ "absolute bottom-3 right-3 opacity-0 rounded-1/2 transition-opacity duration-base ease-smooth group-hover:opacity-100 group-hover:bg-black/60",
38
+ className
39
+ ),
40
+ ...props,
41
+ children: /* @__PURE__ */ jsx(Icon, { className: "m-2 size-5 text-text-primary", icon: "i-nexus:delete-monotone" })
42
+ }
43
+ ));
44
+ const ImgViewer = ({ src, className, children }) => {
45
+ const [images, setImages] = useState([]);
46
+ useEffect(() => {
47
+ const array = Array.isArray(src) ? src : [src];
48
+ const images2 = array.filter(Boolean).map((source) => {
49
+ if (source instanceof File) return URL.createObjectURL(source);
50
+ return source;
51
+ });
52
+ setImages(images2);
53
+ }, [src]);
54
+ const Inner = useMemo(() => {
55
+ if (images.length === 1) {
56
+ return /* @__PURE__ */ jsx("img", { src: images[0], alt: "preview-img", className: "size-full object-contain" });
57
+ }
58
+ if (images.length > 1) {
59
+ const rotation = [-15, 0, 15];
60
+ return images.slice(-3).map((url, index) => /* @__PURE__ */ jsx(
61
+ "img",
62
+ {
63
+ src: url,
64
+ alt: `preview-img-${index}`,
65
+ className: "absolute left-1/2 top-1/2 size-4/5 rounded-3.5 object-contain shadow-2xl",
66
+ style: { transform: `translate(-50%, -50%) rotate(${rotation[index]}deg)` }
67
+ },
68
+ `${url}${index}`
69
+ ));
70
+ }
71
+ return null;
72
+ }, [images]);
73
+ return /* @__PURE__ */ jsxs("div", { className: cn(BaseStyle, BorderStyle, className), children: [
74
+ Inner,
75
+ children
76
+ ] });
77
+ };
78
+ ImgViewer.Delete = Delete;
79
+
80
+ export { ImgViewer };
@@ -0,0 +1,9 @@
1
+ export * from './credits-button';
2
+ export * from './icon';
3
+ export * from './icon-button';
4
+ export * from './img-uploader';
5
+ export * from './img-viewer';
6
+ export * from './loadable';
7
+ export * from './loading';
8
+ export * from './model-uploader';
9
+ export * from './tree';
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ interface Props {
3
+ className?: string;
4
+ onLoadMore: () => Promise<void> | void;
5
+ children: React.ReactNode;
6
+ }
7
+ export declare const Loadable: React.FC<Props>;
8
+ export {};
@@ -0,0 +1,67 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { cn } from '../../utils/config.js';
3
+ import '@radix-ui/react-portal';
4
+ import '../../ui/avatar/index.js';
5
+ import '../../ui/button.js';
6
+ import '../../ui/carousel/index.js';
7
+ import '../../ui/checkbox/index.js';
8
+ import '../../ui/collapsible/index.js';
9
+ import '../../ui/dialog/confirm.js';
10
+ import '../../ui/dialog/dialog.js';
11
+ import '../../ui/drawer.js';
12
+ import '../../ui/form.js';
13
+ import '../../ui/input-otp.js';
14
+ import '../../ui/label.js';
15
+ import { useRef, useState, useLayoutEffect } from 'react';
16
+ import '../../ui/popover/index.js';
17
+ import '../../ui/progress.js';
18
+ import '../../ui/select/index.js';
19
+ import '../../ui/slider/index.js';
20
+ import '../../ui/sonner.js';
21
+ import '../../ui/switch.js';
22
+ import '../../ui/table/index.js';
23
+ import '../../ui/tabs/index.js';
24
+ import '../../ui/toggle/toggle.js';
25
+ import '../../ui/toggle/toggle-group.js';
26
+ import '../../ui/tooltip/index.js';
27
+ import { Loading } from '../loading/index.js';
28
+
29
+ const Loadable = ({ children, onLoadMore, className }) => {
30
+ const ref = useRef(null);
31
+ const loadMoreRef = useRef(onLoadMore);
32
+ const loadingRef = useRef(false);
33
+ const [loading, setLoading] = useState(false);
34
+ loadMoreRef.current = onLoadMore;
35
+ loadingRef.current = loading;
36
+ useLayoutEffect(() => {
37
+ if (!ref.current) return;
38
+ const observer = new IntersectionObserver(async ([entry]) => {
39
+ if (entry.intersectionRatio <= 0) return;
40
+ if (loadingRef.current) return;
41
+ try {
42
+ setLoading(true);
43
+ loadingRef.current = true;
44
+ await loadMoreRef.current();
45
+ } catch (error) {
46
+ console.error("加载更多数据时发生错误:", error);
47
+ } finally {
48
+ setLoading(false);
49
+ loadingRef.current = false;
50
+ }
51
+ });
52
+ observer.observe(ref.current);
53
+ return () => observer.disconnect();
54
+ }, []);
55
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
56
+ children,
57
+ /* @__PURE__ */ jsx("div", { ref, className: "min-h-10 w-full", children: loading && /* @__PURE__ */ jsx(
58
+ "div",
59
+ {
60
+ className: cn("w-full flex flex-col items-center justify-center gap-2 mt-5", className),
61
+ children: /* @__PURE__ */ jsx(Loading.Icon, { className: "max-w-10" })
62
+ }
63
+ ) })
64
+ ] });
65
+ };
66
+
67
+ export { Loadable };