@jacshuo/onyx 0.1.4

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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +497 -0
  3. package/dist/components/Accordion.d.ts +20 -0
  4. package/dist/components/Accordion.d.ts.map +1 -0
  5. package/dist/components/Alert.d.ts +25 -0
  6. package/dist/components/Alert.d.ts.map +1 -0
  7. package/dist/components/Badge.d.ts +7 -0
  8. package/dist/components/Badge.d.ts.map +1 -0
  9. package/dist/components/Button.d.ts +7 -0
  10. package/dist/components/Button.d.ts.map +1 -0
  11. package/dist/components/Card.d.ts +30 -0
  12. package/dist/components/Card.d.ts.map +1 -0
  13. package/dist/components/Chat.d.ts +29 -0
  14. package/dist/components/Chat.d.ts.map +1 -0
  15. package/dist/components/CinePlayer.d.ts +37 -0
  16. package/dist/components/CinePlayer.d.ts.map +1 -0
  17. package/dist/components/Dialog.d.ts +21 -0
  18. package/dist/components/Dialog.d.ts.map +1 -0
  19. package/dist/components/Dropdown.d.ts +57 -0
  20. package/dist/components/Dropdown.d.ts.map +1 -0
  21. package/dist/components/DropdownButton.d.ts +33 -0
  22. package/dist/components/DropdownButton.d.ts.map +1 -0
  23. package/dist/components/FileExplorer.d.ts +93 -0
  24. package/dist/components/FileExplorer.d.ts.map +1 -0
  25. package/dist/components/FilmReel.d.ts +40 -0
  26. package/dist/components/FilmReel.d.ts.map +1 -0
  27. package/dist/components/Header.d.ts +50 -0
  28. package/dist/components/Header.d.ts.map +1 -0
  29. package/dist/components/ImageCard.d.ts +23 -0
  30. package/dist/components/ImageCard.d.ts.map +1 -0
  31. package/dist/components/Input.d.ts +21 -0
  32. package/dist/components/Input.d.ts.map +1 -0
  33. package/dist/components/Label.d.ts +7 -0
  34. package/dist/components/Label.d.ts.map +1 -0
  35. package/dist/components/List.d.ts +8 -0
  36. package/dist/components/List.d.ts.map +1 -0
  37. package/dist/components/MiniPlayer.d.ts +50 -0
  38. package/dist/components/MiniPlayer.d.ts.map +1 -0
  39. package/dist/components/Panel.d.ts +9 -0
  40. package/dist/components/Panel.d.ts.map +1 -0
  41. package/dist/components/SideNav.d.ts +64 -0
  42. package/dist/components/SideNav.d.ts.map +1 -0
  43. package/dist/components/Table.d.ts +79 -0
  44. package/dist/components/Table.d.ts.map +1 -0
  45. package/dist/components/Tabs.d.ts +25 -0
  46. package/dist/components/Tabs.d.ts.map +1 -0
  47. package/dist/components/Tooltip.d.ts +14 -0
  48. package/dist/components/Tooltip.d.ts.map +1 -0
  49. package/dist/components/Tree.d.ts +31 -0
  50. package/dist/components/Tree.d.ts.map +1 -0
  51. package/dist/index.cjs +1 -0
  52. package/dist/index.d.ts +27 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +1 -0
  55. package/dist/lib/utils.d.ts +3 -0
  56. package/dist/lib/utils.d.ts.map +1 -0
  57. package/dist/styles/theme.d.ts +48 -0
  58. package/dist/styles/theme.d.ts.map +1 -0
  59. package/dist/styles.css +4086 -0
  60. package/package.json +108 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shuo Wang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,497 @@
1
+ <p align="center">
2
+ <img src="https://img.shields.io/npm/v/@jacshuo/onyx?color=8b5cf6&style=flat-square" alt="npm version" />
3
+ <img src="https://img.shields.io/npm/l/@jacshuo/onyx?style=flat-square" alt="license" />
4
+ <img src="https://img.shields.io/github/actions/workflow/status/jacshuo/jac-ui/ci.yml?branch=main&style=flat-square&label=CI" alt="CI" />
5
+ <img src="https://img.shields.io/npm/dm/@jacshuo/onyx?color=10b981&style=flat-square" alt="downloads" />
6
+ </p>
7
+
8
+ # @jacshuo/onyx
9
+
10
+ A cross-platform **React UI component library** built with Tailwind CSS v4 — works in web browsers and Electron. Ships ESM + CJS bundles with full TypeScript declarations.
11
+
12
+ > **Live Demo →** [jacshuo.github.io/jac-ui](https://jacshuo.github.io/jac-ui)
13
+
14
+ ---
15
+
16
+ ## Features
17
+
18
+ - 🎨 **30+ components** — from Button → DataTable → CinePlayer
19
+ - 🌗 **Dark / Light mode** — class-based, works out of the box
20
+ - 🎯 **CSS variable design tokens** — override any color via `--cp-*`, `--mp-*`, `--fe-*` custom properties
21
+ - ⚡ **Tailwind CSS v4** — zero config, `@theme` tokens, `color-mix()` accent support
22
+ - 📦 **Tree-shakeable** — ESM + CJS dual output, `sideEffects: ["*.css"]`
23
+ - 🖥️ **Cross-platform** — built with web & Electron in mind
24
+ - 🔤 **Full TypeScript** — every prop, event, and variant is typed
25
+
26
+ ---
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm install @jacshuo/onyx
32
+ # or
33
+ pnpm add @jacshuo/onyx
34
+ # or
35
+ yarn add @jacshuo/onyx
36
+ ```
37
+
38
+ ### Peer Dependencies
39
+
40
+ ```bash
41
+ npm install react react-dom
42
+ ```
43
+
44
+ > Requires **React ≥ 18.0.0**.
45
+
46
+ ---
47
+
48
+ ## Quick Start
49
+
50
+ **1. Import the stylesheet** (once, at your app entry point):
51
+
52
+ ```tsx
53
+ // main.tsx or App.tsx
54
+ import '@jacshuo/onyx/styles.css';
55
+ ```
56
+
57
+ **2. Use components:**
58
+
59
+ ```tsx
60
+ import { Button, Card, CardHeader, CardTitle, CardContent } from '@jacshuo/onyx';
61
+
62
+ function App() {
63
+ return (
64
+ <Card>
65
+ <CardHeader>
66
+ <CardTitle>Hello World</CardTitle>
67
+ </CardHeader>
68
+ <CardContent>
69
+ <Button intent="primary">Get Started</Button>
70
+ </CardContent>
71
+ </Card>
72
+ );
73
+ }
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Components
79
+
80
+ ### Primitives
81
+
82
+ | Component | Description |
83
+ |---|---|
84
+ | **Button** | Primary, secondary, danger, warning, ghost, outline intents with sm/md/lg sizes |
85
+ | **Input** | Styled text input with variant support |
86
+ | **Label** | Form label with size variants |
87
+ | **Badge** | Inline status badges |
88
+ | **Dropdown** | Single & multi-select dropdowns |
89
+ | **DropdownButton** | Button with a dropdown menu |
90
+
91
+ ### Layout
92
+
93
+ | Component | Description |
94
+ |---|---|
95
+ | **Card** | Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter |
96
+ | **HorizontalCard** | Side-by-side image + content card |
97
+ | **ImageCard** | Image-first card with overlay actions |
98
+ | **Panel** | Collapsible panel with header |
99
+
100
+ ### Data Display
101
+
102
+ | Component | Description |
103
+ |---|---|
104
+ | **Table** | Basic table primitives (Table, TableHeader, TableBody, TableRow, etc.) |
105
+ | **SortableTable** | Click-to-sort column headers |
106
+ | **DataTable** | Full-featured data table with sorting, selection, pagination |
107
+ | **List / ListItem** | Styled list component |
108
+ | **Tree / TreeItem** | Expandable tree view |
109
+ | **Chat** | Chat message list with sent/received styling |
110
+
111
+ ### Navigation
112
+
113
+ | Component | Description |
114
+ |---|---|
115
+ | **SideNav** | Collapsible sidebar with icons, sections, and multiple collapse modes |
116
+ | **Header** | App header with nav items and action buttons |
117
+ | **Tabs** | Tab bar with sliding indicator animation |
118
+
119
+ ### Disclosure
120
+
121
+ | Component | Description |
122
+ |---|---|
123
+ | **Accordion** | Expandable accordion sections |
124
+ | **Tabs** | TabList, TabTrigger, TabPanels, TabContent |
125
+
126
+ ### Overlay
127
+
128
+ | Component | Description |
129
+ |---|---|
130
+ | **Dialog** | Modal dialog with stacking support, backdrop click, ESC handling |
131
+ | **Tooltip** | Hover tooltip with configurable placement |
132
+ | **Alert** | Toast-style alert system with `useAlert()` hook |
133
+
134
+ ### Extras
135
+
136
+ | Component | Description |
137
+ |---|---|
138
+ | **FilmReel** | Cinematic photo gallery with lightbox |
139
+ | **MiniPlayer** | Floating mini music player with dock, playlist, shuffle, loop |
140
+ | **CinePlayer** | Full video player with cinema mode, playlist, keyboard shortcuts |
141
+ | **FileExplorer** | Sci-fi themed file explorer with drag, resize, dock, multi-select, Delete key |
142
+
143
+ ---
144
+
145
+ ## Theming
146
+
147
+ ### Dark Mode
148
+
149
+ The library uses Tailwind's **class-based** dark mode. Add `class="dark"` to your `<html>` or any ancestor element:
150
+
151
+ ```html
152
+ <html class="dark">
153
+ <!-- all jac-ui components render in dark mode -->
154
+ </html>
155
+ ```
156
+
157
+ ### Accent Colors
158
+
159
+ Many components accept an `accent` prop (any CSS color string):
160
+
161
+ ```tsx
162
+ <MiniPlayer accent="#3b82f6" playlist={tracks} />
163
+ <CinePlayer accent="#f43f5e" playlist={videos} />
164
+ <FileExplorer accent="#10b981" files={files} />
165
+ ```
166
+
167
+ ### CSS Custom Properties
168
+
169
+ All component colors are defined as CSS custom properties in `:root` and `.dark`, making them fully overridable:
170
+
171
+ ```css
172
+ /* Override CinePlayer colors */
173
+ :root {
174
+ --cp-bg: #111;
175
+ --cp-text: rgba(255, 255, 255, 0.8);
176
+ --cp-surface-hover: rgba(255, 255, 255, 0.15);
177
+ }
178
+
179
+ /* Override MiniPlayer colors */
180
+ :root {
181
+ --mp-bg: rgba(255, 255, 255, 0.95);
182
+ --mp-text: #1e293b;
183
+ }
184
+ .dark {
185
+ --mp-bg: rgba(20, 18, 30, 0.95);
186
+ --mp-text: #ffffff;
187
+ }
188
+
189
+ /* Override FileExplorer colors */
190
+ :root {
191
+ --fe-bg: linear-gradient(145deg, #fff, #f8f8fc);
192
+ --fe-text: #475569;
193
+ }
194
+ ```
195
+
196
+ <details>
197
+ <summary><strong>Full token reference</strong></summary>
198
+
199
+ #### CinePlayer (`--cp-*`)
200
+ | Token | Default | Description |
201
+ |---|---|---|
202
+ | `--cp-bg` | `#000000` | Player background |
203
+ | `--cp-panel-bg` | `rgba(0,0,0,0.85)` | Playlist/overlay panel |
204
+ | `--cp-text` | `rgba(255,255,255,0.75)` | Primary text |
205
+ | `--cp-text-muted` | `rgba(255,255,255,0.50)` | Secondary text |
206
+ | `--cp-text-strong` | `#ffffff` | Emphasized text |
207
+ | `--cp-border` | `rgba(255,255,255,0.10)` | Border color |
208
+ | `--cp-surface` | `rgba(255,255,255,0.05)` | Surface background |
209
+ | `--cp-surface-hover` | `rgba(255,255,255,0.10)` | Hover state |
210
+ | `--cp-overlay` | `rgba(0,0,0,0.30)` | Overlay backdrop |
211
+ | `--cp-seek-track` | `rgba(255,255,255,0.20)` | Seek bar track |
212
+ | `--cp-seek-buffer` | `rgba(255,255,255,0.15)` | Buffered region |
213
+
214
+ #### MiniPlayer (`--mp-*`)
215
+ | Token | Light | Dark |
216
+ |---|---|---|
217
+ | `--mp-bg` | `rgba(255,255,255,0.90)` | `rgba(26,22,37,0.95)` |
218
+ | `--mp-text` | `primary-900` | `#ffffff` |
219
+ | `--mp-text-muted` | `primary-500` | `rgba(255,255,255,0.50)` |
220
+ | `--mp-border` | `rgba(148,163,184,0.60)` | `rgba(255,255,255,0.10)` |
221
+ | `--mp-surface` | `rgba(148,163,184,0.50)` | `rgba(255,255,255,0.10)` |
222
+ | `--mp-surface-hover` | `rgba(241,245,249,0.60)` | `rgba(255,255,255,0.05)` |
223
+ | `--mp-dock-strip` | `rgba(148,163,184,0.40)` | `rgba(255,255,255,0.20)` |
224
+
225
+ #### FileExplorer (`--fe-*`)
226
+ | Token | Light | Dark |
227
+ |---|---|---|
228
+ | `--fe-bg` | Gradient white | Gradient dark |
229
+ | `--fe-shadow` | Soft shadow | Glow shadow |
230
+ | `--fe-text` | `primary-600` | `rgba(255,255,255,0.70)` |
231
+ | `--fe-text-strong` | `primary-900` | `#ffffff` |
232
+ | `--fe-text-muted` | `primary-400` | `rgba(255,255,255,0.30)` |
233
+ | `--fe-border` | `rgba(0,0,0,0.06)` | `rgba(255,255,255,0.06)` |
234
+ | `--fe-btn-color` | `rgba(0,0,0,0.45)` | `rgba(255,255,255,0.50)` |
235
+
236
+ </details>
237
+
238
+ ---
239
+
240
+ ## Usage Examples
241
+
242
+ ### Button
243
+
244
+ ```tsx
245
+ import { Button } from '@jacshuo/onyx';
246
+
247
+ <Button intent="primary" size="lg">Save</Button>
248
+ <Button intent="danger">Delete</Button>
249
+ <Button intent="ghost">Cancel</Button>
250
+ <Button intent="outline">Settings</Button>
251
+ ```
252
+
253
+ ### Dialog
254
+
255
+ ```tsx
256
+ import { useState } from 'react';
257
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Button } from '@jacshuo/onyx';
258
+
259
+ function ConfirmDialog() {
260
+ const [open, setOpen] = useState(false);
261
+
262
+ return (
263
+ <>
264
+ <Button onClick={() => setOpen(true)}>Open Dialog</Button>
265
+ <Dialog open={open} onOpenChange={setOpen}>
266
+ <DialogContent size="sm">
267
+ <DialogHeader>
268
+ <DialogTitle>Confirm Action</DialogTitle>
269
+ </DialogHeader>
270
+ <p>Are you sure you want to proceed?</p>
271
+ <DialogFooter>
272
+ <Button intent="ghost" onClick={() => setOpen(false)}>Cancel</Button>
273
+ <Button intent="primary" onClick={() => setOpen(false)}>Confirm</Button>
274
+ </DialogFooter>
275
+ </DialogContent>
276
+ </Dialog>
277
+ </>
278
+ );
279
+ }
280
+ ```
281
+
282
+ ### DataTable
283
+
284
+ ```tsx
285
+ import { DataTable, type ColumnDef } from '@jacshuo/onyx';
286
+
287
+ type User = { id: number; name: string; email: string };
288
+
289
+ const columns: ColumnDef<User>[] = [
290
+ { key: 'id', header: 'ID', width: 60 },
291
+ { key: 'name', header: 'Name', sortable: true },
292
+ { key: 'email', header: 'Email', sortable: true },
293
+ ];
294
+
295
+ <DataTable columns={columns} data={users} selectionMode="multi" pageSize={10} />
296
+ ```
297
+
298
+ ### Tabs
299
+
300
+ ```tsx
301
+ import { Tabs, TabList, TabTrigger, TabPanels, TabContent } from '@jacshuo/onyx';
302
+
303
+ <Tabs defaultValue="overview">
304
+ <TabList>
305
+ <TabTrigger value="overview">Overview</TabTrigger>
306
+ <TabTrigger value="settings">Settings</TabTrigger>
307
+ </TabList>
308
+ <TabPanels>
309
+ <TabContent value="overview">Overview content…</TabContent>
310
+ <TabContent value="settings">Settings content…</TabContent>
311
+ </TabPanels>
312
+ </Tabs>
313
+ ```
314
+
315
+ ### Alert (Toast)
316
+
317
+ ```tsx
318
+ import { useAlert, Button } from '@jacshuo/onyx';
319
+
320
+ function NotifyButton() {
321
+ const alert = useAlert();
322
+
323
+ return (
324
+ <Button onClick={() => alert({ title: 'Saved!', description: 'Your changes have been saved.', variant: 'success' })}>
325
+ Save
326
+ </Button>
327
+ );
328
+ }
329
+ ```
330
+
331
+ ### MiniPlayer
332
+
333
+ ```tsx
334
+ import { MiniPlayer } from '@jacshuo/onyx';
335
+
336
+ const tracks = [
337
+ { title: 'Midnight City', artist: 'M83', src: '/audio/midnight.mp3', cover: '/covers/m83.jpg' },
338
+ { title: 'Intro', artist: 'The xx', src: '/audio/intro.mp3' },
339
+ ];
340
+
341
+ <MiniPlayer
342
+ playlist={tracks}
343
+ position="bottom-right"
344
+ accent="#8b5cf6"
345
+ shuffle
346
+ autoPlay
347
+ />
348
+ ```
349
+
350
+ ### CinePlayer
351
+
352
+ ```tsx
353
+ import { CinePlayer } from '@jacshuo/onyx';
354
+
355
+ const videos = [
356
+ { title: 'Big Buck Bunny', src: 'https://example.com/bunny.mp4', subtitle: 'Open source' },
357
+ ];
358
+
359
+ <CinePlayer
360
+ playlist={videos}
361
+ accent="#f43f5e"
362
+ onPlayChange={(playing, index) => console.log(playing, index)}
363
+ />
364
+ ```
365
+
366
+ ### FileExplorer
367
+
368
+ ```tsx
369
+ import { FileExplorer, type FileExplorerItem } from '@jacshuo/onyx';
370
+
371
+ const files: FileExplorerItem[] = [
372
+ { name: 'src', path: '/src', type: 'directory' },
373
+ { name: 'index.ts', path: '/src/index.ts', type: 'file', size: 2048, extension: '.ts' },
374
+ ];
375
+
376
+ <FileExplorer
377
+ files={files}
378
+ accent="#10b981"
379
+ dockable
380
+ onFileOpen={(f) => console.log('Open', f.name)}
381
+ onDelete={(items) => console.log('Delete', items)}
382
+ />
383
+ ```
384
+
385
+ ---
386
+
387
+ ## Keyboard Shortcuts
388
+
389
+ ### FileExplorer
390
+ | Key | Action |
391
+ |---|---|
392
+ | `Click` | Select file |
393
+ | `Ctrl+Click` | Multi-select |
394
+ | `Ctrl+A` | Select all |
395
+ | `Delete` | Delete selected (with confirmation dialog) |
396
+ | `Escape` | Clear selection |
397
+ | `Double-click` | Open file / Navigate directory |
398
+
399
+ ### CinePlayer
400
+ | Key | Action |
401
+ |---|---|
402
+ | `Space` | Play / Pause |
403
+ | `←` / `→` | Seek ±5s |
404
+ | `↑` / `↓` | Volume ±5% |
405
+ | `F` | Toggle fullscreen |
406
+ | `C` | Toggle cinema mode |
407
+ | `L` | Toggle playlist |
408
+ | `M` | Mute / Unmute |
409
+ | `N` | Next track |
410
+ | `P` | Previous track |
411
+ | `S` | Toggle shuffle |
412
+
413
+ ---
414
+
415
+ ## Development
416
+
417
+ ```bash
418
+ # Install dependencies
419
+ npm install
420
+
421
+ # Start demo dev server (http://localhost:8080)
422
+ npm run dev
423
+
424
+ # Production library build (dist/)
425
+ npm run dist
426
+
427
+ # Build demo site (dist-demo/)
428
+ npm run build:demo
429
+
430
+ # Typecheck
431
+ npm run typecheck
432
+ ```
433
+
434
+ ---
435
+
436
+ ## Release Process
437
+
438
+ Releases are fully automated via GitHub Actions:
439
+
440
+ 1. Go to **Actions → Release → Run workflow**
441
+ 2. Choose version bump: `patch` / `minor` / `major`
442
+ 3. The pipeline will:
443
+ - Bump `package.json` version
444
+ - Commit & tag (e.g. `v0.2.0`)
445
+ - Build & publish to **npm**
446
+ - Create a **GitHub Release** with `.tar.gz` and `.zip` download artifacts
447
+ - Build & deploy the **demo site** to GitHub Pages
448
+
449
+ ### Required Secrets
450
+
451
+ | Secret | Where | Description |
452
+ |---|---|---|
453
+ | `NPM_TOKEN` | GitHub repo → Settings → Secrets | npm access token with publish permission |
454
+
455
+ ### GitHub Pages Setup
456
+
457
+ 1. Go to **Settings → Pages**
458
+ 2. Source: **GitHub Actions**
459
+
460
+ ---
461
+
462
+ ## Project Structure
463
+
464
+ ```
465
+ jac-ui/
466
+ ├── src/
467
+ │ ├── components/ # All React components
468
+ │ ├── lib/utils.ts # cn() utility (clsx + tailwind-merge)
469
+ │ └── styles/
470
+ │ ├── theme.css # Tailwind theme, keyframes, CSS custom properties
471
+ │ └── theme.ts # CVA variant definitions
472
+ ├── demo/ # Demo site (GitHub Pages)
473
+ │ ├── App.tsx
474
+ │ ├── main.tsx
475
+ │ └── pages/ # Per-component demo pages
476
+ ├── .github/workflows/
477
+ │ ├── ci.yml # PR/push: typecheck + build
478
+ │ └── release.yml # Manual: version bump → npm → GitHub Release → Pages
479
+ ├── dist/ # Library build output
480
+ └── dist-demo/ # Demo build output
481
+ ```
482
+
483
+ ---
484
+
485
+ ## Contributing
486
+
487
+ 1. Fork the repository
488
+ 2. Create a feature branch (`git checkout -b feature/my-feature`)
489
+ 3. Commit your changes (`git commit -m 'feat: add new component'`)
490
+ 4. Push to the branch (`git push origin feature/my-feature`)
491
+ 5. Open a Pull Request
492
+
493
+ ---
494
+
495
+ ## License
496
+
497
+ [MIT](./LICENSE) © Shuo Wang
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ import { accordionVariants } from '../styles/theme';
4
+ type AccordionProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof accordionVariants> & {
5
+ type?: 'single' | 'multiple';
6
+ defaultValue?: string[];
7
+ value?: string[];
8
+ onValueChange?: (value: string[]) => void;
9
+ };
10
+ export declare function Accordion({ type, defaultValue, value, onValueChange, intent, className, children, ...props }: AccordionProps): import("react/jsx-runtime").JSX.Element;
11
+ type AccordionItemProps = React.HTMLAttributes<HTMLDivElement> & {
12
+ value: string;
13
+ };
14
+ export declare function AccordionItem({ value, className, children, ...props }: AccordionItemProps): import("react/jsx-runtime").JSX.Element;
15
+ type AccordionTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
16
+ export declare function AccordionTrigger({ className, children, ...props }: AccordionTriggerProps): import("react/jsx-runtime").JSX.Element;
17
+ type AccordionContentProps = React.HTMLAttributes<HTMLDivElement>;
18
+ export declare function AccordionContent({ className, children, ...props }: AccordionContentProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};
20
+ //# sourceMappingURL=Accordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../src/components/Accordion.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAChF,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAepD,KAAK,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GACxD,YAAY,CAAC,OAAO,iBAAiB,CAAC,GAAG;IACvC,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEJ,wBAAgB,SAAS,CAAC,EACxB,IAAe,EACf,YAAiB,EACjB,KAAK,EACL,aAAa,EACb,MAAM,EACN,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,2CA6BhB;AAID,KAAK,kBAAkB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,2CAWzF;AAID,KAAK,qBAAqB,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAE3E,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,qBAAqB,2CAuBxF;AAID,KAAK,qBAAqB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;AAElE,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,qBAAqB,2CAoBxF"}
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ import { alertVariants } from '../styles/theme';
4
+ type AlertProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>;
5
+ export declare function Alert({ intent, className, children, ...props }: AlertProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function AlertTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>): import("react/jsx-runtime").JSX.Element;
7
+ export declare function AlertDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>): import("react/jsx-runtime").JSX.Element;
8
+ export type AlertPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center';
9
+ type AlertIntent = NonNullable<VariantProps<typeof alertVariants>['intent']>;
10
+ export type AlertOptions = {
11
+ intent?: AlertIntent;
12
+ title?: string;
13
+ message: string;
14
+ position?: AlertPosition;
15
+ duration?: number;
16
+ };
17
+ declare function removeAlert(id: string): void;
18
+ declare function addAlert(options: AlertOptions): string;
19
+ export declare function configureAlertTopOffset(offset: number): void;
20
+ export declare function useAlert(): {
21
+ addAlert: typeof addAlert;
22
+ removeAlert: typeof removeAlert;
23
+ };
24
+ export {};
25
+ //# sourceMappingURL=Alert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../../src/components/Alert.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAGvE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMhD,KAAK,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAE5F,wBAAgB,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,2CAM1E;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,2CAE3F;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC,2CAE5C;AAMD,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,UAAU,GACV,cAAc,GACd,aAAa,GACb,YAAY,GACZ,eAAe,CAAC;AAEpB,KAAK,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE7E,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAsBF,iBAAS,WAAW,CAAC,EAAE,EAAE,MAAM,QAY9B;AAED,iBAAS,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAe/C;AAQD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,QAErD;AA4HD,wBAAgB,QAAQ;;;EAMvB"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ import { badgeVariants } from '../styles/theme';
4
+ type BadgeProps = React.HTMLAttributes<HTMLSpanElement> & VariantProps<typeof badgeVariants>;
5
+ export declare function Badge({ intent, className, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=Badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../src/components/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,KAAK,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAE7F,wBAAgB,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,2CAEhE"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ import { buttonVariants } from '../styles/theme';
4
+ type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>;
5
+ export declare function Button({ intent, size, className, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=Button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/components/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,KAAK,WAAW,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAC9D,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtC,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW,2CAExE"}
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ import { cardVariants } from '../styles/theme';
4
+ type CardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof cardVariants>;
5
+ export declare function Card({ intent, size, className, ...props }: CardProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
7
+ export declare function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>): import("react/jsx-runtime").JSX.Element;
8
+ export declare function CardDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>): import("react/jsx-runtime").JSX.Element;
9
+ export declare function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
10
+ export declare function CardFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
11
+ type HorizontalCardMediaProps = {
12
+ /** Image source URL. */
13
+ src?: string;
14
+ /** Image alt text. */
15
+ alt?: string;
16
+ /** Render an icon or avatar instead of an image. */
17
+ icon?: React.ReactNode;
18
+ /** Width of the media area. @default '10rem' */
19
+ width?: string;
20
+ };
21
+ type HorizontalCardProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> & VariantProps<typeof cardVariants> & {
22
+ /** Media placement. @default 'left' */
23
+ mediaPosition?: 'left' | 'right';
24
+ /** Media configuration. */
25
+ media: HorizontalCardMediaProps;
26
+ children: React.ReactNode;
27
+ };
28
+ export declare function HorizontalCard({ intent, media, mediaPosition, className, children, ...props }: HorizontalCardProps): import("react/jsx-runtime").JSX.Element;
29
+ export {};
30
+ //# sourceMappingURL=Card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/components/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,KAAK,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC;AAE1F,wBAAgB,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,2CAEpE;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,2CAEvF;AAED,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,2CAO1F;AAED,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC,2CAI5C;AAED,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,2CAIxF;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,2CAUvF;AAID,KAAK,wBAAwB,GAAG;IAC9B,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAC/E,YAAY,CAAC,OAAO,YAAY,CAAC,GAAG;IAClC,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,2BAA2B;IAC3B,KAAK,EAAE,wBAAwB,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEJ,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,aAAsB,EACtB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,mBAAmB,2CAsCrB"}
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ export interface ChatMessage {
3
+ /** Unique id for the message. */
4
+ id: string | number;
5
+ /** Sender display name. */
6
+ sender: string;
7
+ /** Avatar — URL string or ReactNode (icon / component). */
8
+ avatar?: string | React.ReactNode;
9
+ /** Message body. Can be text or rich ReactNode content. */
10
+ content: React.ReactNode;
11
+ /** Timestamp label, e.g. "10:30 AM". */
12
+ time?: string;
13
+ /** Mark as "self" (current user). Controls bubble alignment in split mode. */
14
+ self?: boolean;
15
+ }
16
+ export interface ChatProps extends React.HTMLAttributes<HTMLDivElement> {
17
+ /** Array of messages to render. */
18
+ messages: ChatMessage[];
19
+ /**
20
+ * Layout mode.
21
+ * - `'split'` — self messages on the right, others on the left (default)
22
+ * - `'left'` — all messages aligned to the left
23
+ */
24
+ mode?: 'split' | 'left';
25
+ /** Auto-scroll to bottom when messages change. @default true */
26
+ autoScroll?: boolean;
27
+ }
28
+ export declare function Chat({ messages, mode, autoScroll, className, ...props }: ChatProps): import("react/jsx-runtime").JSX.Element;
29
+ //# sourceMappingURL=Chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/components/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAKjD,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAClC,2DAA2D;IAC3D,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACrE,mCAAmC;IACnC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA+ED,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,IAAc,EACd,UAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,SAAS,2CAyBX"}