@dryui/ui 0.5.2 → 1.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 (99) hide show
  1. package/dist/alert/{alert-root.svelte → alert.svelte} +78 -20
  2. package/dist/alert/alert.svelte.d.ts +15 -0
  3. package/dist/alert/index.d.ts +15 -14
  4. package/dist/alert/index.js +3 -12
  5. package/dist/breadcrumb/breadcrumb-link.svelte +1 -1
  6. package/dist/button/button.svelte +1 -1
  7. package/dist/card/card-root.svelte +2 -2
  8. package/dist/chromatic-shift/chromatic-shift.svelte +2 -2
  9. package/dist/code-block/code-block-button.svelte +1 -1
  10. package/dist/color-picker/color-picker-area.svelte +2 -2
  11. package/dist/color-picker/color-picker-channel-input.svelte +2 -2
  12. package/dist/color-picker/color-picker-input-alpha-slider.svelte +2 -2
  13. package/dist/color-picker/color-picker-input-hue-slider.svelte +2 -2
  14. package/dist/color-picker/color-picker-input.svelte +9 -9
  15. package/dist/color-picker/color-picker-swatch.svelte +2 -2
  16. package/dist/combobox/combobox-input.svelte +9 -9
  17. package/dist/command-palette/command-palette-item.svelte +1 -1
  18. package/dist/data-grid/data-grid-button-input-column.svelte +1 -1
  19. package/dist/diagram/diagram.svelte +222 -32
  20. package/dist/diagram/diagram.svelte.d.ts +1 -0
  21. package/dist/diagram/edge-routing.d.ts +63 -1
  22. package/dist/diagram/edge-routing.js +316 -26
  23. package/dist/diagram/layout.js +633 -62
  24. package/dist/diagram/types.d.ts +58 -0
  25. package/dist/drag-and-drop/drag-and-drop-handle.svelte +1 -1
  26. package/dist/drag-and-drop/drag-and-drop-item.svelte +1 -1
  27. package/dist/file-select/file-select-root.svelte +2 -2
  28. package/dist/file-upload/file-upload-dropzone.svelte +2 -2
  29. package/dist/gauge/gauge.svelte +1 -1
  30. package/dist/image-comparison/image-comparison.svelte +1 -1
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.js +1 -1
  33. package/dist/input/input.svelte +10 -11
  34. package/dist/label/label.svelte +1 -1
  35. package/dist/link/link.svelte +1 -1
  36. package/dist/list/list-item.svelte +2 -2
  37. package/dist/multi-select-combobox/multi-select-combobox-selection-item.svelte +9 -3
  38. package/dist/multi-select-combobox/multi-select-combobox-selection-remove-button.svelte +2 -0
  39. package/dist/navigation-menu/navigation-menu-link.svelte +1 -1
  40. package/dist/notification-center/notification-center-item.svelte +1 -1
  41. package/dist/number-input/number-input-button.svelte +3 -3
  42. package/dist/option-picker/context.svelte.d.ts +9 -0
  43. package/dist/option-picker/context.svelte.js +2 -0
  44. package/dist/option-picker/option-picker-item.svelte +31 -4
  45. package/dist/option-picker/option-picker-preview.svelte +2 -2
  46. package/dist/option-picker/option-picker-root.svelte +2 -2
  47. package/dist/phone-input/phone-input-select.svelte +2 -2
  48. package/dist/pin-input/pin-input-cell.svelte +1 -1
  49. package/dist/pin-input/pin-input-root.svelte +1 -1
  50. package/dist/progress/progress.svelte +1 -1
  51. package/dist/scroll-area/scroll-area.svelte +1 -1
  52. package/dist/shimmer/index.d.ts +8 -0
  53. package/dist/shimmer/index.js +1 -0
  54. package/dist/shimmer/shimmer.svelte +87 -0
  55. package/dist/shimmer/shimmer.svelte.d.ts +10 -0
  56. package/dist/sidebar/sidebar-item.svelte +1 -1
  57. package/dist/slider/slider-input.svelte +2 -2
  58. package/dist/splitter/splitter-handle.svelte +1 -1
  59. package/dist/table-of-contents/table-of-contents-item.svelte +1 -1
  60. package/dist/table-of-contents/table-of-contents-list.svelte +1 -1
  61. package/dist/tags-input/tags-input-root.svelte +1 -1
  62. package/dist/tags-input/tags-input-tag-delete-button.svelte +2 -0
  63. package/dist/tags-input/tags-input-tag.svelte +9 -3
  64. package/dist/textarea/textarea.svelte +11 -11
  65. package/dist/themes/default.css +31 -0
  66. package/dist/toast/toast-root.svelte +1 -1
  67. package/dist/tour/tour-root.css +3 -3
  68. package/dist/tree/tree-item-children.svelte +1 -1
  69. package/dist/tree/tree-item-label.svelte +1 -1
  70. package/dist/video-embed/video-embed-button.svelte +1 -1
  71. package/package.json +11 -750
  72. package/skills/dryui/SKILL.md +26 -21
  73. package/skills/dryui/rules/compound-components.md +3 -3
  74. package/skills/dryui/rules/theming.md +1 -1
  75. package/dist/alert/alert-button-close.svelte +0 -29
  76. package/dist/alert/alert-button-close.svelte.d.ts +0 -8
  77. package/dist/alert/alert-description.svelte +0 -28
  78. package/dist/alert/alert-description.svelte.d.ts +0 -8
  79. package/dist/alert/alert-icon.svelte +0 -26
  80. package/dist/alert/alert-icon.svelte.d.ts +0 -8
  81. package/dist/alert/alert-root.svelte.d.ts +0 -12
  82. package/dist/alert/alert-title.svelte +0 -29
  83. package/dist/alert/alert-title.svelte.d.ts +0 -8
  84. package/dist/alert/context.svelte.d.ts +0 -9
  85. package/dist/alert/context.svelte.js +0 -10
  86. package/dist/option-swatch-group/context.svelte.d.ts +0 -9
  87. package/dist/option-swatch-group/context.svelte.js +0 -2
  88. package/dist/option-swatch-group/index.d.ts +0 -29
  89. package/dist/option-swatch-group/index.js +0 -12
  90. package/dist/option-swatch-group/option-swatch-group-item-button.svelte +0 -214
  91. package/dist/option-swatch-group/option-swatch-group-item-button.svelte.d.ts +0 -12
  92. package/dist/option-swatch-group/option-swatch-group-label.svelte +0 -24
  93. package/dist/option-swatch-group/option-swatch-group-label.svelte.d.ts +0 -8
  94. package/dist/option-swatch-group/option-swatch-group-meta.svelte +0 -24
  95. package/dist/option-swatch-group/option-swatch-group-meta.svelte.d.ts +0 -8
  96. package/dist/option-swatch-group/option-swatch-group-root.svelte +0 -81
  97. package/dist/option-swatch-group/option-swatch-group-root.svelte.d.ts +0 -12
  98. package/dist/option-swatch-group/option-swatch-group-swatch.svelte +0 -52
  99. package/dist/option-swatch-group/option-swatch-group-swatch.svelte.d.ts +0 -10
@@ -33,9 +33,9 @@ Most DryUI components are compound — they require `<Card.Root>`, not `<Card>`.
33
33
  <Card.Root>content</Card.Root>
34
34
  ```
35
35
 
36
- Compound components include Accordion, Alert, AlertDialog, Breadcrumb, Calendar, Card, Carousel, Chart, ChipGroup, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, DataGrid, DateField, DatePicker, DateRangePicker, DescriptionList, Dialog, DragAndDrop, Drawer, DropdownMenu, Field, Fieldset, FileSelect, FileUpload, FlipCard, FloatButton, HoverCard, InputGroup, LinkPreview, List, Listbox, Map, MegaMenu, Menubar, MultiSelectCombobox, NavigationMenu, NotificationCenter, OptionSwatchGroup, Pagination, PinInput, Popover, RadioGroup, RangeCalendar, RichTextEditor, SegmentedControl, Select, Sidebar, Splitter, StarRating, Stepper, Table, TableOfContents, Tabs, TagsInput, Timeline, Toast, ToggleGroup, Toolbar, Tooltip, Tour, Transfer, Tree and Typography.
36
+ Compound components are tracked in the manifest at `packages/mcp/src/component-catalog.ts`. Verify with `info` before you assume a bare name works, then use `.Root` and wrap the parts inside it.
37
37
 
38
- The test: every compound component in your markup uses `.Root`, and its parts are wrapped inside it. See `rules/compound-components.md` for the full list and parts reference.
38
+ The test: every compound component in your markup uses `.Root`, and its parts are wrapped inside it. See `rules/compound-components.md` for the parts reference.
39
39
 
40
40
  ## 3. Let the Theme Do Its Job
41
41
 
@@ -126,20 +126,23 @@ The test: search your markup for raw `<input`, `<select>`, `<dialog>`, `<button>
126
126
  - Codex: public install today is `$skill-installer install https://github.com/rob-balfre/dryui/tree/main/packages/ui/skills/dryui` then `codex mcp add dryui -- npx -y @dryui/mcp`. If you're working inside the DryUI repo itself, install the repo-local plugin from `/plugins` via `.agents/plugins/marketplace.json`.
127
127
  - Copilot/Cursor/Windsurf: `npx degit rob-balfre/dryui/packages/ui/skills/dryui .agents/skills/dryui` + add MCP config (see https://dryui.dev/tools)
128
128
 
129
- **3. Bootstrap the project** `init` detects your project state and applies whatever is missing:
129
+ **3. Install the CLI** so every subsequent command is short and fast:
130
130
 
131
- ```
132
- npx -y @dryui/cli init
131
+ ```bash
132
+ bun install -g @dryui/cli # or: npm install -g @dryui/cli
133
133
  ```
134
134
 
135
- **New project from scratch?** Pass a directory name to scaffold SvelteKit + DryUI in one step:
135
+ **4. Bootstrap the project** `init` detects your project state and applies whatever is missing:
136
136
 
137
+ ```bash
138
+ dryui init # existing project
139
+ dryui init my-app # new project — scaffolds SvelteKit + DryUI in one step
140
+ cd my-app && bun run dev
137
141
  ```
138
- npx -y @dryui/cli init my-app
139
- cd my-app && npm run dev
140
- ```
141
142
 
142
- This works for greenfield (empty directory), brownfield (existing non-SvelteKit project), and existing SvelteKit projects. Verify: `npx -y @dryui/cli detect --toon` — output should show `project: ready`.
143
+ This works for greenfield (empty directory), brownfield (existing non-SvelteKit project), and existing SvelteKit projects. Verify: `dryui detect` should show `project: ready`.
144
+
145
+ > **No global install?** `bunx @dryui/cli <cmd>` and `npx -y @dryui/cli <cmd>` work anywhere without installing — same commands, just slower (re-fetches on each call).
143
146
 
144
147
  ### Manual setup
145
148
 
@@ -185,21 +188,23 @@ Use these to look up APIs, discover components, plan setup, and validate code.
185
188
 
186
189
  ### CLI fallback
187
190
 
188
- All commands support `--toon` for token-optimized agent output and `--full` to disable truncation.
191
+ Install once with `bun install -g @dryui/cli` (or `npm install -g @dryui/cli`), then use the short form below. Every command outputs TOON (token-optimized, agent-friendly) by default. Pass `--text` for human-readable plain text, `--json` where supported, or `--full` to disable truncation.
189
192
 
190
193
  ```bash
191
- bunx @dryui/cli init [path] [--pm bun] # Bootstrap SvelteKit + DryUI project
192
- bunx @dryui/cli info <component> --toon # Look up component API
193
- bunx @dryui/cli compose "date input" --toon # Composition guidance
194
- bunx @dryui/cli detect [path] --toon # Check project setup
195
- bunx @dryui/cli install [path] --toon # Print install plan
196
- bunx @dryui/cli review <file.svelte> --toon # Validate component
197
- bunx @dryui/cli diagnose <file.css> --toon # Validate theme CSS
198
- bunx @dryui/cli doctor [path] --toon # Audit workspace
199
- bunx @dryui/cli lint [path] --toon # Deterministic findings
200
- bunx @dryui/cli list --toon # List components
194
+ dryui init [path] [--pm bun] # Bootstrap SvelteKit + DryUI project
195
+ dryui info <component> # Look up component API
196
+ dryui compose "date input" # Composition guidance
197
+ dryui detect [path] # Check project setup
198
+ dryui install [path] # Print install plan
199
+ dryui review <file.svelte> # Validate component
200
+ dryui diagnose <file.css> # Validate theme CSS
201
+ dryui doctor [path] # Audit workspace
202
+ dryui lint [path] # Deterministic findings
203
+ dryui list # List components
201
204
  ```
202
205
 
206
+ Without a global install, prefix any command with `bunx @dryui/cli …` or `npx -y @dryui/cli …` — same behaviour, just slower (re-fetches on each call).
207
+
203
208
  Categories: action, input, form, layout, navigation, overlay, display, feedback, interaction, utility
204
209
 
205
210
  ## Rule Files
@@ -18,7 +18,7 @@ Every compound component uses `.Root` as the container. Never use the bare name.
18
18
 
19
19
  ## Parts Reference
20
20
 
21
- Below are the parts for the most commonly used compound components. Always run `bunx @dryui/cli info <name>` for the full, up-to-date parts list.
21
+ Below are the parts for the most commonly used compound components. Always run `dryui info <name>` for the full, up-to-date parts list.
22
22
 
23
23
  ### Card
24
24
 
@@ -311,6 +311,6 @@ Parts: Root, Input, Content, Item, Empty
311
311
 
312
312
  ## Full Compound Component List
313
313
 
314
- Run `bunx @dryui/cli info <name>` for any component's complete parts list:
314
+ Run `dryui info <name>` for any component's complete parts list:
315
315
 
316
- Accordion, Alert, AlertDialog, Breadcrumb, Card, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, DataGrid, DatePicker, Dialog, DragAndDrop, Drawer, DropdownMenu, EmptyState, Field, FileUpload, FloatButton, Pagination, Popover, RadioGroup, RichTextEditor, Select, Splitter, Stepper, Table, Tabs, TagsInput, Toast, ToggleGroup, Toolbar, Tooltip, Tour, Transfer
316
+ Accordion, AlertDialog, Breadcrumb, Card, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, DataGrid, DatePicker, Dialog, DragAndDrop, Drawer, DropdownMenu, EmptyState, Field, FileUpload, FloatButton, Pagination, Popover, RadioGroup, RichTextEditor, Select, Splitter, Stepper, Table, Tabs, TagsInput, Toast, ToggleGroup, Toolbar, Tooltip, Tour, Transfer
@@ -271,7 +271,7 @@ Ensure sufficient contrast between text and background.
271
271
  Run the CLI diagnose command to catch theme issues:
272
272
 
273
273
  ```bash
274
- bunx @dryui/cli diagnose src/styles/global.css
274
+ dryui diagnose src/styles/global.css
275
275
  ```
276
276
 
277
277
  Common diagnostic codes:
@@ -1,29 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { HTMLButtonAttributes } from 'svelte/elements';
4
- import CloseButtonBase from '../internal/close-button-base.svelte';
5
- import { getAlertCtx } from './context.svelte.js';
6
-
7
- interface Props extends HTMLButtonAttributes {
8
- children?: Snippet;
9
- }
10
-
11
- let { children, ...rest }: Props = $props();
12
-
13
- const ctx = getAlertCtx();
14
- </script>
15
-
16
- <span class="alert-close-slot">
17
- <CloseButtonBase aria-label="Dismiss alert" {...rest} onclick={() => ctx.dismiss()}>
18
- {#if children}{@render children()}{/if}
19
- </CloseButtonBase>
20
- </span>
21
-
22
- <style>
23
- .alert-close-slot {
24
- display: inline-grid;
25
- grid-column: -2 / -1;
26
- grid-row: 1 / 3;
27
- align-self: start;
28
- }
29
- </style>
@@ -1,8 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLButtonAttributes } from 'svelte/elements';
3
- interface Props extends HTMLButtonAttributes {
4
- children?: Snippet;
5
- }
6
- declare const AlertButtonClose: import("svelte").Component<Props, {}, "">;
7
- type AlertButtonClose = ReturnType<typeof AlertButtonClose>;
8
- export default AlertButtonClose;
@@ -1,28 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { HTMLAttributes } from 'svelte/elements';
4
- import { markDirectChild } from './context.svelte.js';
5
-
6
- interface Props extends HTMLAttributes<HTMLParagraphElement> {
7
- children: Snippet;
8
- }
9
-
10
- let { class: className, children, ...rest }: Props = $props();
11
- </script>
12
-
13
- <p data-alert-description {@attach markDirectChild} class={className} {...rest}>
14
- {@render children()}
15
- </p>
16
-
17
- <style>
18
- [data-alert-description][data-alert-direct-child] {
19
- grid-column: 2;
20
- }
21
-
22
- [data-alert-description] {
23
- font-size: var(--dry-type-small-size);
24
- line-height: var(--dry-type-small-leading);
25
- color: var(--dry-color-text-weak);
26
- margin: 0;
27
- }
28
- </style>
@@ -1,8 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- interface Props extends HTMLAttributes<HTMLParagraphElement> {
4
- children: Snippet;
5
- }
6
- declare const AlertDescription: import("svelte").Component<Props, {}, "">;
7
- type AlertDescription = ReturnType<typeof AlertDescription>;
8
- export default AlertDescription;
@@ -1,26 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { HTMLAttributes } from 'svelte/elements';
4
-
5
- interface Props extends HTMLAttributes<HTMLSpanElement> {
6
- children: Snippet;
7
- }
8
-
9
- let { class: className, children, ...rest }: Props = $props();
10
- </script>
11
-
12
- <span aria-hidden="true" data-alert-icon class={className} {...rest}>
13
- {@render children()}
14
- </span>
15
-
16
- <style>
17
- [data-alert-icon] {
18
- grid-column: 1;
19
- grid-row: 1 / 3;
20
- color: var(--dry-alert-icon-color);
21
- display: grid;
22
- align-items: center;
23
- margin-top: var(--dry-space-0_5);
24
- padding-inline-end: var(--dry-alert-gap, var(--dry-space-3));
25
- }
26
- </style>
@@ -1,8 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- interface Props extends HTMLAttributes<HTMLSpanElement> {
4
- children: Snippet;
5
- }
6
- declare const AlertIcon: import("svelte").Component<Props, {}, "">;
7
- type AlertIcon = ReturnType<typeof AlertIcon>;
8
- export default AlertIcon;
@@ -1,12 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- import { type AlertVariant } from './context.svelte.js';
4
- interface Props extends HTMLAttributes<HTMLDivElement> {
5
- variant?: AlertVariant;
6
- dismissible?: boolean;
7
- onDismiss?: () => void;
8
- children: Snippet;
9
- }
10
- declare const AlertRoot: import("svelte").Component<Props, {}, "">;
11
- type AlertRoot = ReturnType<typeof AlertRoot>;
12
- export default AlertRoot;
@@ -1,29 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { HTMLAttributes } from 'svelte/elements';
4
- import { markDirectChild } from './context.svelte.js';
5
-
6
- interface Props extends HTMLAttributes<HTMLHeadingElement> {
7
- children: Snippet;
8
- }
9
-
10
- let { class: className, children, ...rest }: Props = $props();
11
- </script>
12
-
13
- <h5 data-alert-title {@attach markDirectChild} class={className} {...rest}>
14
- {@render children()}
15
- </h5>
16
-
17
- <style>
18
- [data-alert-title][data-alert-direct-child] {
19
- grid-column: 2;
20
- }
21
-
22
- [data-alert-title] {
23
- font-size: var(--dry-type-heading-4-size);
24
- font-weight: 600;
25
- line-height: var(--dry-type-small-leading);
26
- color: var(--dry-color-text-strong);
27
- margin: 0;
28
- }
29
- </style>
@@ -1,8 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- interface Props extends HTMLAttributes<HTMLHeadingElement> {
4
- children: Snippet;
5
- }
6
- declare const AlertTitle: import("svelte").Component<Props, {}, "">;
7
- type AlertTitle = ReturnType<typeof AlertTitle>;
8
- export default AlertTitle;
@@ -1,9 +0,0 @@
1
- export type AlertVariant = 'info' | 'success' | 'warning' | 'error';
2
- interface AlertContext {
3
- readonly variant: AlertVariant;
4
- readonly isDismissed: boolean;
5
- dismiss: () => void;
6
- }
7
- export declare const setAlertCtx: (ctx: AlertContext) => AlertContext, getAlertCtx: () => AlertContext;
8
- export declare function markDirectChild(node: HTMLElement): () => void;
9
- export {};
@@ -1,10 +0,0 @@
1
- import { createContext } from '@dryui/primitives';
2
- export const [setAlertCtx, getAlertCtx] = createContext('alert');
3
- export function markDirectChild(node) {
4
- if (node.parentElement?.hasAttribute('data-alert')) {
5
- node.setAttribute('data-alert-direct-child', '');
6
- }
7
- return () => {
8
- node.removeAttribute('data-alert-direct-child');
9
- };
10
- }
@@ -1,9 +0,0 @@
1
- interface SelectableTileGroupContext {
2
- readonly value: string;
3
- readonly disabled: boolean;
4
- readonly orientation: 'horizontal' | 'vertical';
5
- select: (value: string) => void;
6
- isSelected: (value: string) => boolean;
7
- }
8
- export declare const setSelectableTileGroupCtx: (ctx: SelectableTileGroupContext) => SelectableTileGroupContext, getSelectableTileGroupCtx: () => SelectableTileGroupContext;
9
- export {};
@@ -1,2 +0,0 @@
1
- import { createContext } from '@dryui/primitives';
2
- export const [setSelectableTileGroupCtx, getSelectableTileGroupCtx] = createContext('selectable-tile-group');
@@ -1,29 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- import type { SelectableTileGroupItemProps as PrimitiveOptionSwatchGroupItemProps, SelectableTileGroupRootProps as PrimitiveOptionSwatchGroupRootProps } from '@dryui/primitives';
4
- export type { SelectableTileGroupLabelProps as OptionSwatchGroupLabelProps } from '@dryui/primitives';
5
- export type { SelectableTileGroupMetaProps as OptionSwatchGroupMetaProps } from '@dryui/primitives';
6
- export interface OptionSwatchGroupRootProps extends PrimitiveOptionSwatchGroupRootProps {
7
- columns?: 1 | 2 | 3 | 4;
8
- }
9
- export interface OptionSwatchGroupItemProps extends PrimitiveOptionSwatchGroupItemProps {
10
- size?: 'default' | 'compact';
11
- unavailable?: boolean;
12
- }
13
- export interface OptionSwatchGroupSwatchProps extends HTMLAttributes<HTMLSpanElement> {
14
- color?: string;
15
- shape?: 'circle' | 'rounded';
16
- children?: Snippet;
17
- }
18
- import OptionSwatchGroupRoot from './option-swatch-group-root.svelte';
19
- import OptionSwatchGroupItem from './option-swatch-group-item-button.svelte';
20
- import OptionSwatchGroupSwatch from './option-swatch-group-swatch.svelte';
21
- import OptionSwatchGroupLabel from './option-swatch-group-label.svelte';
22
- import OptionSwatchGroupMeta from './option-swatch-group-meta.svelte';
23
- export declare const OptionSwatchGroup: {
24
- Root: typeof OptionSwatchGroupRoot;
25
- Item: typeof OptionSwatchGroupItem;
26
- Swatch: typeof OptionSwatchGroupSwatch;
27
- Label: typeof OptionSwatchGroupLabel;
28
- Meta: typeof OptionSwatchGroupMeta;
29
- };
@@ -1,12 +0,0 @@
1
- import OptionSwatchGroupRoot from './option-swatch-group-root.svelte';
2
- import OptionSwatchGroupItem from './option-swatch-group-item-button.svelte';
3
- import OptionSwatchGroupSwatch from './option-swatch-group-swatch.svelte';
4
- import OptionSwatchGroupLabel from './option-swatch-group-label.svelte';
5
- import OptionSwatchGroupMeta from './option-swatch-group-meta.svelte';
6
- export const OptionSwatchGroup = {
7
- Root: OptionSwatchGroupRoot,
8
- Item: OptionSwatchGroupItem,
9
- Swatch: OptionSwatchGroupSwatch,
10
- Label: OptionSwatchGroupLabel,
11
- Meta: OptionSwatchGroupMeta
12
- };
@@ -1,214 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { HTMLButtonAttributes } from 'svelte/elements';
4
- import Button from '../button/button.svelte';
5
- import { getSelectableTileGroupCtx } from './context.svelte.js';
6
-
7
- interface Props extends Omit<HTMLButtonAttributes, 'value'> {
8
- value: string;
9
- disabled?: boolean;
10
- unavailable?: boolean;
11
- size?: 'default' | 'compact';
12
- children: Snippet;
13
- }
14
-
15
- let {
16
- value,
17
- disabled = false,
18
- unavailable = false,
19
- size = 'default',
20
- children,
21
- ...rest
22
- }: Props = $props();
23
-
24
- const ctx = getSelectableTileGroupCtx();
25
- const isDisabled = $derived(disabled || unavailable || ctx.disabled);
26
- const isSelected = $derived(ctx.isSelected(value));
27
-
28
- function moveFocus(current: HTMLButtonElement, direction: -1 | 1) {
29
- const group = current.closest('[role="radiogroup"]');
30
- if (!(group instanceof HTMLElement)) return;
31
-
32
- const items = Array.from(
33
- group.querySelectorAll<HTMLButtonElement>('[role="radio"]:not([disabled])')
34
- );
35
- const index = items.indexOf(current);
36
- if (index === -1) return;
37
-
38
- const target = items[(index + direction + items.length) % items.length];
39
- target?.focus();
40
- const nextValue = target?.dataset.value;
41
- if (nextValue) ctx.select(nextValue);
42
- }
43
-
44
- function handleKeydown(event: KeyboardEvent) {
45
- if (isDisabled || !(event.currentTarget instanceof HTMLButtonElement)) return;
46
-
47
- const isHorizontal = ctx.orientation === 'horizontal';
48
- if (
49
- (isHorizontal && event.key === 'ArrowRight') ||
50
- (!isHorizontal && event.key === 'ArrowDown')
51
- ) {
52
- event.preventDefault();
53
- moveFocus(event.currentTarget, 1);
54
- }
55
- if ((isHorizontal && event.key === 'ArrowLeft') || (!isHorizontal && event.key === 'ArrowUp')) {
56
- event.preventDefault();
57
- moveFocus(event.currentTarget, -1);
58
- }
59
- if (event.key === ' ' || event.key === 'Enter') {
60
- event.preventDefault();
61
- ctx.select(value);
62
- }
63
- }
64
- </script>
65
-
66
- <span
67
- class="root"
68
- data-size={size !== 'default' ? size : undefined}
69
- data-state={isSelected ? 'checked' : 'unchecked'}
70
- data-selected={isSelected ? '' : undefined}
71
- data-disabled={isDisabled || undefined}
72
- data-unavailable={unavailable || undefined}
73
- >
74
- <Button
75
- variant="bare"
76
- type="button"
77
- role="radio"
78
- aria-checked={isSelected}
79
- disabled={isDisabled}
80
- data-option-swatch-group-item
81
- data-state={isSelected ? 'checked' : 'unchecked'}
82
- data-selected={isSelected ? '' : undefined}
83
- data-unavailable={unavailable || undefined}
84
- data-value={value}
85
- tabindex={isSelected ? 0 : -1}
86
- {...rest}
87
- onclick={() => {
88
- if (!isDisabled) ctx.select(value);
89
- }}
90
- onkeydown={handleKeydown}
91
- >
92
- <span class="content">
93
- {@render children()}
94
- </span>
95
- </Button>
96
- </span>
97
-
98
- <style>
99
- .root {
100
- --_swatch-item-selected-bg: var(
101
- --dry-option-swatch-group-selected-bg,
102
- color-mix(in srgb, var(--dry-color-fill-selected) 12%, var(--dry-color-bg-raised) 88%)
103
- );
104
- --_swatch-item-selected-bg-hover: var(
105
- --dry-option-swatch-group-selected-bg-hover,
106
- color-mix(in srgb, var(--dry-color-fill-selected) 16%, var(--dry-color-bg-raised) 84%)
107
- );
108
- --_swatch-item-selected-border: var(
109
- --dry-option-swatch-group-selected-border,
110
- var(--dry-color-stroke-selected)
111
- );
112
-
113
- display: grid;
114
- background: var(--dry-option-swatch-group-bg, var(--dry-color-bg-base));
115
- border: 1px solid var(--dry-option-swatch-group-border, var(--dry-color-stroke-weak));
116
- border-radius: var(--dry-option-swatch-group-radius, var(--dry-radius-lg));
117
- box-shadow: var(--dry-option-swatch-group-shadow, none);
118
- transition:
119
- background var(--dry-duration-fast, 100ms) ease,
120
- border-color var(--dry-duration-fast, 100ms) ease,
121
- box-shadow var(--dry-duration-fast, 100ms) ease,
122
- transform var(--dry-duration-fast, 100ms) ease;
123
-
124
- --dry-btn-bg: transparent;
125
- --dry-btn-border: transparent;
126
- --dry-btn-color: var(--dry-option-swatch-group-color, var(--dry-color-text-strong));
127
- --dry-btn-padding-x: 0;
128
- --dry-btn-padding-y: 0;
129
- --dry-btn-radius: var(--dry-option-swatch-group-radius, var(--dry-radius-lg));
130
- --dry-btn-justify: stretch;
131
- --dry-btn-align: stretch;
132
- --dry-btn-min-height: 0;
133
- }
134
-
135
- .root:hover:not([data-disabled]) {
136
- border-color: color-mix(
137
- in srgb,
138
- var(--dry-color-stroke-strong) 72%,
139
- var(--dry-color-stroke-weak) 28%
140
- );
141
- background: var(
142
- --dry-option-swatch-group-bg-hover,
143
- color-mix(in srgb, var(--dry-color-bg-raised) 92%, var(--dry-color-fill-selected) 8%)
144
- );
145
- }
146
-
147
- .root[data-state='checked'] {
148
- border-color: var(--_swatch-item-selected-border);
149
- background: var(--_swatch-item-selected-bg);
150
- }
151
-
152
- .root[data-state='checked']:hover:not([data-disabled]) {
153
- background: var(--_swatch-item-selected-bg-hover);
154
- }
155
-
156
- .root:focus-within {
157
- outline: 2px solid var(--dry-color-focus-ring);
158
- outline-offset: 2px;
159
- }
160
-
161
- .content {
162
- display: grid;
163
- grid-template-columns: auto minmax(0, 1fr);
164
- align-items: center;
165
- justify-items: start;
166
- gap: var(--dry-option-swatch-group-item-gap, var(--dry-space-2_5));
167
- padding: var(--dry-option-swatch-group-padding-y, var(--dry-space-2))
168
- var(--dry-option-swatch-group-padding-x, var(--dry-space-2_5));
169
- min-block-size: var(--dry-option-swatch-group-min-block-size, 3rem);
170
- text-align: left;
171
- }
172
-
173
- .root[data-size='compact'] .content {
174
- grid-template-columns: auto;
175
- justify-items: center;
176
- gap: 0;
177
- min-block-size: 0;
178
- padding: var(--dry-option-swatch-group-compact-padding, var(--dry-space-0_5));
179
- }
180
-
181
- .root[data-size='compact'] {
182
- background: transparent;
183
- border-color: transparent;
184
- border-radius: 999px;
185
- box-shadow: none;
186
- }
187
-
188
- .root[data-size='compact']:hover:not([data-disabled]) {
189
- background: color-mix(in srgb, var(--dry-color-fill-selected) 6%, transparent);
190
- border-color: transparent;
191
- }
192
-
193
- .root[data-size='compact'][data-state='checked'] {
194
- --dry-option-swatch-group-swatch-border: color-mix(
195
- in srgb,
196
- var(--_swatch-item-selected-border) 34%,
197
- var(--dry-color-stroke-weak) 66%
198
- );
199
-
200
- background: color-mix(in srgb, var(--dry-color-fill-selected) 6%, transparent);
201
- border-color: transparent;
202
- box-shadow: 0 0 0 1px var(--_swatch-item-selected-border);
203
- }
204
-
205
- .root[data-size='compact'][data-state='checked']:hover:not([data-disabled]) {
206
- background: color-mix(in srgb, var(--dry-color-fill-selected) 8%, transparent);
207
- }
208
-
209
- .root[data-disabled] {
210
- opacity: 0.6;
211
- border-color: var(--dry-color-stroke-disabled);
212
- box-shadow: none;
213
- }
214
- </style>
@@ -1,12 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLButtonAttributes } from 'svelte/elements';
3
- interface Props extends Omit<HTMLButtonAttributes, 'value'> {
4
- value: string;
5
- disabled?: boolean;
6
- unavailable?: boolean;
7
- size?: 'default' | 'compact';
8
- children: Snippet;
9
- }
10
- declare const OptionSwatchGroupItemButton: import("svelte").Component<Props, {}, "">;
11
- type OptionSwatchGroupItemButton = ReturnType<typeof OptionSwatchGroupItemButton>;
12
- export default OptionSwatchGroupItemButton;
@@ -1,24 +0,0 @@
1
- <script lang="ts">
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- import type { Snippet } from 'svelte';
4
-
5
- interface Props extends HTMLAttributes<HTMLSpanElement> {
6
- children?: Snippet;
7
- }
8
-
9
- let { class: className, children, ...rest }: Props = $props();
10
- </script>
11
-
12
- <span data-part="label" data-option-swatch-group-label class={className} {...rest}
13
- >{@render children?.()}</span
14
- >
15
-
16
- <style>
17
- [data-option-swatch-group-label] {
18
- grid-column: 2;
19
- grid-row: 1;
20
- font-size: var(--dry-type-small-size);
21
- font-weight: 600;
22
- line-height: 1.2;
23
- }
24
- </style>
@@ -1,8 +0,0 @@
1
- import type { HTMLAttributes } from 'svelte/elements';
2
- import type { Snippet } from 'svelte';
3
- interface Props extends HTMLAttributes<HTMLSpanElement> {
4
- children?: Snippet;
5
- }
6
- declare const OptionSwatchGroupLabel: import("svelte").Component<Props, {}, "">;
7
- type OptionSwatchGroupLabel = ReturnType<typeof OptionSwatchGroupLabel>;
8
- export default OptionSwatchGroupLabel;
@@ -1,24 +0,0 @@
1
- <script lang="ts">
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- import type { Snippet } from 'svelte';
4
-
5
- interface Props extends HTMLAttributes<HTMLSpanElement> {
6
- children?: Snippet;
7
- }
8
-
9
- let { class: className, children, ...rest }: Props = $props();
10
- </script>
11
-
12
- <span data-part="meta" data-option-swatch-group-meta class={className} {...rest}
13
- >{@render children?.()}</span
14
- >
15
-
16
- <style>
17
- [data-option-swatch-group-meta] {
18
- grid-column: 2;
19
- grid-row: 2;
20
- color: var(--dry-option-swatch-muted);
21
- font-size: var(--dry-type-tiny-size);
22
- line-height: 1.2;
23
- }
24
- </style>
@@ -1,8 +0,0 @@
1
- import type { HTMLAttributes } from 'svelte/elements';
2
- import type { Snippet } from 'svelte';
3
- interface Props extends HTMLAttributes<HTMLSpanElement> {
4
- children?: Snippet;
5
- }
6
- declare const OptionSwatchGroupMeta: import("svelte").Component<Props, {}, "">;
7
- type OptionSwatchGroupMeta = ReturnType<typeof OptionSwatchGroupMeta>;
8
- export default OptionSwatchGroupMeta;