@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.
Files changed (138) hide show
  1. package/README.md +121 -28
  2. package/dist/components/_internal/focus-ring.d.mts +8 -0
  3. package/dist/components/_internal/focus-ring.mjs +8 -0
  4. package/dist/components/buttons/button/button.d.mts +9 -2
  5. package/dist/components/buttons/button/button.mjs +13 -12
  6. package/dist/components/buttons/icon-button/icon-button.d.mts +8 -2
  7. package/dist/components/buttons/icon-button/icon-button.mjs +3 -2
  8. package/dist/components/data-display/accordion/accordion-button.mjs +3 -2
  9. package/dist/components/data-display/accordion/accordion-item.d.mts +2 -0
  10. package/dist/components/data-display/accordion/accordion-item.mjs +7 -2
  11. package/dist/components/data-display/accordion/accordion.mjs +1 -1
  12. package/dist/components/data-display/accordion/context.d.mts +2 -0
  13. package/dist/components/data-display/accordion/context.mjs +12 -6
  14. package/dist/components/data-display/accordion/index.d.mts +9 -9
  15. package/dist/components/data-display/avatar/avatar.d.mts +1 -1
  16. package/dist/components/data-display/avatar/avatar.mjs +3 -3
  17. package/dist/components/data-display/badge/badge.d.mts +2 -2
  18. package/dist/components/data-display/badge/badge.mjs +6 -5
  19. package/dist/components/data-display/card/card.mjs +2 -2
  20. package/dist/components/data-display/card/interactive-card.mjs +2 -2
  21. package/dist/components/data-display/card/type.d.mts +1 -1
  22. package/dist/components/data-display/code/code.d.mts +1 -1
  23. package/dist/components/data-display/code/code.mjs +3 -4
  24. package/dist/components/data-display/code/find-all-colors.mjs +3 -3
  25. package/dist/components/data-display/heading/heading.d.mts +1 -1
  26. package/dist/components/data-display/heading/heading.mjs +7 -7
  27. package/dist/components/data-display/table/table.d.mts +12 -17
  28. package/dist/components/data-display/table/table.mjs +23 -21
  29. package/dist/components/feedback/alert/alert.d.mts +2 -2
  30. package/dist/components/feedback/alert/alert.mjs +6 -6
  31. package/dist/components/feedback/progress/progress.d.mts +1 -1
  32. package/dist/components/feedback/progress/progress.mjs +5 -6
  33. package/dist/components/feedback/skeleton/skeleton.d.mts +1 -1
  34. package/dist/components/feedback/skeleton/skeleton.mjs +2 -2
  35. package/dist/components/feedback/spinner/spinner.d.mts +1 -1
  36. package/dist/components/feedback/spinner/spinner.mjs +2 -2
  37. package/dist/components/feedback/toast/context.d.mts +3 -4
  38. package/dist/components/feedback/toast/context.mjs +3 -4
  39. package/dist/components/feedback/toast/provider.mjs +2 -2
  40. package/dist/components/feedback/toast/toast.d.mts +1 -1
  41. package/dist/components/feedback/toast/toast.mjs +2 -2
  42. package/dist/components/form/autocomplete/autocomplete.d.mts +1 -1
  43. package/dist/components/form/autocomplete/autocomplete.mjs +67 -39
  44. package/dist/components/form/checkbox/checkbox.d.mts +4 -4
  45. package/dist/components/form/checkbox/checkbox.mjs +5 -4
  46. package/dist/components/form/checkbox-card/checkbox-card.d.mts +1 -1
  47. package/dist/components/form/checkbox-card/checkbox-card.mjs +4 -2
  48. package/dist/components/form/checkbox-group/checkbox-group.d.mts +1 -1
  49. package/dist/components/form/checkbox-group/checkbox-group.mjs +1 -0
  50. package/dist/components/form/checkbox-group/index.d.mts +10 -12
  51. package/dist/components/form/file-field/file-field.d.mts +4 -5
  52. package/dist/components/form/file-field/file-field.mjs +2 -7
  53. package/dist/components/form/form/form.d.mts +1 -1
  54. package/dist/components/form/form/form.mjs +2 -3
  55. package/dist/components/form/number-field/cast.mjs +2 -2
  56. package/dist/components/form/number-field/number-field.d.mts +1 -1
  57. package/dist/components/form/number-field/number-field.mjs +7 -6
  58. package/dist/components/form/password-input/password-input.d.mts +1 -1
  59. package/dist/components/form/password-input/password-input.mjs +4 -3
  60. package/dist/components/form/radio/radio.d.mts +4 -4
  61. package/dist/components/form/radio/radio.mjs +6 -5
  62. package/dist/components/form/radio-card/radio-card.d.mts +4 -4
  63. package/dist/components/form/radio-card/radio-card.mjs +6 -4
  64. package/dist/components/form/select/select.d.mts +1 -1
  65. package/dist/components/form/select/select.mjs +6 -4
  66. package/dist/components/form/slider/slider.d.mts +1 -1
  67. package/dist/components/form/slider/slider.mjs +15 -8
  68. package/dist/components/form/switch/switch.d.mts +4 -4
  69. package/dist/components/form/switch/switch.mjs +4 -3
  70. package/dist/components/form/text-field/text-field.d.mts +1 -1
  71. package/dist/components/form/text-field/text-field.mjs +2 -1
  72. package/dist/components/form/textarea/textarea.d.mts +1 -1
  73. package/dist/components/form/textarea/textarea.mjs +2 -1
  74. package/dist/components/index.d.mts +3 -1
  75. package/dist/components/index.mjs +3 -1
  76. package/dist/components/layout/_shared/gap.d.mts +11 -0
  77. package/dist/components/layout/_shared/gap.mjs +10 -0
  78. package/dist/components/layout/grid/grid.d.mts +16 -0
  79. package/dist/components/layout/grid/grid.mjs +35 -0
  80. package/dist/components/layout/grid/index.d.mts +2 -0
  81. package/dist/components/layout/grid/index.mjs +2 -0
  82. package/dist/components/layout/separator/separator.d.mts +1 -1
  83. package/dist/components/layout/separator/separator.mjs +2 -5
  84. package/dist/components/layout/stack/index.d.mts +2 -0
  85. package/dist/components/layout/stack/index.mjs +2 -0
  86. package/dist/components/layout/stack/stack.d.mts +13 -0
  87. package/dist/components/layout/stack/stack.mjs +23 -0
  88. package/dist/components/navigation/anchor/anchor.d.mts +10 -9
  89. package/dist/components/navigation/anchor/anchor.mjs +4 -3
  90. package/dist/components/navigation/breadcrumb/breadcrumb.d.mts +2 -4
  91. package/dist/components/navigation/breadcrumb/breadcrumb.mjs +4 -4
  92. package/dist/components/navigation/pagination/pagination.mjs +12 -6
  93. package/dist/components/navigation/tabs/tabs.d.mts +2 -0
  94. package/dist/components/navigation/tabs/tabs.mjs +35 -19
  95. package/dist/components/overlays/dialog/dialog.d.mts +1 -2
  96. package/dist/components/overlays/drawer/drawer.d.mts +3 -2
  97. package/dist/components/overlays/drawer/drawer.mjs +7 -4
  98. package/dist/components/overlays/dropdown-menu/dropdown-menu.mjs +4 -4
  99. package/dist/components/overlays/dropdown-menu/hooks.d.mts +153 -154
  100. package/dist/components/overlays/list-box/hooks.d.mts +173 -174
  101. package/dist/components/overlays/list-box/list-box.d.mts +1 -1
  102. package/dist/components/overlays/list-box/list-box.mjs +6 -6
  103. package/dist/components/overlays/modal/modal.mjs +9 -5
  104. package/dist/components/overlays/popover/hooks.d.mts +1 -2
  105. package/dist/components/overlays/popover/popover.mjs +8 -2
  106. package/dist/components/overlays/tooltip/tooltip.d.mts +1 -2
  107. package/dist/hooks/index.d.mts +3 -2
  108. package/dist/hooks/index.mjs +4 -3
  109. package/dist/hooks/writing-mode/index.d.mts +7 -0
  110. package/dist/hooks/writing-mode/index.mjs +22 -0
  111. package/dist/index.d.mts +5 -2
  112. package/dist/index.mjs +21 -18
  113. package/dist/integrations/_shared/renderers.d.mts +74 -0
  114. package/dist/integrations/_shared/renderers.mjs +667 -0
  115. package/dist/integrations/_shared/schemas.d.mts +704 -0
  116. package/dist/integrations/_shared/schemas.mjs +496 -0
  117. package/dist/integrations/json-render/catalog.d.mts +770 -0
  118. package/dist/integrations/json-render/catalog.mjs +229 -0
  119. package/dist/integrations/json-render/registry.d.mts +4 -0
  120. package/dist/integrations/json-render/registry.mjs +137 -0
  121. package/dist/integrations/openui/form-views.d.mts +31 -0
  122. package/dist/integrations/openui/form-views.mjs +75 -0
  123. package/dist/integrations/openui/library.d.mts +4 -0
  124. package/dist/integrations/openui/library.mjs +432 -0
  125. package/dist/styles/base.css +75 -0
  126. package/dist/styles/index.css +12 -463
  127. package/dist/styles/tokens.css +379 -0
  128. package/dist/styles/tokens.d.mts +2 -84
  129. package/dist/styles/tokens.generated.d.mts +839 -0
  130. package/dist/styles/tokens.generated.mjs +812 -0
  131. package/dist/styles/tokens.mjs +2 -752
  132. package/dist/styles/utilities.css +62 -0
  133. package/dist/types/index.d.mts +1 -1
  134. package/docs/GUIDE.md +26 -7
  135. package/docs/references/components.md +40 -21
  136. package/docs/references/hooks.md +17 -0
  137. package/docs/references/typography.md +29 -0
  138. 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 ≥5.9.0
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
- ### Layout & Navigation
79
+ ### Buttons
80
80
 
81
- - **Accordion** - Collapsible content panels
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
- - **Card** / **InteractiveCard** - Flexible content container (with hover interaction)
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** - Binary selection input
94
+ - **Checkbox** / **CheckboxCard** / **CheckboxGroup** - Multi-selection inputs
92
95
  - **FileField** - File upload with composite pattern
93
- - **FormControl** - Form field wrapper with label and validation
96
+ - **Form** / **FormControl** - Form wrapper and field with label/validation
94
97
  - **NumberField** - Numeric input with controls
95
- - **Radio** - Single selection from options
96
- - **Slider** - Slider input control
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
- ### Buttons & Links
106
+ ### Data Display
102
107
 
103
- - **Button** - Primary action button
104
- - **IconButton** - Button with icon only
105
- - **LinkButton** - Button styled as link
106
- - **Anchor** - External link component
107
- - **IconLink** - Link with icon
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 & Status
117
+ ### Feedback
110
118
 
111
119
  - **Alert** - Important messages and notifications
112
- - **Toast** - Temporary notification messages
113
120
  - **Progress** - Progress indication
114
- - **BaselineStatus** - Web standard support indicator
121
+ - **Skeleton** - Content loading placeholder
122
+ - **Spinner** - Loading indicator
123
+ - **ToastProvider** / **useToast** - Temporary notification messages
115
124
 
116
- ### Overlays & Modals
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
- ### Data Display
135
+ ### Layout
126
136
 
127
- - **Code** - Formatted code display
128
- - **Heading** - Typography heading component
129
- - **ListBox** - Selectable list component
137
+ - **ScrollLinked** - Scroll progress indicator
138
+ - **Separator** - Visual content divider
130
139
 
131
140
  ### Utilities
132
141
 
133
- - **ArteOdysseyProvider** - Context providers for the library
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** - Local storage with React state
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?: 'contained' | 'outlined' | 'skeleton';
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 = "contained", disabled = false, fullWidth = false, isActive = false, onAction, onClick, startIcon, endIcon, renderItem, ...rest }) => {
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 === "contained" && color === "primary",
28
- "border-transparent bg-secondary-bg text-secondary-fg hover:bg-secondary-bg-emphasize/80 active:bg-secondary-bg-emphasize": variant === "contained" && color === "secondary",
29
- "border-transparent bg-bg-subtle text-fg-base hover:bg-bg-mute/80 active:bg-bg-mute": variant === "contained" && color === "gray",
30
- "border-primary-border bg-bg-base text-primary-fg hover:bg-bg-subtle active:bg-bg-mute": variant === "outlined" && color === "primary",
31
- "border-secondary-border bg-bg-base text-secondary-fg hover:bg-bg-subtle active:bg-bg-mute": variant === "outlined" && color === "secondary",
32
- "border-border-base bg-bg-base text-fg-base hover:bg-bg-subtle active:bg-bg-mute": variant === "outlined" && color === "gray",
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
- }, "focus-visible:border-transparent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info", 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", (hasStartIcon || hasEndIcon) && "flex items-center gap-2", hasStartIcon && hasEndIcon ? "justify-between" : hasStartIcon && variant !== "skeleton" ? "justify-center" : hasEndIcon && "justify-between", isActive && "text-fg-info");
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 === "contained" && color === "primary",
48
- "cursor-not-allowed opacity-35 hover:bg-secondary-bg active:bg-secondary-bg": isDisabled && variant === "contained" && color === "secondary",
49
- "cursor-not-allowed opacity-35 hover:bg-bg-subtle active:bg-bg-subtle": isDisabled && variant === "contained" && color === "gray",
50
- "cursor-not-allowed bg-bg-base opacity-35": isDisabled && variant === "outlined",
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
- bg?: 'transparent' | 'base' | 'primary' | 'secondary';
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", bg = "transparent", label, tooltipPlacement = "top", tooltipDisabled = false, children, onAction, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, disabled, renderItem, "aria-describedby": describedBy, ...props }) => {
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", "focus-visible:border-transparent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info", (bg === "transparent" || bg === "base") && "hover:bg-bg-subtle active:bg-bg-mute", bg === "base" && "bg-bg-base", bg === "transparent" && "bg-transparent", bg === "primary" && "bg-primary-bg hover:bg-primary-bg-emphasize/80 active:bg-primary-bg-emphasize", bg === "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
+ 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", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-info"),
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
- children: /* @__PURE__ */ jsx("div", { children })
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 { createContext, use } from "react";
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 { isOpen, toggle } = useDisclosure(defaultOpen);
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: toggle,
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: _$react.FC<{
6
- children?: _$react.ReactNode | undefined;
3
+ readonly Root: import("react").FC<{
4
+ children?: import("react").ReactNode | undefined;
7
5
  }>;
8
- readonly Button: _$react.FC<{
9
- children?: _$react.ReactNode | undefined;
6
+ readonly Button: import("react").FC<{
7
+ children?: import("react").ReactNode | undefined;
10
8
  }>;
11
- readonly Item: _$react.FC<_$react.PropsWithChildren<{
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: _$react.FC<{
15
- children?: _$react.ReactNode | undefined;
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, className, ...rest }) => {
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", className),
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", className, ...rest }) => {
5
- 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");
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: cn(badgeClassName, 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: cn(badgeClassName, 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", className, ...rest }) => /* @__PURE__ */ jsx("div", {
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", className),
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", className, ...rest }) => /* @__PURE__ */ jsx("div", {
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", className),
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