@k8o/arte-odyssey 9.0.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -28
- package/dist/components/_internal/focus-ring.d.mts +8 -0
- package/dist/components/_internal/focus-ring.mjs +8 -0
- package/dist/components/buttons/button/button.d.mts +9 -2
- package/dist/components/buttons/button/button.mjs +13 -12
- package/dist/components/buttons/icon-button/icon-button.d.mts +8 -2
- package/dist/components/buttons/icon-button/icon-button.mjs +3 -2
- package/dist/components/data-display/accordion/accordion-button.mjs +3 -2
- package/dist/components/data-display/accordion/accordion-item.d.mts +2 -0
- package/dist/components/data-display/accordion/accordion-item.mjs +7 -2
- package/dist/components/data-display/accordion/accordion.mjs +1 -1
- package/dist/components/data-display/accordion/context.d.mts +2 -0
- package/dist/components/data-display/accordion/context.mjs +12 -6
- package/dist/components/data-display/accordion/index.d.mts +9 -9
- package/dist/components/data-display/avatar/avatar.d.mts +1 -1
- package/dist/components/data-display/avatar/avatar.mjs +3 -3
- package/dist/components/data-display/badge/badge.d.mts +2 -2
- package/dist/components/data-display/badge/badge.mjs +6 -5
- package/dist/components/data-display/card/card.mjs +2 -2
- package/dist/components/data-display/card/interactive-card.mjs +2 -2
- package/dist/components/data-display/card/type.d.mts +1 -1
- package/dist/components/data-display/code/code.d.mts +1 -1
- package/dist/components/data-display/code/code.mjs +3 -4
- package/dist/components/data-display/code/find-all-colors.mjs +3 -3
- package/dist/components/data-display/heading/heading.d.mts +1 -1
- package/dist/components/data-display/heading/heading.mjs +7 -7
- package/dist/components/data-display/table/table.d.mts +12 -17
- package/dist/components/data-display/table/table.mjs +23 -21
- package/dist/components/feedback/alert/alert.d.mts +2 -2
- package/dist/components/feedback/alert/alert.mjs +6 -6
- package/dist/components/feedback/progress/progress.d.mts +1 -1
- package/dist/components/feedback/progress/progress.mjs +5 -6
- package/dist/components/feedback/skeleton/skeleton.d.mts +1 -1
- package/dist/components/feedback/skeleton/skeleton.mjs +2 -2
- package/dist/components/feedback/spinner/spinner.d.mts +1 -1
- package/dist/components/feedback/spinner/spinner.mjs +2 -2
- package/dist/components/feedback/toast/context.d.mts +3 -4
- package/dist/components/feedback/toast/context.mjs +3 -4
- package/dist/components/feedback/toast/provider.mjs +2 -2
- package/dist/components/feedback/toast/toast.d.mts +1 -1
- package/dist/components/feedback/toast/toast.mjs +2 -2
- package/dist/components/form/autocomplete/autocomplete.d.mts +1 -1
- package/dist/components/form/autocomplete/autocomplete.mjs +67 -39
- package/dist/components/form/checkbox/checkbox.d.mts +4 -4
- package/dist/components/form/checkbox/checkbox.mjs +5 -4
- package/dist/components/form/checkbox-card/checkbox-card.d.mts +1 -1
- package/dist/components/form/checkbox-card/checkbox-card.mjs +4 -2
- package/dist/components/form/checkbox-group/checkbox-group.d.mts +1 -1
- package/dist/components/form/checkbox-group/checkbox-group.mjs +1 -0
- package/dist/components/form/checkbox-group/index.d.mts +10 -12
- package/dist/components/form/file-field/file-field.d.mts +4 -5
- package/dist/components/form/file-field/file-field.mjs +2 -7
- package/dist/components/form/form/form.d.mts +1 -1
- package/dist/components/form/form/form.mjs +2 -3
- package/dist/components/form/number-field/cast.mjs +2 -2
- package/dist/components/form/number-field/number-field.d.mts +1 -1
- package/dist/components/form/number-field/number-field.mjs +7 -6
- package/dist/components/form/password-input/password-input.d.mts +1 -1
- package/dist/components/form/password-input/password-input.mjs +4 -3
- package/dist/components/form/radio/radio.d.mts +4 -4
- package/dist/components/form/radio/radio.mjs +6 -5
- package/dist/components/form/radio-card/radio-card.d.mts +4 -4
- package/dist/components/form/radio-card/radio-card.mjs +6 -4
- package/dist/components/form/select/select.d.mts +1 -1
- package/dist/components/form/select/select.mjs +6 -4
- package/dist/components/form/slider/slider.d.mts +1 -1
- package/dist/components/form/slider/slider.mjs +15 -8
- package/dist/components/form/switch/switch.d.mts +4 -4
- package/dist/components/form/switch/switch.mjs +4 -3
- package/dist/components/form/text-field/text-field.d.mts +1 -1
- package/dist/components/form/text-field/text-field.mjs +2 -1
- package/dist/components/form/textarea/textarea.d.mts +1 -1
- package/dist/components/form/textarea/textarea.mjs +2 -1
- package/dist/components/index.d.mts +3 -1
- package/dist/components/index.mjs +3 -1
- package/dist/components/layout/_shared/gap.d.mts +11 -0
- package/dist/components/layout/_shared/gap.mjs +10 -0
- package/dist/components/layout/grid/grid.d.mts +16 -0
- package/dist/components/layout/grid/grid.mjs +35 -0
- package/dist/components/layout/grid/index.d.mts +2 -0
- package/dist/components/layout/grid/index.mjs +2 -0
- package/dist/components/layout/separator/separator.d.mts +1 -1
- package/dist/components/layout/separator/separator.mjs +2 -5
- package/dist/components/layout/stack/index.d.mts +2 -0
- package/dist/components/layout/stack/index.mjs +2 -0
- package/dist/components/layout/stack/stack.d.mts +13 -0
- package/dist/components/layout/stack/stack.mjs +23 -0
- package/dist/components/navigation/anchor/anchor.d.mts +10 -9
- package/dist/components/navigation/anchor/anchor.mjs +4 -3
- package/dist/components/navigation/breadcrumb/breadcrumb.d.mts +2 -4
- package/dist/components/navigation/breadcrumb/breadcrumb.mjs +4 -4
- package/dist/components/navigation/pagination/pagination.mjs +12 -6
- package/dist/components/navigation/tabs/tabs.d.mts +2 -0
- package/dist/components/navigation/tabs/tabs.mjs +35 -19
- package/dist/components/overlays/dialog/dialog.d.mts +1 -2
- package/dist/components/overlays/drawer/drawer.d.mts +3 -2
- package/dist/components/overlays/drawer/drawer.mjs +7 -4
- package/dist/components/overlays/dropdown-menu/dropdown-menu.mjs +4 -4
- package/dist/components/overlays/dropdown-menu/hooks.d.mts +153 -154
- package/dist/components/overlays/list-box/hooks.d.mts +173 -174
- package/dist/components/overlays/list-box/list-box.d.mts +1 -1
- package/dist/components/overlays/list-box/list-box.mjs +6 -6
- package/dist/components/overlays/modal/modal.mjs +9 -5
- package/dist/components/overlays/popover/hooks.d.mts +1 -2
- package/dist/components/overlays/popover/popover.mjs +8 -2
- package/dist/components/overlays/tooltip/tooltip.d.mts +1 -2
- package/dist/hooks/index.d.mts +3 -2
- package/dist/hooks/index.mjs +4 -3
- package/dist/hooks/writing-mode/index.d.mts +7 -0
- package/dist/hooks/writing-mode/index.mjs +22 -0
- package/dist/index.d.mts +5 -2
- package/dist/index.mjs +21 -18
- package/dist/integrations/_shared/renderers.d.mts +74 -0
- package/dist/integrations/_shared/renderers.mjs +667 -0
- package/dist/integrations/_shared/schemas.d.mts +704 -0
- package/dist/integrations/_shared/schemas.mjs +496 -0
- package/dist/integrations/json-render/catalog.d.mts +770 -0
- package/dist/integrations/json-render/catalog.mjs +229 -0
- package/dist/integrations/json-render/registry.d.mts +4 -0
- package/dist/integrations/json-render/registry.mjs +137 -0
- package/dist/integrations/openui/form-views.d.mts +31 -0
- package/dist/integrations/openui/form-views.mjs +75 -0
- package/dist/integrations/openui/library.d.mts +4 -0
- package/dist/integrations/openui/library.mjs +432 -0
- package/dist/styles/base.css +75 -0
- package/dist/styles/index.css +12 -463
- package/dist/styles/tokens.css +379 -0
- package/dist/styles/tokens.d.mts +2 -84
- package/dist/styles/tokens.generated.d.mts +839 -0
- package/dist/styles/tokens.generated.mjs +812 -0
- package/dist/styles/tokens.mjs +2 -752
- package/dist/styles/utilities.css +62 -0
- package/dist/types/index.d.mts +1 -1
- package/docs/GUIDE.md +26 -7
- package/docs/references/components.md +40 -21
- package/docs/references/hooks.md +17 -0
- package/docs/references/typography.md +29 -0
- package/package.json +69 -27
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ npm install react react-dom typescript tailwindcss
|
|
|
23
23
|
Required versions:
|
|
24
24
|
|
|
25
25
|
- React ≥19.0.0
|
|
26
|
-
- TypeScript ≥
|
|
26
|
+
- TypeScript ≥6.0.0
|
|
27
27
|
- Tailwind CSS ≥4.0.0
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
@@ -76,61 +76,71 @@ ArteOdyssey includes design system documentation in `docs/` directory. When inst
|
|
|
76
76
|
|
|
77
77
|
## Component Categories
|
|
78
78
|
|
|
79
|
-
###
|
|
79
|
+
### Buttons
|
|
80
80
|
|
|
81
|
-
- **
|
|
81
|
+
- **Button** - Primary action button (use `renderItem` to render as a link)
|
|
82
|
+
- **IconButton** - Button with icon only (use `renderItem` to render as a link)
|
|
83
|
+
|
|
84
|
+
### Navigation
|
|
85
|
+
|
|
86
|
+
- **Anchor** - Text link with external-link awareness
|
|
82
87
|
- **Breadcrumb** - Navigation path indicator
|
|
83
|
-
- **
|
|
84
|
-
- **Separator** - Visual content divider
|
|
88
|
+
- **Pagination** - Page navigation controls
|
|
85
89
|
- **Tabs** - Tab-based content organization
|
|
86
|
-
- **ScrollLinked** - Scroll progress indicator
|
|
87
90
|
|
|
88
91
|
### Form Controls
|
|
89
92
|
|
|
90
93
|
- **Autocomplete** - Search with suggestions
|
|
91
|
-
- **Checkbox** -
|
|
94
|
+
- **Checkbox** / **CheckboxCard** / **CheckboxGroup** - Multi-selection inputs
|
|
92
95
|
- **FileField** - File upload with composite pattern
|
|
93
|
-
- **FormControl** - Form field
|
|
96
|
+
- **Form** / **FormControl** - Form wrapper and field with label/validation
|
|
94
97
|
- **NumberField** - Numeric input with controls
|
|
95
|
-
- **
|
|
96
|
-
- **
|
|
98
|
+
- **PasswordInput** - Password input with show/hide toggle
|
|
99
|
+
- **Radio** / **RadioCard** - Single-selection inputs
|
|
97
100
|
- **Select** - Dropdown selection
|
|
101
|
+
- **Slider** - Slider input control
|
|
102
|
+
- **Switch** - Toggle switch
|
|
98
103
|
- **TextField** - Single-line text input
|
|
99
104
|
- **Textarea** - Multi-line text input
|
|
100
105
|
|
|
101
|
-
###
|
|
106
|
+
### Data Display
|
|
102
107
|
|
|
103
|
-
- **
|
|
104
|
-
- **
|
|
105
|
-
- **
|
|
106
|
-
- **
|
|
107
|
-
- **
|
|
108
|
+
- **Accordion** - Collapsible content panels
|
|
109
|
+
- **Avatar** - User/entity avatar
|
|
110
|
+
- **Badge** - Status/label indicator
|
|
111
|
+
- **BaselineStatus** - Web standard support indicator
|
|
112
|
+
- **Card** / **InteractiveCard** - Flexible content container (with hover interaction)
|
|
113
|
+
- **Code** - Formatted code display
|
|
114
|
+
- **Heading** - Typography heading component
|
|
115
|
+
- **Table** - Tabular data display
|
|
108
116
|
|
|
109
|
-
### Feedback
|
|
117
|
+
### Feedback
|
|
110
118
|
|
|
111
119
|
- **Alert** - Important messages and notifications
|
|
112
|
-
- **Toast** - Temporary notification messages
|
|
113
120
|
- **Progress** - Progress indication
|
|
114
|
-
- **
|
|
121
|
+
- **Skeleton** - Content loading placeholder
|
|
122
|
+
- **Spinner** - Loading indicator
|
|
123
|
+
- **ToastProvider** / **useToast** - Temporary notification messages
|
|
115
124
|
|
|
116
|
-
### Overlays
|
|
125
|
+
### Overlays
|
|
117
126
|
|
|
118
127
|
- **Dialog** - Modal dialog boxes
|
|
119
128
|
- **Drawer** - Slide-out panel
|
|
129
|
+
- **DropdownMenu** - Action menu component
|
|
130
|
+
- **ListBox** - Selectable list component
|
|
120
131
|
- **Modal** - Overlay modal component
|
|
121
132
|
- **Popover** - Floating content container
|
|
122
133
|
- **Tooltip** - Contextual help text
|
|
123
|
-
- **DropdownMenu** - Action menu component
|
|
124
134
|
|
|
125
|
-
###
|
|
135
|
+
### Layout
|
|
126
136
|
|
|
127
|
-
- **
|
|
128
|
-
- **
|
|
129
|
-
- **ListBox** - Selectable list component
|
|
137
|
+
- **ScrollLinked** - Scroll progress indicator
|
|
138
|
+
- **Separator** - Visual content divider
|
|
130
139
|
|
|
131
140
|
### Utilities
|
|
132
141
|
|
|
133
|
-
- **ArteOdysseyProvider** -
|
|
142
|
+
- **ArteOdysseyProvider** - Root provider for the library
|
|
143
|
+
- **PortalRootProvider** / **usePortalRoot** - Customize the portal mount root
|
|
134
144
|
- **Icons** - Icon component collection
|
|
135
145
|
|
|
136
146
|
## Usage Examples
|
|
@@ -220,22 +230,105 @@ import { useClickAway } from '@k8o/arte-odyssey';
|
|
|
220
230
|
import { useLocalStorage } from '@k8o/arte-odyssey';
|
|
221
231
|
```
|
|
222
232
|
|
|
233
|
+
## Generative UI integrations
|
|
234
|
+
|
|
235
|
+
ArteOdyssey ships official adapters so an LLM can generate UIs using these components, via either [json-render](https://json-render.dev) or [OpenUI](https://www.openui.com). Each adapter constrains the model to ArteOdyssey components with prop schemas locked to the design tokens, so generated UIs stay on-brand. Component-specific `renderItem` render props are bridged internally — the model only ever sees flat data (e.g. `href`).
|
|
236
|
+
|
|
237
|
+
These integrations are exposed as optional subpath exports. Install the framework you use (they are optional peer dependencies):
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# json-render
|
|
241
|
+
pnpm add @json-render/core @json-render/react zod
|
|
242
|
+
# OpenUI
|
|
243
|
+
pnpm add @openuidev/react-lang zod
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Supported components (**all 47**, both frameworks):
|
|
247
|
+
|
|
248
|
+
- **Layout / containers**: `Stack`, `Card`, `InteractiveCard`, `Form`
|
|
249
|
+
- **Buttons / nav**: `Button`, `IconButton`, `Anchor`, `Breadcrumb`, `Pagination`
|
|
250
|
+
- **Display**: `Badge`, `Heading`, `Avatar`, `Code`, `Icon`, `Alert`, `Spinner`, `Progress`, `Skeleton`, `Separator`, `Tabs`, `Accordion`, `Table`, `BaselineStatus`, `ScrollLinked`
|
|
251
|
+
- **Overlays (self-contained widgets)**: `Modal`, `Dialog`, `Drawer`, `Popover`, `Tooltip`, `DropdownMenu`, `Toast`
|
|
252
|
+
- **Form**: `TextField`, `Textarea`, `PasswordInput`, `NumberField`, `Slider`, `Checkbox`, `Switch`, `Select`, `Radio`, `RadioCard`, `CheckboxCard`, `ListBox`, `CheckboxGroup`, `Autocomplete`, `FileField`, `FormControl`
|
|
253
|
+
|
|
254
|
+
Overlays are exposed as **self-contained widgets**: a `Modal`/`Dialog`/`Drawer`/`Popover` declares its own trigger button via `triggerLabel`, manages open/close internally, and renders the supplied children inside the surface. This lets a model generate UIs that include overlays without modelling imperative open/close state. `Tooltip`/`DropdownMenu`/`Toast` follow the same self-contained pattern (trigger + content).
|
|
255
|
+
|
|
256
|
+
### json-render (RSC-ready)
|
|
257
|
+
|
|
258
|
+
The catalog (schemas / prompt) and the registry (rendering) are split so the catalog is **server-safe** — you can generate the system prompt in a React Server Component, and render on the client.
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
// Server Component: prompt generation
|
|
262
|
+
import { catalog } from '@k8o/arte-odyssey/json-render';
|
|
263
|
+
|
|
264
|
+
const systemPrompt = catalog.prompt(); // safe on the server
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
// Client Component: rendering
|
|
269
|
+
'use client';
|
|
270
|
+
import { registry } from '@k8o/arte-odyssey/json-render/registry';
|
|
271
|
+
import { JSONUIProvider, Renderer } from '@json-render/react';
|
|
272
|
+
|
|
273
|
+
export function GenUi({ spec }: { spec: unknown }) {
|
|
274
|
+
return (
|
|
275
|
+
<JSONUIProvider registry={registry}>
|
|
276
|
+
<Renderer registry={registry} spec={spec} />
|
|
277
|
+
</JSONUIProvider>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
| Export | Side | Contents |
|
|
283
|
+
| ---------------------------------------- | -------------- | -------------------------------- |
|
|
284
|
+
| `@k8o/arte-odyssey/json-render` | server-safe | `catalog` (schemas + `prompt()`) |
|
|
285
|
+
| `@k8o/arte-odyssey/json-render/registry` | `'use client'` | `registry` (rendering) |
|
|
286
|
+
|
|
287
|
+
### OpenUI
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
'use client';
|
|
291
|
+
import { library } from '@k8o/arte-odyssey/openui';
|
|
292
|
+
import { Renderer } from '@openuidev/react-lang';
|
|
293
|
+
|
|
294
|
+
export function GenUi({ response }: { response: string }) {
|
|
295
|
+
return <Renderer library={library} response={response} />;
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Generate the system prompt at build time with the OpenUI CLI, or call `library.prompt()` in the same client bundle.
|
|
300
|
+
|
|
301
|
+
> **Notes**
|
|
302
|
+
>
|
|
303
|
+
> - Make sure `@k8o/arte-odyssey/styles.css` is loaded and the app is wrapped in `ArteOdysseyProvider`.
|
|
304
|
+
> - `Tabs` panels are text content (`tabs: [{ label, content }]`); rich-component panels are a future enhancement.
|
|
305
|
+
> - In OpenUI, `Card` can contain a `Stack`, but `Stack` cannot nest another `Stack` (the framework does not support self-referential schemas). json-render nests freely (slots-based).
|
|
306
|
+
|
|
223
307
|
## Custom Hooks
|
|
224
308
|
|
|
225
309
|
The library includes several useful hooks:
|
|
226
310
|
|
|
311
|
+
- **useBreakpoint** - Tailwind breakpoint matcher
|
|
227
312
|
- **useClickAway** - Detect clicks outside an element
|
|
228
313
|
- **useClient** - Client-side rendering detection
|
|
229
314
|
- **useClipboard** - Clipboard operations
|
|
315
|
+
- **useControllableState** - Controlled/uncontrolled state pattern
|
|
316
|
+
- **useDebouncedTransition** - Rate-limited transition with `AbortSignal`
|
|
317
|
+
- **useDeferredDebounce** - `useDeferredValue` with pending flag
|
|
318
|
+
- **useDisclosure** - Open/close/toggle disclosure state
|
|
230
319
|
- **useHash** - URL hash management
|
|
320
|
+
- **useHover** - Element hover detection
|
|
321
|
+
- **useIntersectionObserver** / **useInView** - Element visibility
|
|
231
322
|
- **useInterval** - Interval timer management
|
|
232
|
-
- **useLocalStorage** -
|
|
233
|
-
- **useResize** - Element resize detection
|
|
323
|
+
- **useLocalStorage** / **useSessionStorage** - Web Storage with React state
|
|
324
|
+
- **useResize** - Element resize detection (ResizeObserver)
|
|
234
325
|
- **useScrollDirection** - Scroll direction detection
|
|
326
|
+
- **useScrollLock** - Body/element scroll lock
|
|
235
327
|
- **useStep** - Step-based state management
|
|
236
328
|
- **useTimeout** - Timeout management
|
|
237
329
|
- **useWindowResize** - Window resize events
|
|
238
330
|
- **useWindowSize** - Window size tracking
|
|
331
|
+
- **useWritingMode** - Detect horizontal/vertical `writing-mode`
|
|
239
332
|
|
|
240
333
|
## Accessibility
|
|
241
334
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/components/_internal/focus-ring.d.ts
|
|
2
|
+
declare const FOCUS_RING = "focus-visible:border-transparent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info";
|
|
3
|
+
declare const FOCUS_RING_NO_BORDER = "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info";
|
|
4
|
+
declare const FOCUS_RING_WITHIN = "focus-within:border-transparent focus-within:outline-hidden focus-within:ring-2 focus-within:ring-border-info";
|
|
5
|
+
declare const FOCUS_RING_PEER = "peer-focus-visible:border-transparent peer-focus-visible:outline-hidden peer-focus-visible:ring-2 peer-focus-visible:ring-border-info";
|
|
6
|
+
declare const FOCUS_RING_PEER_NO_BORDER = "peer-focus-visible:outline-hidden peer-focus-visible:ring-2 peer-focus-visible:ring-border-info";
|
|
7
|
+
//#endregion
|
|
8
|
+
export { FOCUS_RING, FOCUS_RING_NO_BORDER, FOCUS_RING_PEER, FOCUS_RING_PEER_NO_BORDER, FOCUS_RING_WITHIN };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/components/_internal/focus-ring.ts
|
|
2
|
+
const FOCUS_RING = "focus-visible:border-transparent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info";
|
|
3
|
+
const FOCUS_RING_NO_BORDER = "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info";
|
|
4
|
+
const FOCUS_RING_WITHIN = "focus-within:border-transparent focus-within:outline-hidden focus-within:ring-2 focus-within:ring-border-info";
|
|
5
|
+
const FOCUS_RING_PEER = "peer-focus-visible:border-transparent peer-focus-visible:outline-hidden peer-focus-visible:ring-2 peer-focus-visible:ring-border-info";
|
|
6
|
+
const FOCUS_RING_PEER_NO_BORDER = "peer-focus-visible:outline-hidden peer-focus-visible:ring-2 peer-focus-visible:ring-border-info";
|
|
7
|
+
//#endregion
|
|
8
|
+
export { FOCUS_RING, FOCUS_RING_NO_BORDER, FOCUS_RING_PEER, FOCUS_RING_PEER_NO_BORDER, FOCUS_RING_WITHIN };
|
|
@@ -5,17 +5,24 @@ type Props = {
|
|
|
5
5
|
type?: 'button' | 'submit';
|
|
6
6
|
size?: 'sm' | 'md' | 'lg';
|
|
7
7
|
color?: 'primary' | 'secondary' | 'gray';
|
|
8
|
-
variant?: '
|
|
8
|
+
variant?: 'solid' | 'outline' | 'skeleton';
|
|
9
9
|
fullWidth?: boolean;
|
|
10
10
|
isActive?: boolean;
|
|
11
11
|
startIcon?: ReactNode;
|
|
12
12
|
endIcon?: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* クリック時の処理。`onAction` は非同期処理を `useTransition` で包み、保留中は
|
|
15
|
+
* 自動でスピナーを表示する糖衣。素のクリックイベント(`event` が必要、
|
|
16
|
+
* `preventDefault` したい等)は `onClick` を使う。両者は併用可能で、
|
|
17
|
+
* `onClick` → `onAction` の順に実行される(`onClick` が `preventDefault`
|
|
18
|
+
* した場合は `onAction` をスキップ)。
|
|
19
|
+
*/
|
|
13
20
|
onAction?: () => void | Promise<void>;
|
|
14
21
|
renderItem?: (props: {
|
|
15
22
|
className: string;
|
|
16
23
|
children: ReactNode;
|
|
17
24
|
}) => ReactNode;
|
|
18
|
-
} & Omit<HTMLProps<HTMLButtonElement>, 'size' | 'type'>;
|
|
25
|
+
} & Omit<HTMLProps<HTMLButtonElement>, 'size' | 'type' | 'className' | 'style'>;
|
|
19
26
|
declare const Button: FC<Props>;
|
|
20
27
|
//#endregion
|
|
21
28
|
export { Button };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { FOCUS_RING } from "../../_internal/focus-ring.mjs";
|
|
2
3
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
4
|
import { Spinner } from "../../feedback/spinner/spinner.mjs";
|
|
4
5
|
import { useTransition } from "react";
|
|
5
6
|
import { useFormStatus } from "react-dom";
|
|
6
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
//#region src/components/buttons/button/button.tsx
|
|
8
|
-
const Button = ({ ref, children, type = "button", size = "md", color = "primary", variant = "
|
|
9
|
+
const Button = ({ ref, children, type = "button", size = "md", color = "primary", variant = "solid", disabled = false, fullWidth = false, isActive = false, onAction, onClick, startIcon, endIcon, renderItem, ...rest }) => {
|
|
9
10
|
const [transitionPending, startTransition] = useTransition();
|
|
10
11
|
const { pending: formPending } = useFormStatus();
|
|
11
12
|
const isPending = transitionPending || type === "submit" && formPending;
|
|
@@ -24,14 +25,14 @@ const Button = ({ ref, children, type = "button", size = "md", color = "primary"
|
|
|
24
25
|
const hasStartIcon = resolvedStartIcon !== void 0;
|
|
25
26
|
const hasEndIcon = endIcon !== void 0;
|
|
26
27
|
const baseClassName = cn("rounded-full border-2 text-center font-bold transition-colors", {
|
|
27
|
-
"border-transparent bg-primary-bg text-primary-fg hover:bg-primary-bg-emphasize/80 active:bg-primary-bg-emphasize": variant === "
|
|
28
|
-
"border-transparent bg-secondary-bg text-secondary-fg hover:bg-secondary-bg-emphasize/80 active:bg-secondary-bg-emphasize": variant === "
|
|
29
|
-
"border-transparent bg-bg-subtle text-fg-base hover:bg-bg-mute/80 active:bg-bg-mute": variant === "
|
|
30
|
-
"border-primary-border bg-bg-base text-primary-fg hover:bg-bg-subtle active:bg-bg-mute": variant === "
|
|
31
|
-
"border-secondary-border bg-bg-base text-secondary-fg hover:bg-bg-subtle active:bg-bg-mute": variant === "
|
|
32
|
-
"border-border-base bg-bg-base text-fg-base hover:bg-bg-subtle active:bg-bg-mute": variant === "
|
|
28
|
+
"border-transparent bg-primary-bg text-primary-fg hover:bg-primary-bg-emphasize/80 active:bg-primary-bg-emphasize": variant === "solid" && color === "primary",
|
|
29
|
+
"border-transparent bg-secondary-bg text-secondary-fg hover:bg-secondary-bg-emphasize/80 active:bg-secondary-bg-emphasize": variant === "solid" && color === "secondary",
|
|
30
|
+
"border-transparent bg-bg-subtle text-fg-base hover:bg-bg-mute/80 active:bg-bg-mute": variant === "solid" && color === "gray",
|
|
31
|
+
"border-primary-border bg-bg-base text-primary-fg hover:bg-bg-subtle active:bg-bg-mute": variant === "outline" && color === "primary",
|
|
32
|
+
"border-secondary-border bg-bg-base text-secondary-fg hover:bg-bg-subtle active:bg-bg-mute": variant === "outline" && color === "secondary",
|
|
33
|
+
"border-border-base bg-bg-base text-fg-base hover:bg-bg-subtle active:bg-bg-mute": variant === "outline" && color === "gray",
|
|
33
34
|
"border-transparent bg-transparent text-fg-mute hover:bg-bg-subtle hover:text-fg-base active:bg-bg-mute active:text-fg-base": variant === "skeleton"
|
|
34
|
-
},
|
|
35
|
+
}, FOCUS_RING, size === "sm" && "px-3 py-1 text-sm", size === "md" && "px-4 py-2 text-md", size === "lg" && "px-6 py-3 text-lg", fullWidth && "w-full vertical:w-auto", (hasStartIcon || hasEndIcon) && "flex items-center gap-2", hasStartIcon && hasEndIcon ? "justify-between" : hasStartIcon && variant !== "skeleton" ? "justify-center" : hasEndIcon && "justify-between", isActive && "text-fg-info");
|
|
35
36
|
const composedChildren = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
36
37
|
resolvedStartIcon,
|
|
37
38
|
children,
|
|
@@ -44,10 +45,10 @@ const Button = ({ ref, children, type = "button", size = "md", color = "primary"
|
|
|
44
45
|
return /* @__PURE__ */ jsx("button", {
|
|
45
46
|
"aria-busy": isPending || void 0,
|
|
46
47
|
className: cn(baseClassName, "cursor-pointer", {
|
|
47
|
-
"cursor-not-allowed opacity-35 hover:bg-primary-bg active:bg-primary-bg": isDisabled && variant === "
|
|
48
|
-
"cursor-not-allowed opacity-35 hover:bg-secondary-bg active:bg-secondary-bg": isDisabled && variant === "
|
|
49
|
-
"cursor-not-allowed opacity-35 hover:bg-bg-subtle active:bg-bg-subtle": isDisabled && variant === "
|
|
50
|
-
"cursor-not-allowed bg-bg-base opacity-35": isDisabled && variant === "
|
|
48
|
+
"cursor-not-allowed opacity-35 hover:bg-primary-bg active:bg-primary-bg": isDisabled && variant === "solid" && color === "primary",
|
|
49
|
+
"cursor-not-allowed opacity-35 hover:bg-secondary-bg active:bg-secondary-bg": isDisabled && variant === "solid" && color === "secondary",
|
|
50
|
+
"cursor-not-allowed opacity-35 hover:bg-bg-subtle active:bg-bg-subtle": isDisabled && variant === "solid" && color === "gray",
|
|
51
|
+
"cursor-not-allowed bg-bg-base opacity-35": isDisabled && variant === "outline",
|
|
51
52
|
"cursor-not-allowed bg-transparent text-fg-mute opacity-35": isDisabled && variant === "skeleton"
|
|
52
53
|
}),
|
|
53
54
|
disabled: isDisabled,
|
|
@@ -6,10 +6,16 @@ import { Placement } from "@floating-ui/react";
|
|
|
6
6
|
type IconButtonTriggerProps = Partial<TooltipTriggerProps>;
|
|
7
7
|
type Props = {
|
|
8
8
|
size?: 'sm' | 'md' | 'lg';
|
|
9
|
-
|
|
9
|
+
color?: 'transparent' | 'base' | 'primary' | 'secondary';
|
|
10
10
|
label: string;
|
|
11
11
|
tooltipPlacement?: Placement;
|
|
12
12
|
tooltipDisabled?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* クリック時の処理。`onAction` は非同期処理を `useTransition` で包み、保留中は
|
|
15
|
+
* `aria-busy` を立てる糖衣。素のクリックイベントが必要なら `onClick` を使う。
|
|
16
|
+
* 両者は併用可能で `onClick` → `onAction` の順に実行される(`onClick` が
|
|
17
|
+
* `preventDefault` した場合は `onAction` をスキップ)。
|
|
18
|
+
*/
|
|
13
19
|
onAction?: () => void | Promise<void>;
|
|
14
20
|
renderItem?: (props: {
|
|
15
21
|
className: string;
|
|
@@ -17,7 +23,7 @@ type Props = {
|
|
|
17
23
|
'aria-label': string;
|
|
18
24
|
triggerProps: IconButtonTriggerProps;
|
|
19
25
|
}) => ReactNode;
|
|
20
|
-
} & Omit<HTMLProps<HTMLButtonElement>, 'size' | 'type'>;
|
|
26
|
+
} & Omit<HTMLProps<HTMLButtonElement>, 'size' | 'type' | 'className' | 'style'>;
|
|
21
27
|
declare const IconButton: FC<Props>;
|
|
22
28
|
//#endregion
|
|
23
29
|
export { IconButton, IconButtonTriggerProps };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { FOCUS_RING } from "../../_internal/focus-ring.mjs";
|
|
2
3
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
4
|
import { Tooltip } from "../../overlays/tooltip/tooltip.mjs";
|
|
4
5
|
import { chain } from "../../../helpers/chain.mjs";
|
|
@@ -11,7 +12,7 @@ const joinIds = (...ids) => {
|
|
|
11
12
|
const filtered = ids.filter(Boolean);
|
|
12
13
|
return filtered.length === 0 ? void 0 : filtered.join(" ");
|
|
13
14
|
};
|
|
14
|
-
const IconButton = ({ ref, size = "md",
|
|
15
|
+
const IconButton = ({ ref, size = "md", color = "transparent", label, tooltipPlacement = "top", tooltipDisabled = false, children, onAction, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, disabled, renderItem, "aria-describedby": describedBy, ...props }) => {
|
|
15
16
|
const [transitionPending, startTransition] = useTransition();
|
|
16
17
|
const { pending: formPending } = useFormStatus();
|
|
17
18
|
const isPending = transitionPending || formPending;
|
|
@@ -23,7 +24,7 @@ const IconButton = ({ ref, size = "md", bg = "transparent", label, tooltipPlacem
|
|
|
23
24
|
await onAction();
|
|
24
25
|
});
|
|
25
26
|
} : void 0;
|
|
26
|
-
const className = cn("inline-flex rounded-full transition-colors",
|
|
27
|
+
const className = cn("inline-flex rounded-full transition-colors", FOCUS_RING, (color === "transparent" || color === "base") && "hover:bg-bg-subtle active:bg-bg-mute", color === "base" && "bg-bg-base", color === "transparent" && "bg-transparent", color === "primary" && "bg-primary-bg hover:bg-primary-bg-emphasize/80 active:bg-primary-bg-emphasize", color === "secondary" && "bg-secondary-bg hover:bg-secondary-bg-emphasize/80 active:bg-secondary-bg-emphasize", size === "sm" && "p-1", size === "md" && "p-2", size === "lg" && "p-3", !renderItem && "cursor-pointer", !renderItem && isDisabled && "cursor-not-allowed opacity-50 hover:bg-transparent active:bg-transparent");
|
|
27
28
|
if (tooltipDisabled) {
|
|
28
29
|
if (renderItem) return /* @__PURE__ */ jsx(Fragment$1, { children: renderItem({
|
|
29
30
|
className,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { FOCUS_RING_NO_BORDER } from "../../_internal/focus-ring.mjs";
|
|
2
3
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
4
|
import { ChevronIcon } from "../../icons/lucide.mjs";
|
|
4
5
|
import { useItemId, useOpen, useToggleOpen } from "./context.mjs";
|
|
@@ -11,12 +12,12 @@ const AccordionButton = ({ children }) => {
|
|
|
11
12
|
return /* @__PURE__ */ jsxs("button", {
|
|
12
13
|
"aria-controls": `${id}-panel`,
|
|
13
14
|
"aria-expanded": open,
|
|
14
|
-
className: cn("flex w-full cursor-pointer items-center justify-between rounded-md p-4 text-fg-base transition-colors", "hover:bg-primary-bg-subtle hover:text-primary-fg",
|
|
15
|
+
className: cn("flex w-full cursor-pointer items-center justify-between rounded-md p-4 text-fg-base transition-colors vertical:h-full", "hover:bg-primary-bg-subtle hover:text-primary-fg", FOCUS_RING_NO_BORDER),
|
|
15
16
|
id: `${id}-button`,
|
|
16
17
|
onClick: toggleOpen,
|
|
17
18
|
type: "button",
|
|
18
19
|
children: [children, /* @__PURE__ */ jsx("span", {
|
|
19
|
-
className: cn("transition-transform duration-150", open && "rotate-180"),
|
|
20
|
+
className: cn("transition-transform duration-150", !open && "vertical:rotate-90", open && "rotate-180 vertical:-rotate-90"),
|
|
20
21
|
children: /* @__PURE__ */ jsx(ChevronIcon, { direction: "down" })
|
|
21
22
|
})]
|
|
22
23
|
});
|
|
@@ -2,7 +2,9 @@ import { FC, PropsWithChildren } from "react";
|
|
|
2
2
|
|
|
3
3
|
//#region src/components/data-display/accordion/accordion-item.d.ts
|
|
4
4
|
declare const AccordionItem: FC<PropsWithChildren<{
|
|
5
|
+
isOpen?: boolean;
|
|
5
6
|
defaultOpen?: boolean;
|
|
7
|
+
onChange?: (isOpen: boolean) => void;
|
|
6
8
|
}>>;
|
|
7
9
|
//#endregion
|
|
8
10
|
export { AccordionItem };
|
|
@@ -3,11 +3,16 @@ import { AccordionItemProvider } from "./context.mjs";
|
|
|
3
3
|
import { useId } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/data-display/accordion/accordion-item.tsx
|
|
6
|
-
const AccordionItem = ({ children, defaultOpen = false }) => {
|
|
6
|
+
const AccordionItem = ({ children, isOpen, defaultOpen = false, onChange }) => {
|
|
7
7
|
return /* @__PURE__ */ jsx(AccordionItemProvider, {
|
|
8
8
|
defaultOpen,
|
|
9
9
|
id: useId(),
|
|
10
|
-
|
|
10
|
+
isOpen,
|
|
11
|
+
onChange,
|
|
12
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
13
|
+
className: "vertical:h-full",
|
|
14
|
+
children
|
|
15
|
+
})
|
|
11
16
|
});
|
|
12
17
|
};
|
|
13
18
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
//#region src/components/data-display/accordion/accordion.tsx
|
|
3
3
|
const Accordion = ({ children }) => /* @__PURE__ */ jsx("div", {
|
|
4
|
-
className: "divide-border-mute divide-y",
|
|
4
|
+
className: "divide-border-mute vertical:flex vertical:h-full vertical:flex-col vertical:divide-y-0 vertical:[&>:not(:last-child)]:border-l vertical:[&>:not(:last-child)]:border-border-mute divide-y",
|
|
5
5
|
children
|
|
6
6
|
});
|
|
7
7
|
//#endregion
|
|
@@ -6,7 +6,9 @@ declare const useToggleOpen: () => ToggleOpen;
|
|
|
6
6
|
declare const useItemId: () => string;
|
|
7
7
|
declare const useOpen: () => boolean;
|
|
8
8
|
declare const AccordionItemProvider: FC<PropsWithChildren<{
|
|
9
|
+
isOpen?: boolean;
|
|
9
10
|
defaultOpen?: boolean;
|
|
11
|
+
onChange?: (isOpen: boolean) => void;
|
|
10
12
|
id: string;
|
|
11
13
|
}>>;
|
|
12
14
|
//#endregion
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useDisclosure } from "../../../hooks/disclosure/index.mjs";
|
|
3
2
|
import { createSafeContext } from "../../../helpers/create-safe-context.mjs";
|
|
4
|
-
import {
|
|
3
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
4
|
+
import { createContext, use, useCallback } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/data-display/accordion/context.tsx
|
|
7
7
|
const OpenContext = createContext(false);
|
|
8
8
|
const [ToggleOpenContext, useToggleOpen] = createSafeContext("useToggleOpen must be used within AccordionProvider");
|
|
9
9
|
const [ItemIdContext, useItemId] = createSafeContext("useItemId must be used within AccordionProvider");
|
|
10
10
|
const useOpen = () => use(OpenContext);
|
|
11
|
-
const AccordionItemProvider = ({ defaultOpen = false, id, children }) => {
|
|
12
|
-
const
|
|
13
|
-
return /* @__PURE__ */ jsx(OpenContext, {
|
|
11
|
+
const AccordionItemProvider = ({ isOpen, defaultOpen = false, onChange, id, children }) => {
|
|
12
|
+
const [open, setOpen] = useControllableState({
|
|
14
13
|
value: isOpen,
|
|
14
|
+
defaultValue: defaultOpen,
|
|
15
|
+
onChange
|
|
16
|
+
});
|
|
17
|
+
return /* @__PURE__ */ jsx(OpenContext, {
|
|
18
|
+
value: open,
|
|
15
19
|
children: /* @__PURE__ */ jsx(ToggleOpenContext, {
|
|
16
|
-
value:
|
|
20
|
+
value: useCallback(() => {
|
|
21
|
+
setOpen((prev) => !prev);
|
|
22
|
+
}, [setOpen]),
|
|
17
23
|
children: /* @__PURE__ */ jsx(ItemIdContext, {
|
|
18
24
|
value: id,
|
|
19
25
|
children
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import * as _$react from "react";
|
|
2
|
-
|
|
3
1
|
//#region src/components/data-display/accordion/index.d.ts
|
|
4
2
|
declare const Accordion: {
|
|
5
|
-
readonly Root:
|
|
6
|
-
children?:
|
|
3
|
+
readonly Root: import("react").FC<{
|
|
4
|
+
children?: import("react").ReactNode | undefined;
|
|
7
5
|
}>;
|
|
8
|
-
readonly Button:
|
|
9
|
-
children?:
|
|
6
|
+
readonly Button: import("react").FC<{
|
|
7
|
+
children?: import("react").ReactNode | undefined;
|
|
10
8
|
}>;
|
|
11
|
-
readonly Item:
|
|
9
|
+
readonly Item: import("react").FC<import("react").PropsWithChildren<{
|
|
10
|
+
isOpen?: boolean;
|
|
12
11
|
defaultOpen?: boolean;
|
|
12
|
+
onChange?: (isOpen: boolean) => void;
|
|
13
13
|
}>>;
|
|
14
|
-
readonly Panel:
|
|
15
|
-
children?:
|
|
14
|
+
readonly Panel: import("react").FC<{
|
|
15
|
+
children?: import("react").ReactNode | undefined;
|
|
16
16
|
}>;
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
@@ -7,7 +7,7 @@ type Props = {
|
|
|
7
7
|
name?: string;
|
|
8
8
|
size?: 'sm' | 'md' | 'lg';
|
|
9
9
|
src?: string;
|
|
10
|
-
} & Omit<HTMLAttributes<HTMLSpanElement>, 'role' | 'aria-label'>;
|
|
10
|
+
} & Omit<HTMLAttributes<HTMLSpanElement>, 'role' | 'aria-label' | 'className' | 'style'>;
|
|
11
11
|
declare const Avatar: FC<Props>;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { Avatar };
|
|
@@ -5,10 +5,10 @@ import { jsx } from "react/jsx-runtime";
|
|
|
5
5
|
//#region src/components/data-display/avatar/avatar.tsx
|
|
6
6
|
const getInitials = (name) => {
|
|
7
7
|
if (name === void 0 || name === "") return "?";
|
|
8
|
-
const initials = name.trim().split(/\s+/).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
8
|
+
const initials = name.trim().split(/\s+/u).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
9
9
|
return initials === "" ? "?" : initials;
|
|
10
10
|
};
|
|
11
|
-
const Avatar = ({ alt, fallback, name, size = "md", src,
|
|
11
|
+
const Avatar = ({ alt, fallback, name, size = "md", src, ...rest }) => {
|
|
12
12
|
const [failedSrc, setFailedSrc] = useState(null);
|
|
13
13
|
const showImage = Boolean(src) && failedSrc !== src;
|
|
14
14
|
const label = alt ?? name ?? "Avatar";
|
|
@@ -16,7 +16,7 @@ const Avatar = ({ alt, fallback, name, size = "md", src, className, ...rest }) =
|
|
|
16
16
|
return /* @__PURE__ */ jsx("span", {
|
|
17
17
|
...rest,
|
|
18
18
|
"aria-label": label,
|
|
19
|
-
className: cn("inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-border-base bg-bg-mute font-medium text-fg-base", size === "sm" && "size-8 text-xs", size === "md" && "size-10 text-sm", size === "lg" && "size-14 text-lg"
|
|
19
|
+
className: cn("inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-border-base bg-bg-mute font-medium text-fg-base", size === "sm" && "size-8 text-xs", size === "md" && "size-10 text-sm", size === "lg" && "size-14 text-lg"),
|
|
20
20
|
role: "img",
|
|
21
21
|
children: showImage ? /* @__PURE__ */ jsx("img", {
|
|
22
22
|
alt: alt ?? "",
|
|
@@ -3,11 +3,11 @@ import { FC, HTMLAttributes } from "react";
|
|
|
3
3
|
//#region src/components/data-display/badge/badge.d.ts
|
|
4
4
|
type Props = {
|
|
5
5
|
text: string;
|
|
6
|
-
size?: 'sm' | 'md';
|
|
6
|
+
size?: 'sm' | 'md' | 'lg';
|
|
7
7
|
interactive?: boolean;
|
|
8
8
|
tone?: 'neutral' | 'info' | 'success' | 'warning' | 'error';
|
|
9
9
|
variant?: 'solid' | 'outline';
|
|
10
|
-
} & Omit<HTMLAttributes<HTMLElement>, 'children'>;
|
|
10
|
+
} & Omit<HTMLAttributes<HTMLElement>, 'children' | 'className' | 'style'>;
|
|
11
11
|
declare const Badge: FC<Props>;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { Badge };
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
import "../../_internal/focus-ring.mjs";
|
|
1
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
2
3
|
import { jsx } from "react/jsx-runtime";
|
|
3
4
|
//#region src/components/data-display/badge/badge.tsx
|
|
4
|
-
const Badge = ({ interactive = false, size = "md", text, tone = "neutral", variant = "solid",
|
|
5
|
-
const interactiveClassName = cn(interactive &&
|
|
6
|
-
const badgeClassName = cn("inline-flex items-center rounded-full border font-medium transition-colors", size === "sm" && "px-2 py-0.5 text-xs", size === "md" && "px-2.5 py-1 text-xs", tone === "neutral" && variant === "solid" && "border-border-mute bg-bg-mute text-fg-base", tone === "neutral" && variant === "outline" && "border-border-base bg-bg-base text-fg-base", tone === "info" && variant === "solid" && "border-border-info bg-bg-info text-fg-info", tone === "info" && variant === "outline" && "border-border-info bg-bg-base text-fg-info", tone === "success" && variant === "solid" && "border-border-success bg-bg-success text-fg-success", tone === "success" && variant === "outline" && "border-border-success bg-bg-base text-fg-success", tone === "warning" && variant === "solid" && "border-border-warning bg-bg-warning text-fg-warning", tone === "warning" && variant === "outline" && "border-border-warning bg-bg-base text-fg-warning", tone === "error" && variant === "solid" && "border-border-error bg-bg-error text-fg-error", tone === "error" && variant === "outline" && "border-border-error bg-bg-base text-fg-error", interactiveClassName);
|
|
5
|
+
const Badge = ({ interactive = false, size = "md", text, tone = "neutral", variant = "solid", ...rest }) => {
|
|
6
|
+
const interactiveClassName = cn(interactive && `cursor-pointer focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info`, interactive && tone === "neutral" && variant === "solid" && "hover:bg-bg-emphasize active:bg-bg-base", interactive && tone === "neutral" && variant === "outline" && "hover:bg-bg-subtle active:bg-bg-mute", interactive && tone === "info" && variant === "solid" && "hover:bg-bg-info/80 active:bg-bg-info/60", interactive && tone === "info" && variant === "outline" && "hover:bg-bg-info active:bg-bg-info/80", interactive && tone === "success" && variant === "solid" && "hover:bg-bg-success/80 active:bg-bg-success/60", interactive && tone === "success" && variant === "outline" && "hover:bg-bg-success active:bg-bg-success/80", interactive && tone === "warning" && variant === "solid" && "hover:bg-bg-warning/80 active:bg-bg-warning/60", interactive && tone === "warning" && variant === "outline" && "hover:bg-bg-warning active:bg-bg-warning/80", interactive && tone === "error" && variant === "solid" && "hover:bg-bg-error/80 active:bg-bg-error/60", interactive && tone === "error" && variant === "outline" && "hover:bg-bg-error active:bg-bg-error/80");
|
|
7
|
+
const badgeClassName = cn("inline-flex items-center rounded-full border font-medium transition-colors", size === "sm" && "px-2 py-0.5 text-xs", size === "md" && "px-2.5 py-1 text-xs", size === "lg" && "px-3 py-1.5 text-sm", tone === "neutral" && variant === "solid" && "border-border-mute bg-bg-mute text-fg-base", tone === "neutral" && variant === "outline" && "border-border-base bg-bg-base text-fg-base", tone === "info" && variant === "solid" && "border-border-info bg-bg-info text-fg-info", tone === "info" && variant === "outline" && "border-border-info bg-bg-base text-fg-info", tone === "success" && variant === "solid" && "border-border-success bg-bg-success text-fg-success", tone === "success" && variant === "outline" && "border-border-success bg-bg-base text-fg-success", tone === "warning" && variant === "solid" && "border-border-warning bg-bg-warning text-fg-warning", tone === "warning" && variant === "outline" && "border-border-warning bg-bg-base text-fg-warning", tone === "error" && variant === "solid" && "border-border-error bg-bg-error text-fg-error", tone === "error" && variant === "outline" && "border-border-error bg-bg-base text-fg-error", interactiveClassName);
|
|
7
8
|
if (interactive) return /* @__PURE__ */ jsx("button", {
|
|
8
9
|
...rest,
|
|
9
|
-
className:
|
|
10
|
+
className: badgeClassName,
|
|
10
11
|
type: "button",
|
|
11
12
|
children: text
|
|
12
13
|
});
|
|
13
14
|
return /* @__PURE__ */ jsx("span", {
|
|
14
15
|
...rest,
|
|
15
|
-
className:
|
|
16
|
+
className: badgeClassName,
|
|
16
17
|
children: text
|
|
17
18
|
});
|
|
18
19
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { cn } from "../../../helpers/cn.mjs";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/data-display/card/card.tsx
|
|
4
|
-
const Card = ({ children, width = "full", appearance = "shadow",
|
|
4
|
+
const Card = ({ children, width = "full", appearance = "shadow", ...rest }) => /* @__PURE__ */ jsx("div", {
|
|
5
5
|
...rest,
|
|
6
|
-
className: cn("rounded-xl", appearance === "shadow" && "shadow-sm", appearance === "bordered" && "border border-border-mute", width === "full" && "w-full", width === "fit" && "w-fit", "bg-bg-base"
|
|
6
|
+
className: cn("rounded-xl", appearance === "shadow" && "shadow-sm border border-transparent dark:border-border-subtle", appearance === "bordered" && "border border-border-mute", width === "full" && "w-full", width === "fit" && "w-fit", "bg-bg-base"),
|
|
7
7
|
children
|
|
8
8
|
});
|
|
9
9
|
//#endregion
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { cn } from "../../../helpers/cn.mjs";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/data-display/card/interactive-card.tsx
|
|
4
|
-
const InteractiveCard = ({ children, width = "full", appearance = "shadow",
|
|
4
|
+
const InteractiveCard = ({ children, width = "full", appearance = "shadow", ...rest }) => /* @__PURE__ */ jsx("div", {
|
|
5
5
|
...rest,
|
|
6
|
-
className: cn("rounded-xl transition-transform hover:scale-[1.02] active:scale-[0.98]", appearance === "shadow" && "shadow-sm", appearance === "bordered" && "border border-border-mute", width === "full" && "w-full", width === "fit" && "w-fit", "bg-bg-base"
|
|
6
|
+
className: cn("rounded-xl transition-transform hover:scale-[1.02] active:scale-[0.98]", appearance === "shadow" && "shadow-sm", appearance === "bordered" && "border border-border-mute", width === "full" && "w-full", width === "fit" && "w-fit", "bg-bg-base"),
|
|
7
7
|
children
|
|
8
8
|
});
|
|
9
9
|
//#endregion
|