@spaethtech/svelte-ui 0.20.1-dev.102.3c5719c → 0.20.1-dev.105.894ecae

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 (54) hide show
  1. package/dist/components/Alert.svelte +4 -1
  2. package/dist/components/Alert.svelte.d.ts +2 -1
  3. package/dist/components/Banner.svelte +4 -1
  4. package/dist/components/Banner.svelte.d.ts +2 -1
  5. package/dist/components/Carousel/Carousel.svelte +4 -1
  6. package/dist/components/Carousel/Carousel.svelte.d.ts +2 -1
  7. package/dist/components/Chip/Chip.svelte +4 -1
  8. package/dist/components/Chip/Chip.svelte.d.ts +2 -1
  9. package/dist/components/Combobox/Combobox.svelte +4 -1
  10. package/dist/components/Combobox/Combobox.svelte.d.ts +2 -1
  11. package/dist/components/CommandPalette/CommandPalette.svelte +4 -2
  12. package/dist/components/CommandPalette/CommandPalette.svelte.d.ts +2 -1
  13. package/dist/components/ConfirmDialog.svelte +4 -1
  14. package/dist/components/ConfirmDialog.svelte.d.ts +2 -1
  15. package/dist/components/ContextMenu/ContextMenu.svelte +4 -2
  16. package/dist/components/ContextMenu/ContextMenu.svelte.d.ts +2 -1
  17. package/dist/components/DataTable.svelte +4 -1
  18. package/dist/components/DataTable.svelte.d.ts +2 -1
  19. package/dist/components/DatePicker.svelte +4 -2
  20. package/dist/components/DatePicker.svelte.d.ts +2 -1
  21. package/dist/components/Drawer/Drawer.svelte +4 -1
  22. package/dist/components/Drawer/Drawer.svelte.d.ts +2 -1
  23. package/dist/components/FileUpload/FileUpload.svelte +4 -2
  24. package/dist/components/FileUpload/FileUpload.svelte.d.ts +2 -1
  25. package/dist/components/Menu.svelte +4 -1
  26. package/dist/components/Menu.svelte.d.ts +2 -1
  27. package/dist/components/Pagination/Pagination.svelte +4 -1
  28. package/dist/components/Pagination/Pagination.svelte.d.ts +2 -1
  29. package/dist/components/Popup.svelte +8 -1
  30. package/dist/components/Popup.svelte.d.ts +2 -1
  31. package/dist/components/Query.svelte +4 -2
  32. package/dist/components/Query.svelte.d.ts +2 -1
  33. package/dist/components/ScrollArea/ScrollArea.svelte +5 -2
  34. package/dist/components/ScrollArea/ScrollArea.svelte.d.ts +2 -1
  35. package/dist/components/SideBarMenu/SideBarMenu.svelte +7 -1
  36. package/dist/components/SideBarMenu/SideBarMenu.svelte.d.ts +2 -1
  37. package/dist/components/Slider/Slider.svelte +4 -2
  38. package/dist/components/Slider/Slider.svelte.d.ts +2 -1
  39. package/dist/components/Spinner/Spinner.svelte +4 -1
  40. package/dist/components/Spinner/Spinner.svelte.d.ts +2 -1
  41. package/dist/components/Splitter/Splitter.svelte +4 -1
  42. package/dist/components/Splitter/Splitter.svelte.d.ts +2 -1
  43. package/dist/components/Stepper/Stepper.svelte +4 -1
  44. package/dist/components/Stepper/Stepper.svelte.d.ts +2 -1
  45. package/dist/components/ThemeSelector.svelte +10 -2
  46. package/dist/components/ThemeSelector.svelte.d.ts +2 -1
  47. package/dist/components/ThemeToggle.svelte +10 -1
  48. package/dist/components/ThemeToggle.svelte.d.ts +2 -1
  49. package/dist/components/TokenInput/TokenInput.svelte +6 -1
  50. package/dist/components/TokenInput/TokenInput.svelte.d.ts +2 -1
  51. package/dist/components/Tree/Tree.svelte +11 -2
  52. package/dist/components/Tree/Tree.svelte.d.ts +2 -1
  53. package/docs/components.md +12 -0
  54. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
1
2
  import type { Variant } from "../../types/variants.js";
2
3
  import type { Size } from "../../types/sizes.js";
3
4
  import { type Responsive } from "../../types/responsive.js";
@@ -19,7 +20,7 @@ type $$ComponentProps = {
19
20
  borderless?: boolean;
20
21
  disabled?: boolean;
21
22
  class?: string;
22
- };
23
+ } & Omit<HTMLAttributes<HTMLElement>, "class" | "style">;
23
24
  declare const Pagination: import("svelte").Component<$$ComponentProps, {}, "perPage" | "page">;
24
25
  type Pagination = ReturnType<typeof Pagination>;
25
26
  export default Pagination;
@@ -17,6 +17,7 @@
17
17
  -->
18
18
  <script lang="ts">
19
19
  import type { Snippet } from "svelte";
20
+ import type { HTMLAttributes } from "svelte/elements";
20
21
  import {
21
22
  anchored,
22
23
  type Side,
@@ -46,6 +47,7 @@
46
47
  onclose,
47
48
  onplaced,
48
49
  children,
50
+ ...rest
49
51
  }: {
50
52
  /** The trigger element to position against. */
51
53
  anchor: HTMLElement | undefined;
@@ -80,7 +82,11 @@
80
82
  * the box actually landed (e.g. edge-flush borders). */
81
83
  onplaced?: (p: Placement) => void;
82
84
  children: Snippet;
83
- } = $props();
85
+ // Leftover HTML attributes are forwarded onto the popover box (the top-layer positioner `<div>`,
86
+ // which is this component's primary content container). `style` omitted — the box computes its own
87
+ // (the panel border when `surface`). `onclose` omitted — it collides with the DOM `onclose` event
88
+ // but is this component's own dismissal callback (`() => void`).
89
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "style" | "onclose"> = $props();
84
90
 
85
91
  // Themed-panel styling (only used when `surface`). Border tints from the variant token; `borderless`
86
92
  // paints it the panel's background. Padding scales with `size`.
@@ -137,6 +143,7 @@
137
143
  </script>
138
144
 
139
145
  <div
146
+ {...rest}
140
147
  bind:this={el}
141
148
  popover="manual"
142
149
  data-open={open}
@@ -1,4 +1,5 @@
1
1
  import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
2
3
  import { type Side, type Align, type Boundary, type Placement } from "../positioning/anchored.js";
3
4
  import type { Size } from "../types/sizes.js";
4
5
  import { type Responsive } from "../types/responsive.js";
@@ -37,7 +38,7 @@ type $$ComponentProps = {
37
38
  * the box actually landed (e.g. edge-flush borders). */
38
39
  onplaced?: (p: Placement) => void;
39
40
  children: Snippet;
40
- };
41
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "style" | "onclose">;
41
42
  declare const Popup: import("svelte").Component<$$ComponentProps, {}, "open">;
42
43
  type Popup = ReturnType<typeof Popup>;
43
44
  export default Popup;
@@ -10,6 +10,7 @@
10
10
  import { uiI18n } from "../i18n.js";
11
11
  const i18n = uiI18n();
12
12
  import { tick } from "svelte";
13
+ import type { HTMLAttributes } from "svelte/elements";
13
14
  import IconSearch from "~icons/mdi/magnify";
14
15
  import IconClose from "~icons/mdi/close";
15
16
  import IconHelp from "~icons/mdi/help-circle-outline";
@@ -28,6 +29,7 @@
28
29
  size = "md",
29
30
  variant = "neutral",
30
31
  borderless = false,
32
+ ...rest
31
33
  }: {
32
34
  dataset: DataSet;
33
35
  placeholder?: string;
@@ -35,7 +37,7 @@
35
37
  size?: Responsive<Size>;
36
38
  variant?: Variant;
37
39
  borderless?: boolean;
38
- } = $props();
40
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class"> = $props();
39
41
 
40
42
  let inputEl = $state<HTMLInputElement>();
41
43
  let wrapperEl = $state<HTMLElement>();
@@ -134,7 +136,7 @@
134
136
  const bc = "border-[color-mix(in_srgb,var(--ui-color-secondary)_30%,transparent)]";
135
137
  </script>
136
138
 
137
- <div class="w-full [color:var(--ui-color-text)]">
139
+ <div {...rest} class="w-full [color:var(--ui-color-text)]">
138
140
  <!-- Built on the core <Input> so the frame/border/hover/focus glow + themed autofill are shared,
139
141
  not re-rolled. Search is the left icon; clear + help live in the `actions` slot; the parse
140
142
  error reuses Input's own validation (danger) styling. -->
@@ -1,3 +1,4 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
1
2
  import type { DataSet } from "../data/dataset.js";
2
3
  import type { Size } from "../types/sizes.js";
3
4
  import type { Responsive } from "../types/responsive.js";
@@ -9,7 +10,7 @@ type $$ComponentProps = {
9
10
  size?: Responsive<Size>;
10
11
  variant?: Variant;
11
12
  borderless?: boolean;
12
- };
13
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class">;
13
14
  declare const Query: import("svelte").Component<$$ComponentProps, {}, "">;
14
15
  type Query = ReturnType<typeof Query>;
15
16
  export default Query;
@@ -6,6 +6,7 @@
6
6
  -->
7
7
  <script lang="ts">
8
8
  import type { Snippet } from "svelte";
9
+ import type { HTMLAttributes } from "svelte/elements";
9
10
  import type { Variant } from "../../types/variants.js";
10
11
  import { variantToken } from "../../types/variants.js";
11
12
 
@@ -16,6 +17,7 @@
16
17
  variant,
17
18
  class: cls = "",
18
19
  children,
20
+ ...rest
19
21
  }: {
20
22
  orientation?: "vertical" | "horizontal" | "both";
21
23
  /** Cap the height (any CSS length) — content beyond scrolls. */
@@ -25,7 +27,8 @@
25
27
  variant?: Variant;
26
28
  class?: string;
27
29
  children: Snippet;
28
- } = $props();
30
+ // `style` omitted — the container computes its own (thumb tint vars + height/max-height).
31
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "style"> = $props();
29
32
 
30
33
  const overflow = $derived(
31
34
  orientation === "horizontal"
@@ -43,7 +46,7 @@
43
46
  );
44
47
  </script>
45
48
 
46
- <div class="ui-scroll {overflow} {cls}" {style}>
49
+ <div {...rest} class="ui-scroll {overflow} {cls}" {style}>
47
50
  {@render children()}
48
51
  </div>
49
52
 
@@ -1,4 +1,5 @@
1
1
  import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
2
3
  import type { Variant } from "../../types/variants.js";
3
4
  type $$ComponentProps = {
4
5
  orientation?: "vertical" | "horizontal" | "both";
@@ -9,7 +10,7 @@ type $$ComponentProps = {
9
10
  variant?: Variant;
10
11
  class?: string;
11
12
  children: Snippet;
12
- };
13
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "style">;
13
14
  declare const ScrollArea: import("svelte").Component<$$ComponentProps, {}, "">;
14
15
  type ScrollArea = ReturnType<typeof ScrollArea>;
15
16
  export default ScrollArea;
@@ -128,6 +128,7 @@
128
128
  import IconChevronRight from "~icons/mdi/chevron-right";
129
129
  import IconChevronUp from "~icons/mdi/chevron-up";
130
130
  import IconChevronDown from "~icons/mdi/chevron-down";
131
+ import type { HTMLAttributes } from "svelte/elements";
131
132
  import type { Placement } from "../../positioning/anchored.js";
132
133
  import type { Size } from "../../types/sizes.js";
133
134
  import { variantToken, type Variant } from "../../types/variants.js";
@@ -156,6 +157,7 @@
156
157
  activeMode = $bindable(),
157
158
  publishWidthVar,
158
159
  class: additionalClass = "",
160
+ ...rest
159
161
  }: {
160
162
  items?: SideBarMenuItem[];
161
163
  bottomItems?: SideBarMenuItem[];
@@ -244,7 +246,10 @@
244
246
  * when you run more than one). Unset → nothing published. */
245
247
  publishWidthVar?: boolean | string;
246
248
  class?: string;
247
- } = $props();
249
+ // Leftover HTML attributes are forwarded onto the strip's root `<aside>` (the primary content
250
+ // container; the outer wrapper is `display:contents` in every non-hover-expand mode). `style` is
251
+ // omitted — the aside computes its own (`--sbm-accent`), as does the wrapper (spacer width).
252
+ } & Omit<HTMLAttributes<HTMLElement>, "class" | "style"> = $props();
248
253
 
249
254
  // Per-instance, hydration-stable id prefix so popout DOM ids are unique when more than one
250
255
  // SideBarMenu renders on a page (otherwise `sbm-popout-top-1` collides, breaking `aria-controls`
@@ -1174,6 +1179,7 @@
1174
1179
  style="{hoverExpandActive ? `width: ${collapsedW}px;` : ''}"
1175
1180
  >
1176
1181
  <aside
1182
+ {...rest}
1177
1183
  bind:this={asideRef}
1178
1184
  bind:clientHeight={asideH}
1179
1185
  data-sbm-aside={uid}
@@ -94,6 +94,7 @@ export type SideBarMenuItem = {
94
94
  * the default `currentPath` segment-boundary match against `link`. */
95
95
  activeMatch?: SideBarMenuActiveRule;
96
96
  };
97
+ import type { HTMLAttributes } from "svelte/elements";
97
98
  import type { Size } from "../../types/sizes.js";
98
99
  import { type Variant } from "../../types/variants.js";
99
100
  import { type Breakpoint } from "../../types/breakpoints.js";
@@ -186,7 +187,7 @@ type $$ComponentProps = {
186
187
  * when you run more than one). Unset → nothing published. */
187
188
  publishWidthVar?: boolean | string;
188
189
  class?: string;
189
- };
190
+ } & Omit<HTMLAttributes<HTMLElement>, "class" | "style">;
190
191
  declare const SideBarMenu: import("svelte").Component<$$ComponentProps, {}, "open" | "stepLevel" | "api" | "activeMode">;
191
192
  type SideBarMenu = ReturnType<typeof SideBarMenu>;
192
193
  export default SideBarMenu;
@@ -12,6 +12,7 @@
12
12
  import { variantToken } from "../../types/variants.js";
13
13
  import type { Size } from "../../types/sizes.js";
14
14
  import { responsiveClasses, type Responsive } from "../../types/responsive.js";
15
+ import type { HTMLAttributes } from "svelte/elements";
15
16
 
16
17
  let {
17
18
  value = $bindable(0),
@@ -31,6 +32,7 @@
31
32
  required = false,
32
33
  id,
33
34
  class: cls = "",
35
+ ...rest
34
36
  }: {
35
37
  value?: number | [number, number];
36
38
  min?: number;
@@ -49,7 +51,7 @@
49
51
  required?: boolean;
50
52
  id?: string;
51
53
  class?: string;
52
- } = $props();
54
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "id"> = $props();
53
55
 
54
56
  const controlId = id ?? nextFieldId();
55
57
  const isRange = $derived(range || Array.isArray(value));
@@ -166,7 +168,7 @@
166
168
 
167
169
  <FieldChrome {label} {aside} {error} {description} {required} {controlId} {size} class={cls}>
168
170
  {#snippet control({ describedBy })}
169
- <div class="flex items-center gap-3 select-none">
171
+ <div {...rest} class="flex items-center gap-3 select-none">
170
172
  <!-- The track is the click-to-position surface; the thumbs below carry role="slider". -->
171
173
  <!-- svelte-ignore a11y_no_static_element_interactions -->
172
174
  <!-- Disabled keeps pointer events (so the not-allowed cursor shows) but every handler no-ops on
@@ -2,6 +2,7 @@ import type { Snippet } from "svelte";
2
2
  import type { Variant } from "../../types/variants.js";
3
3
  import type { Size } from "../../types/sizes.js";
4
4
  import { type Responsive } from "../../types/responsive.js";
5
+ import type { HTMLAttributes } from "svelte/elements";
5
6
  type $$ComponentProps = {
6
7
  value?: number | [number, number];
7
8
  min?: number;
@@ -20,7 +21,7 @@ type $$ComponentProps = {
20
21
  required?: boolean;
21
22
  id?: string;
22
23
  class?: string;
23
- };
24
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "id">;
24
25
  declare const Slider: import("svelte").Component<$$ComponentProps, {}, "value">;
25
26
  type Slider = ReturnType<typeof Slider>;
26
27
  export default Slider;
@@ -8,6 +8,7 @@
8
8
  */
9
9
  -->
10
10
  <script lang="ts">
11
+ import type { HTMLAttributes } from "svelte/elements";
11
12
  import type { Variant } from "../../types/variants.js";
12
13
  import { variantToken } from "../../types/variants.js";
13
14
  import type { Size } from "../../types/sizes.js";
@@ -18,6 +19,7 @@
18
19
  size = "md",
19
20
  label = "Loading",
20
21
  class: cls = "",
22
+ ...rest
21
23
  }: {
22
24
  /** Colour accent. Omit to inherit `currentColor` (e.g. inside a filled Button). */
23
25
  variant?: Variant;
@@ -25,7 +27,7 @@
25
27
  /** Accessible label (visually hidden). */
26
28
  label?: string;
27
29
  class?: string;
28
- } = $props();
30
+ } & Omit<HTMLAttributes<HTMLSpanElement>, "class" | "style"> = $props();
29
31
 
30
32
  // 16 / 20 / 24px rings on the shared size axis.
31
33
  const sizeClass: Record<Size, string> = {
@@ -46,6 +48,7 @@
46
48
  <span
47
49
  role="status"
48
50
  aria-live="polite"
51
+ {...rest}
49
52
  class="inline-block shrink-0 animate-spin rounded-full border-solid align-[-0.125em] {responsiveClasses(
50
53
  size,
51
54
  sizeClass,
@@ -1,3 +1,4 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
1
2
  import type { Variant } from "../../types/variants.js";
2
3
  import type { Size } from "../../types/sizes.js";
3
4
  import { type Responsive } from "../../types/responsive.js";
@@ -8,7 +9,7 @@ type $$ComponentProps = {
8
9
  /** Accessible label (visually hidden). */
9
10
  label?: string;
10
11
  class?: string;
11
- };
12
+ } & Omit<HTMLAttributes<HTMLSpanElement>, "class" | "style">;
12
13
  declare const Spinner: import("svelte").Component<$$ComponentProps, {}, "">;
13
14
  type Spinner = ReturnType<typeof Spinner>;
14
15
  export default Spinner;
@@ -9,6 +9,7 @@
9
9
  import type { Snippet } from "svelte";
10
10
  import type { Variant } from "../../types/variants.js";
11
11
  import { variantToken } from "../../types/variants.js";
12
+ import type { HTMLAttributes } from "svelte/elements";
12
13
 
13
14
  let {
14
15
  start,
@@ -21,6 +22,7 @@
21
22
  variant = "primary",
22
23
  disabled = false,
23
24
  class: cls = "",
25
+ ...rest
24
26
  }: {
25
27
  start: Snippet;
26
28
  end: Snippet;
@@ -33,7 +35,7 @@
33
35
  variant?: Variant;
34
36
  disabled?: boolean;
35
37
  class?: string;
36
- } = $props();
38
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "style"> = $props();
37
39
 
38
40
  const isH = $derived(orientation === "horizontal");
39
41
  const token = $derived(variantToken[variant]);
@@ -82,6 +84,7 @@
82
84
  </script>
83
85
 
84
86
  <div
87
+ {...rest}
85
88
  bind:this={containerEl}
86
89
  class="flex {isH ? 'flex-row' : 'flex-col'} {cls}"
87
90
  style={dragging ? "user-select: none;" : ""}
@@ -1,5 +1,6 @@
1
1
  import type { Snippet } from "svelte";
2
2
  import type { Variant } from "../../types/variants.js";
3
+ import type { HTMLAttributes } from "svelte/elements";
3
4
  type $$ComponentProps = {
4
5
  start: Snippet;
5
6
  end: Snippet;
@@ -12,7 +13,7 @@ type $$ComponentProps = {
12
13
  variant?: Variant;
13
14
  disabled?: boolean;
14
15
  class?: string;
15
- };
16
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class" | "style">;
16
17
  declare const Splitter: import("svelte").Component<$$ComponentProps, {}, "size">;
17
18
  type Splitter = ReturnType<typeof Splitter>;
18
19
  export default Splitter;
@@ -18,6 +18,7 @@
18
18
  import { variantToken } from "../../types/variants.js";
19
19
  import type { Size } from "../../types/sizes.js";
20
20
  import { responsiveClasses, type Responsive } from "../../types/responsive.js";
21
+ import type { HTMLAttributes } from "svelte/elements";
21
22
 
22
23
  let {
23
24
  steps,
@@ -27,6 +28,7 @@
27
28
  size = "md",
28
29
  onstep,
29
30
  class: cls = "",
31
+ ...rest
30
32
  }: {
31
33
  steps: StepItem[];
32
34
  current?: number;
@@ -35,7 +37,7 @@
35
37
  size?: Responsive<Size>;
36
38
  onstep?: (index: number) => void;
37
39
  class?: string;
38
- } = $props();
40
+ } & Omit<HTMLAttributes<HTMLElement>, "class"> = $props();
39
41
 
40
42
  const token = $derived(variantToken[variant]);
41
43
  const isH = $derived(orientation === "horizontal");
@@ -62,6 +64,7 @@
62
64
  </script>
63
65
 
64
66
  <ol
67
+ {...rest}
65
68
  class="flex {isH ? 'flex-row items-start' : 'flex-col'} {cls}"
66
69
  aria-label={i18n.messages.progress}
67
70
  >
@@ -7,6 +7,7 @@ export type StepItem = {
7
7
  import type { Variant } from "../../types/variants.js";
8
8
  import type { Size } from "../../types/sizes.js";
9
9
  import { type Responsive } from "../../types/responsive.js";
10
+ import type { HTMLAttributes } from "svelte/elements";
10
11
  type $$ComponentProps = {
11
12
  steps: StepItem[];
12
13
  current?: number;
@@ -15,7 +16,7 @@ type $$ComponentProps = {
15
16
  size?: Responsive<Size>;
16
17
  onstep?: (index: number) => void;
17
18
  class?: string;
18
- };
19
+ } & Omit<HTMLAttributes<HTMLElement>, "class">;
19
20
  declare const Stepper: import("svelte").Component<$$ComponentProps, {}, "current">;
20
21
  type Stepper = ReturnType<typeof Stepper>;
21
22
  export default Stepper;
@@ -5,10 +5,18 @@
5
5
  import type { Size } from "../types/sizes.js";
6
6
  import { responsiveClasses, type Responsive } from "../types/responsive.js";
7
7
  import type { Variant } from "../types/variants.js";
8
+ import type { HTMLAttributes } from "svelte/elements";
8
9
  import { applyTheme, readStoredTheme, type ThemeValue } from "./theme.js";
9
10
 
10
11
  // Shared axes, forwarded to the underlying Select (and the label text tracks size).
11
- let { size = "md", variant }: { size?: Responsive<Size>; variant?: Variant } = $props();
12
+ let {
13
+ size = "md",
14
+ variant,
15
+ ...rest
16
+ }: { size?: Responsive<Size>; variant?: Variant } & Omit<
17
+ HTMLAttributes<HTMLDivElement>,
18
+ "class"
19
+ > = $props();
12
20
  const labelText: Record<Size, string> = { sm: "text-xs", md: "text-sm", lg: "text-base" };
13
21
  const labelClass = $derived(responsiveClasses(size, labelText));
14
22
 
@@ -33,7 +41,7 @@
33
41
  });
34
42
  </script>
35
43
 
36
- <div class="flex items-center gap-2">
44
+ <div {...rest} class="flex items-center gap-2">
37
45
  <label for="theme-selector" class="{labelClass} font-medium text-[var(--ui-color-text)]"
38
46
  >Theme:</label
39
47
  >
@@ -1,10 +1,11 @@
1
1
  import type { Size } from "../types/sizes.js";
2
2
  import { type Responsive } from "../types/responsive.js";
3
3
  import type { Variant } from "../types/variants.js";
4
+ import type { HTMLAttributes } from "svelte/elements";
4
5
  type $$ComponentProps = {
5
6
  size?: Responsive<Size>;
6
7
  variant?: Variant;
7
- };
8
+ } & Omit<HTMLAttributes<HTMLDivElement>, "class">;
8
9
  declare const ThemeSelector: import("svelte").Component<$$ComponentProps, {}, "">;
9
10
  type ThemeSelector = ReturnType<typeof ThemeSelector>;
10
11
  export default ThemeSelector;
@@ -9,12 +9,18 @@
9
9
  import type { Size } from "../types/sizes.js";
10
10
  import type { Variant } from "../types/variants.js";
11
11
  import type { Responsive } from "../types/responsive.js";
12
+ import type { HTMLButtonAttributes } from "svelte/elements";
12
13
  import { applyTheme, readStoredTheme, resolveTheme, type ThemeValue } from "./theme.js";
13
14
  import IconSun from "~icons/mdi/weather-sunny";
14
15
  import IconMoon from "~icons/mdi/weather-night";
15
16
 
16
17
  // Shared axes, forwarded to the underlying Button. Icon-only, so it defaults to the chromeless ghost.
17
- let { size = "md", variant = "ghost" }: { size?: Responsive<Size>; variant?: Variant } = $props();
18
+ let {
19
+ size = "md",
20
+ variant = "ghost",
21
+ ...rest
22
+ }: { size?: Responsive<Size>; variant?: Variant } & Omit<HTMLButtonAttributes, "class"> =
23
+ $props();
18
24
 
19
25
  // The stored value ("auto" until the user picks) and the tracked system preference.
20
26
  let theme = $state<ThemeValue>("auto");
@@ -44,7 +50,10 @@
44
50
  }
45
51
  </script>
46
52
 
53
+ <!-- rest is fully typed on this component's own Props (below); the cast only sidesteps a TS
54
+ "union too complex" limit when spreading a wide attrs type into Button's ButtonProps|AnchorProps. -->
47
55
  <Button
56
+ {...rest as Record<string, unknown>}
48
57
  {size}
49
58
  {variant}
50
59
  onclick={toggle}
@@ -1,10 +1,11 @@
1
1
  import type { Size } from "../types/sizes.js";
2
2
  import type { Variant } from "../types/variants.js";
3
3
  import type { Responsive } from "../types/responsive.js";
4
+ import type { HTMLButtonAttributes } from "svelte/elements";
4
5
  type $$ComponentProps = {
5
6
  size?: Responsive<Size>;
6
7
  variant?: Variant;
7
- };
8
+ } & Omit<HTMLButtonAttributes, "class">;
8
9
  declare const ThemeToggle: import("svelte").Component<$$ComponentProps, {}, "">;
9
10
  type ThemeToggle = ReturnType<typeof ThemeToggle>;
10
11
  export default ThemeToggle;
@@ -8,6 +8,7 @@
8
8
  -->
9
9
  <script lang="ts">
10
10
  import type { Snippet } from "svelte";
11
+ import type { HTMLAttributes } from "svelte/elements";
11
12
  import FieldChrome, { nextFieldId } from "../FieldChrome.svelte";
12
13
  import Chip from "../Chip/Chip.svelte";
13
14
  import type { Variant } from "../../types/variants.js";
@@ -30,6 +31,7 @@
30
31
  id,
31
32
  required = false,
32
33
  class: cls = "",
34
+ ...rest
33
35
  }: {
34
36
  values?: string[];
35
37
  allowDuplicates?: boolean;
@@ -45,7 +47,9 @@
45
47
  id?: string;
46
48
  required?: boolean;
47
49
  class?: string;
48
- } = $props();
50
+ // Forwarded onto the field frame (`<label class="tok-field">`). `style` omitted — that frame
51
+ // computes its own (`--tok-border` vars). `class` goes to FieldChrome's chrome stack (existing).
52
+ } & Omit<HTMLAttributes<HTMLLabelElement>, "class" | "style"> = $props();
49
53
 
50
54
  const controlId = id ?? nextFieldId();
51
55
  const token = $derived(variantToken[variant]);
@@ -108,6 +112,7 @@
108
112
  {#snippet control({ describedBy })}
109
113
  <!-- A <label> so clicking anywhere in the field focuses the input natively (no JS handler). -->
110
114
  <label
115
+ {...rest}
111
116
  for={controlId}
112
117
  class="tok-field flex flex-wrap items-center rounded-[var(--ui-border-radius)] border transition-colors {responsiveClasses(
113
118
  size,
@@ -1,4 +1,5 @@
1
1
  import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
2
3
  import type { Variant } from "../../types/variants.js";
3
4
  import type { Size } from "../../types/sizes.js";
4
5
  import { type Responsive } from "../../types/responsive.js";
@@ -17,7 +18,7 @@ type $$ComponentProps = {
17
18
  id?: string;
18
19
  required?: boolean;
19
20
  class?: string;
20
- };
21
+ } & Omit<HTMLAttributes<HTMLLabelElement>, "class" | "style">;
21
22
  declare const TokenInput: import("svelte").Component<$$ComponentProps, {}, "values">;
22
23
  type TokenInput = ReturnType<typeof TokenInput>;
23
24
  export default TokenInput;
@@ -19,6 +19,7 @@
19
19
 
20
20
  <script lang="ts">
21
21
  import IconChevronRight from "~icons/mdi/chevron-right";
22
+ import type { HTMLAttributes } from "svelte/elements";
22
23
  import type { Variant } from "../../types/variants.js";
23
24
  import { variantToken } from "../../types/variants.js";
24
25
  import type { Size } from "../../types/sizes.js";
@@ -32,6 +33,7 @@
32
33
  variant = "primary",
33
34
  size = "md",
34
35
  class: cls = "",
36
+ ...rest
35
37
  }: {
36
38
  items: TreeNode[];
37
39
  /** Keys of expanded nodes (bindable). */
@@ -42,7 +44,9 @@
42
44
  variant?: Variant;
43
45
  size?: Responsive<Size>;
44
46
  class?: string;
45
- } = $props();
47
+ // `style` omitted — rows compute their own inline style (indent + active tint). `onselect` omitted
48
+ // too: it collides with the DOM `onselect` in HTMLAttributes but has this component's own signature.
49
+ } & Omit<HTMLAttributes<HTMLElement>, "class" | "style" | "onselect"> = $props();
46
50
 
47
51
  const token = $derived(variantToken[variant]);
48
52
  const rowH: Record<Size, string> = { sm: "h-7 text-xs", md: "h-8 text-sm", lg: "h-10 text-base" };
@@ -137,7 +141,12 @@
137
141
  </script>
138
142
 
139
143
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
140
- <ul role="tree" class="flex flex-col {responsiveClasses(size, iconCls)} {cls}" onkeydown={onKeydown}>
144
+ <ul
145
+ {...rest}
146
+ role="tree"
147
+ class="flex flex-col {responsiveClasses(size, iconCls)} {cls}"
148
+ onkeydown={onKeydown}
149
+ >
141
150
  {#each flat as f (f.key)}
142
151
  {@const active = selected === f.key}
143
152
  <li role="none" class="list-none">
@@ -7,6 +7,7 @@ export type TreeNode = {
7
7
  children?: TreeNode[];
8
8
  disabled?: boolean;
9
9
  };
10
+ import type { HTMLAttributes } from "svelte/elements";
10
11
  import type { Variant } from "../../types/variants.js";
11
12
  import type { Size } from "../../types/sizes.js";
12
13
  import { type Responsive } from "../../types/responsive.js";
@@ -20,7 +21,7 @@ type $$ComponentProps = {
20
21
  variant?: Variant;
21
22
  size?: Responsive<Size>;
22
23
  class?: string;
23
- };
24
+ } & Omit<HTMLAttributes<HTMLElement>, "class" | "style" | "onselect">;
24
25
  declare const Tree: import("svelte").Component<$$ComponentProps, {}, "selected" | "expanded">;
25
26
  type Tree = ReturnType<typeof Tree>;
26
27
  export default Tree;
@@ -17,6 +17,18 @@ Most sizeable/themeable components share two props (defined in `types/variants.t
17
17
  - **`size`** — `sm` (24px), `md` (32px, **default**), `lg` (40px). Tied to the theme's
18
18
  `--ui-height-sm` / `--ui-height` / `--ui-height-lg`.
19
19
 
20
+ ## HTML attribute passthrough
21
+
22
+ Components forward the standard HTML attributes you pass — **`class`** (merged onto the root, appended
23
+ last so your classes win), **`data-*`** (e.g. a stable `data-testid` for e2e), **`aria-*`**, **`id`**,
24
+ **`title`**, and event handlers — onto their root element, typed against the matching `HTML*Attributes`.
25
+ So `<Badge data-testid="status" class="ml-2">` or `<Card onmouseenter={…}>` just work and type-check.
26
+
27
+ Exceptions: components that compute their own root **`style`** (themed `color-mix`, dimensions, drag
28
+ transforms — e.g. `Badge`, `Alert`, `Skeleton`, `DataTable`) do **not** accept a `style` override —
29
+ use `class`. Field-shaped components (`Input`, the specialized inputs, `Slider`, `TokenInput`,
30
+ `FileUpload`) route `class` to their outer field wrapper and land other attributes on the control.
31
+
20
32
  ## Field chrome (shared)
21
33
 
22
34
  Every field-shaped component — `Input`, `Select`, `TextArea`, `Checkbox`, `Toggle` (and the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaethtech/svelte-ui",
3
- "version": "0.20.1-dev.102.3c5719c",
3
+ "version": "0.20.1-dev.105.894ecae",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/spaethtech/svelte-ui.git"