@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.
- package/LICENSE +21 -0
- package/README.md +497 -0
- package/dist/components/Accordion.d.ts +20 -0
- package/dist/components/Accordion.d.ts.map +1 -0
- package/dist/components/Alert.d.ts +25 -0
- package/dist/components/Alert.d.ts.map +1 -0
- package/dist/components/Badge.d.ts +7 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/Button.d.ts +7 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Card.d.ts +30 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Chat.d.ts +29 -0
- package/dist/components/Chat.d.ts.map +1 -0
- package/dist/components/CinePlayer.d.ts +37 -0
- package/dist/components/CinePlayer.d.ts.map +1 -0
- package/dist/components/Dialog.d.ts +21 -0
- package/dist/components/Dialog.d.ts.map +1 -0
- package/dist/components/Dropdown.d.ts +57 -0
- package/dist/components/Dropdown.d.ts.map +1 -0
- package/dist/components/DropdownButton.d.ts +33 -0
- package/dist/components/DropdownButton.d.ts.map +1 -0
- package/dist/components/FileExplorer.d.ts +93 -0
- package/dist/components/FileExplorer.d.ts.map +1 -0
- package/dist/components/FilmReel.d.ts +40 -0
- package/dist/components/FilmReel.d.ts.map +1 -0
- package/dist/components/Header.d.ts +50 -0
- package/dist/components/Header.d.ts.map +1 -0
- package/dist/components/ImageCard.d.ts +23 -0
- package/dist/components/ImageCard.d.ts.map +1 -0
- package/dist/components/Input.d.ts +21 -0
- package/dist/components/Input.d.ts.map +1 -0
- package/dist/components/Label.d.ts +7 -0
- package/dist/components/Label.d.ts.map +1 -0
- package/dist/components/List.d.ts +8 -0
- package/dist/components/List.d.ts.map +1 -0
- package/dist/components/MiniPlayer.d.ts +50 -0
- package/dist/components/MiniPlayer.d.ts.map +1 -0
- package/dist/components/Panel.d.ts +9 -0
- package/dist/components/Panel.d.ts.map +1 -0
- package/dist/components/SideNav.d.ts +64 -0
- package/dist/components/SideNav.d.ts.map +1 -0
- package/dist/components/Table.d.ts +79 -0
- package/dist/components/Table.d.ts.map +1 -0
- package/dist/components/Tabs.d.ts +25 -0
- package/dist/components/Tabs.d.ts.map +1 -0
- package/dist/components/Tooltip.d.ts +14 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tree.d.ts +31 -0
- package/dist/components/Tree.d.ts.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/styles/theme.d.ts +48 -0
- package/dist/styles/theme.d.ts.map +1 -0
- package/dist/styles.css +4086 -0
- 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"}
|