sv5ui 1.8.0 → 2.1.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 (92) hide show
  1. package/dist/Accordion/Accordion.svelte +11 -0
  2. package/dist/Alert/alert.types.d.ts +1 -1
  3. package/dist/AvatarGroup/AvatarGroup.svelte +5 -3
  4. package/dist/Badge/badge.types.d.ts +1 -1
  5. package/dist/Button/Button.svelte +7 -6
  6. package/dist/Button/button.types.d.ts +3 -3
  7. package/dist/Calendar/Calendar.svelte +14 -1
  8. package/dist/Collapsible/collapsible.types.d.ts +4 -2
  9. package/dist/Command/command.types.d.ts +4 -2
  10. package/dist/Command/index.d.ts +1 -1
  11. package/dist/ContextMenu/ContextMenu.svelte +1 -1
  12. package/dist/Drawer/Drawer.svelte +7 -3
  13. package/dist/Drawer/DrawerTriggerTestWrapper.svelte +10 -0
  14. package/dist/Drawer/DrawerTriggerTestWrapper.svelte.d.ts +18 -0
  15. package/dist/Drawer/drawer.types.d.ts +13 -2
  16. package/dist/DropdownMenu/DropdownMenu.svelte +1 -3
  17. package/dist/DropdownMenu/DropdownMenuTriggerTestWrapper.svelte +12 -0
  18. package/dist/DropdownMenu/DropdownMenuTriggerTestWrapper.svelte.d.ts +7 -0
  19. package/dist/DropdownMenu/dropdown-menu.types.d.ts +17 -9
  20. package/dist/Editor/Editor.svelte +85 -61
  21. package/dist/Editor/SlashPopup.svelte +8 -1
  22. package/dist/Editor/SlashPopup.svelte.d.ts +2 -0
  23. package/dist/Editor/editor.extensions.d.ts +1 -1
  24. package/dist/Editor/editor.extensions.js +25 -16
  25. package/dist/Editor/editor.schemas.d.ts +1 -0
  26. package/dist/Editor/editor.schemas.js +24 -0
  27. package/dist/Editor/editor.slash.svelte.d.ts +0 -9
  28. package/dist/Editor/editor.slash.svelte.js +33 -7
  29. package/dist/Editor/editor.suggestion.js +23 -0
  30. package/dist/Editor/editor.toolbar.js +0 -8
  31. package/dist/Editor/editor.types.d.ts +20 -0
  32. package/dist/Editor/editor.variants.d.ts +0 -5
  33. package/dist/Editor/editor.variants.js +0 -15
  34. package/dist/Editor/index.d.ts +6 -4
  35. package/dist/Editor/index.js +6 -4
  36. package/dist/FileUpload/FileUpload.svelte +7 -0
  37. package/dist/Icon/icon.types.d.ts +4 -1
  38. package/dist/Input/Input.svelte +22 -16
  39. package/dist/Input/index.d.ts +1 -1
  40. package/dist/Input/input.variants.d.ts +0 -15
  41. package/dist/Input/input.variants.js +1 -20
  42. package/dist/Link/Link.svelte +4 -3
  43. package/dist/Link/link.types.d.ts +2 -2
  44. package/dist/Modal/Modal.svelte +4 -2
  45. package/dist/Modal/ModalTriggerTestWrapper.svelte +10 -0
  46. package/dist/Modal/ModalTriggerTestWrapper.svelte.d.ts +18 -0
  47. package/dist/Modal/modal.types.d.ts +13 -3
  48. package/dist/Pagination/Pagination.svelte +7 -1
  49. package/dist/Pagination/pagination.types.d.ts +4 -1
  50. package/dist/Pagination/pagination.variants.d.ts +0 -72
  51. package/dist/Pagination/pagination.variants.js +6 -30
  52. package/dist/Popover/Popover.svelte +1 -1
  53. package/dist/Popover/popover.types.d.ts +2 -0
  54. package/dist/Progress/Progress.svelte +14 -6
  55. package/dist/RadioGroup/RadioGroup.svelte +3 -1
  56. package/dist/Select/Select.svelte +3 -1
  57. package/dist/Select/select.types.d.ts +5 -9
  58. package/dist/SelectMenu/SelectMenu.svelte +27 -10
  59. package/dist/SelectMenu/SelectMenuFormFieldTestWrapper.svelte +11 -0
  60. package/dist/SelectMenu/SelectMenuFormFieldTestWrapper.svelte.d.ts +7 -0
  61. package/dist/SelectMenu/select-menu.types.d.ts +5 -2
  62. package/dist/SelectMenu/select-menu.variants.d.ts +12 -2
  63. package/dist/SelectMenu/select-menu.variants.js +10 -1
  64. package/dist/Separator/Separator.svelte +9 -2
  65. package/dist/Separator/separator.types.d.ts +6 -1
  66. package/dist/Separator/separator.variants.d.ts +25 -0
  67. package/dist/Separator/separator.variants.js +7 -1
  68. package/dist/Skeleton/Skeleton.svelte +3 -5
  69. package/dist/Slideover/Slideover.svelte +4 -2
  70. package/dist/Slideover/SlideoverTriggerTestWrapper.svelte +10 -0
  71. package/dist/Slideover/SlideoverTriggerTestWrapper.svelte.d.ts +18 -0
  72. package/dist/Slideover/slideover.types.d.ts +13 -3
  73. package/dist/Stepper/Stepper.svelte +1 -3
  74. package/dist/Switch/Switch.svelte +12 -17
  75. package/dist/Table/table.utils.d.ts +7 -4
  76. package/dist/Table/table.utils.js +26 -25
  77. package/dist/Tabs/Tabs.svelte +4 -2
  78. package/dist/Tabs/tabs.types.d.ts +4 -6
  79. package/dist/ThemeModeButton/ThemeModeButton.svelte +4 -3
  80. package/dist/Tooltip/Tooltip.svelte +1 -1
  81. package/dist/Tooltip/tooltip.types.d.ts +2 -0
  82. package/dist/hooks/HookContextProbe.svelte +7 -0
  83. package/dist/hooks/HookContextProbe.svelte.d.ts +18 -0
  84. package/dist/hooks/HookContextProvider.svelte +9 -0
  85. package/dist/hooks/HookContextProvider.svelte.d.ts +18 -0
  86. package/dist/hooks/HookEmitProbe.svelte +14 -0
  87. package/dist/hooks/HookEmitProbe.svelte.d.ts +18 -0
  88. package/dist/hooks/index.d.ts +1 -1
  89. package/dist/hooks/index.js +1 -1
  90. package/dist/hooks/useFormField.svelte.d.ts +0 -31
  91. package/dist/hooks/useFormField.svelte.js +0 -21
  92. package/package.json +1 -1
@@ -65,9 +65,6 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
65
65
  trailing: {
66
66
  true: string;
67
67
  };
68
- loading: {
69
- true: string;
70
- };
71
68
  highlight: {
72
69
  true: string;
73
70
  };
@@ -146,9 +143,6 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
146
143
  trailing: {
147
144
  true: string;
148
145
  };
149
- loading: {
150
- true: string;
151
- };
152
146
  highlight: {
153
147
  true: string;
154
148
  };
@@ -227,9 +221,6 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
227
221
  trailing: {
228
222
  true: string;
229
223
  };
230
- loading: {
231
- true: string;
232
- };
233
224
  highlight: {
234
225
  true: string;
235
226
  };
@@ -312,9 +303,6 @@ export declare const inputDefaults: {
312
303
  trailing: {
313
304
  true: string;
314
305
  };
315
- loading: {
316
- true: string;
317
- };
318
306
  highlight: {
319
307
  true: string;
320
308
  };
@@ -393,9 +381,6 @@ export declare const inputDefaults: {
393
381
  trailing: {
394
382
  true: string;
395
383
  };
396
- loading: {
397
- true: string;
398
- };
399
384
  highlight: {
400
385
  true: string;
401
386
  };
@@ -81,9 +81,6 @@ export const inputVariants = tv({
81
81
  trailing: {
82
82
  true: ''
83
83
  },
84
- loading: {
85
- true: ''
86
- },
87
84
  highlight: {
88
85
  true: ''
89
86
  }
@@ -376,23 +373,7 @@ export const inputVariants = tv({
376
373
  { trailing: true, size: 'sm', class: { base: 'pe-8' } },
377
374
  { trailing: true, size: 'md', class: { base: 'pe-9' } },
378
375
  { trailing: true, size: 'lg', class: { base: 'pe-10' } },
379
- { trailing: true, size: 'xl', class: { base: 'pe-12' } },
380
- // ========== LOADING ICON ANIMATION ==========
381
- {
382
- loading: true,
383
- leading: true,
384
- class: {
385
- leadingIcon: 'animate-spin'
386
- }
387
- },
388
- {
389
- loading: true,
390
- leading: false,
391
- trailing: true,
392
- class: {
393
- trailingIcon: 'animate-spin'
394
- }
395
- }
376
+ { trailing: true, size: 'xl', class: { base: 'pe-12' } }
396
377
  ],
397
378
  defaultVariants: {
398
379
  variant: 'outline',
@@ -51,6 +51,7 @@
51
51
 
52
52
  <script lang="ts">
53
53
  import { page } from '$app/state'
54
+ import { twMerge } from 'tailwind-merge'
54
55
  import { linkVariants, linkDefaults } from './link.variants.js'
55
56
  import { getComponentConfig } from '../config.js'
56
57
 
@@ -113,7 +114,7 @@
113
114
 
114
115
  const baseClass = $derived.by(() => {
115
116
  const stateClass = isActive ? activeClass : inactiveClass
116
- if (raw) return [className, stateClass].filter(Boolean).join(' ')
117
+ if (raw) return twMerge(stateClass, className)
117
118
 
118
119
  const slots = linkVariants({ active: isActive, disabled, raw })
119
120
  return slots.base({ class: [config.slots.base, stateClass, className, ui?.base] })
@@ -138,6 +139,7 @@
138
139
  <!-- eslint-disable svelte/no-navigation-without-resolve -->
139
140
  <a
140
141
  bind:this={ref}
142
+ {...restProps}
141
143
  href={disabled ? undefined : href}
142
144
  class={baseClass}
143
145
  target={resolvedTarget}
@@ -147,7 +149,6 @@
147
149
  aria-current={ariaCurrent}
148
150
  tabindex={disabled ? -1 : undefined}
149
151
  onclick={handleClick}
150
- {...restProps}
151
152
  >
152
153
  <!-- eslint-enable svelte/no-navigation-without-resolve -->
153
154
  {@render children?.()}
@@ -155,12 +156,12 @@
155
156
  {:else}
156
157
  <button
157
158
  bind:this={ref}
159
+ {...restProps}
158
160
  type={type ?? 'button'}
159
161
  class={baseClass}
160
162
  {disabled}
161
163
  aria-current={ariaCurrent}
162
164
  onclick={handleClick}
163
- {...restProps}
164
165
  >
165
166
  {@render children?.()}
166
167
  </button>
@@ -1,8 +1,8 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { HTMLAttributes, HTMLButtonAttributes, HTMLAnchorAttributes } from 'svelte/elements';
3
3
  import type { LinkSlots } from './link.variants.js';
4
4
  import type { ClassNameValue } from 'tailwind-merge';
5
- export type LinkProps = Omit<HTMLAttributes<HTMLElement>, 'class'> & {
5
+ export type LinkProps = Omit<HTMLAttributes<HTMLElement>, 'class'> & Pick<HTMLButtonAttributes, 'name' | 'value' | 'form' | 'formaction' | 'formenctype' | 'formmethod' | 'formnovalidate' | 'formtarget' | 'popovertarget' | 'popovertargetaction'> & Pick<HTMLAnchorAttributes, 'download' | 'hreflang' | 'ping' | 'media' | 'referrerpolicy'> & {
6
6
  /**
7
7
  * Bindable reference to the root DOM element.
8
8
  */
@@ -203,8 +203,10 @@
203
203
 
204
204
  <Dialog.Root bind:open onOpenChange={handleOpenChange} {onOpenChangeComplete}>
205
205
  {#if children}
206
- <Dialog.Trigger class={className as string}>
207
- {@render children()}
206
+ <Dialog.Trigger>
207
+ {#snippet child({ props })}
208
+ {@render children({ props })}
209
+ {/snippet}
208
210
  </Dialog.Trigger>
209
211
  {/if}
210
212
 
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ import Modal from './Modal.svelte'
3
+ </script>
4
+
5
+ <Modal title="Trigger test" description="D">
6
+ {#snippet children({ props })}
7
+ <button data-testid="trigger" {...props}>Open</button>
8
+ {/snippet}
9
+ {#snippet body()}<p>Body</p>{/snippet}
10
+ </Modal>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const ModalTriggerTestWrapper: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type ModalTriggerTestWrapper = InstanceType<typeof ModalTriggerTestWrapper>;
18
+ export default ModalTriggerTestWrapper;
@@ -101,10 +101,20 @@ export interface ModalProps extends RootProps, ContentProps {
101
101
  */
102
102
  class?: ClassNameValue;
103
103
  /**
104
- * Default slot content used as the trigger element.
105
- * When provided, clicking this element opens the modal.
104
+ * Trigger content. Spread the provided `props` onto your own focusable
105
+ * element (e.g. a `<Button>`) so the dialog's trigger ARIA and event
106
+ * handlers land on the real control instead of a nested wrapper button.
107
+ *
108
+ * @example
109
+ * ```svelte
110
+ * {#snippet children({ props })}
111
+ * <Button {...props}>Open</Button>
112
+ * {/snippet}
113
+ * ```
106
114
  */
107
- children?: Snippet;
115
+ children?: Snippet<[{
116
+ props: Record<string, unknown>;
117
+ }]>;
108
118
  /**
109
119
  * Custom content slot that replaces the entire default layout
110
120
  * (header, body, footer). Title and description are rendered
@@ -47,7 +47,8 @@
47
47
  nextSlot,
48
48
  lastSlot,
49
49
  ellipsisSlot,
50
- itemSlot
50
+ itemSlot,
51
+ ...restProps
51
52
  }: Props = $props()
52
53
 
53
54
  if (page === undefined) {
@@ -94,6 +95,7 @@
94
95
  </script>
95
96
 
96
97
  <Pagination.Root
98
+ {...restProps}
97
99
  bind:ref
98
100
  count={total}
99
101
  perPage={itemsPerPage}
@@ -144,6 +146,7 @@
144
146
  square
145
147
  {size}
146
148
  class={classes.prev}
149
+ aria-label="Previous page"
147
150
  >
148
151
  {@render prevSlot({ page: page!, disabled: prevDisabled })}
149
152
  </ButtonComponent>
@@ -156,6 +159,7 @@
156
159
  {size}
157
160
  icon={prevIcon}
158
161
  class={classes.prev}
162
+ aria-label="Previous page"
159
163
  />
160
164
  {/if}
161
165
  {/snippet}
@@ -196,6 +200,7 @@
196
200
  square
197
201
  {size}
198
202
  class={classes.next}
203
+ aria-label="Next page"
199
204
  >
200
205
  {@render nextSlot({ page: page!, disabled: nextDisabled })}
201
206
  </ButtonComponent>
@@ -208,6 +213,7 @@
208
213
  {size}
209
214
  icon={nextIcon}
210
215
  class={classes.next}
216
+ aria-label="Next page"
211
217
  />
212
218
  {/if}
213
219
  {/snippet}
@@ -1,5 +1,6 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import type { ClassNameValue } from 'tailwind-merge';
3
+ import type { PaginationRootProps } from 'bits-ui';
3
4
  import type { PaginationSlots, PaginationVariantProps } from './pagination.variants.js';
4
5
  import type { ButtonProps } from '../Button/button.types.js';
5
6
  /**
@@ -38,7 +39,9 @@ export interface PaginationItemSlotProps {
38
39
  *
39
40
  * @see https://bits-ui.com/docs/components/pagination
40
41
  */
41
- export interface PaginationProps {
42
+ export interface PaginationProps extends Pick<PaginationRootProps, 'id' | 'style' | 'title' | 'role' | 'tabindex' | 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'onclick' | 'onkeydown' | 'onmouseenter' | 'onmouseleave' | 'onfocus' | 'onblur'> {
43
+ /** Custom data attributes are forwarded to the root element. */
44
+ [key: `data-${string}`]: string | number | boolean | null | undefined;
42
45
  /**
43
46
  * Bindable reference to the root DOM element.
44
47
  */
@@ -7,50 +7,30 @@ export declare const paginationVariants: import("tailwind-variants").TVReturnTyp
7
7
  item: string;
8
8
  ellipsis: string;
9
9
  ellipsisIcon: string;
10
- firstIcon: string;
11
- prevIcon: string;
12
- nextIcon: string;
13
- lastIcon: string;
14
10
  };
15
11
  sm: {
16
12
  list: string;
17
13
  item: string;
18
14
  ellipsis: string;
19
15
  ellipsisIcon: string;
20
- firstIcon: string;
21
- prevIcon: string;
22
- nextIcon: string;
23
- lastIcon: string;
24
16
  };
25
17
  md: {
26
18
  list: string;
27
19
  item: string;
28
20
  ellipsis: string;
29
21
  ellipsisIcon: string;
30
- firstIcon: string;
31
- prevIcon: string;
32
- nextIcon: string;
33
- lastIcon: string;
34
22
  };
35
23
  lg: {
36
24
  list: string;
37
25
  item: string;
38
26
  ellipsis: string;
39
27
  ellipsisIcon: string;
40
- firstIcon: string;
41
- prevIcon: string;
42
- nextIcon: string;
43
- lastIcon: string;
44
28
  };
45
29
  xl: {
46
30
  list: string;
47
31
  item: string;
48
32
  ellipsis: string;
49
33
  ellipsisIcon: string;
50
- firstIcon: string;
51
- prevIcon: string;
52
- nextIcon: string;
53
- lastIcon: string;
54
34
  };
55
35
  };
56
36
  disabled: {
@@ -68,10 +48,6 @@ export declare const paginationVariants: import("tailwind-variants").TVReturnTyp
68
48
  next: string;
69
49
  last: string;
70
50
  ellipsisIcon: string;
71
- firstIcon: string;
72
- prevIcon: string;
73
- nextIcon: string;
74
- lastIcon: string;
75
51
  }, undefined, {
76
52
  size: {
77
53
  xs: {
@@ -79,50 +55,30 @@ export declare const paginationVariants: import("tailwind-variants").TVReturnTyp
79
55
  item: string;
80
56
  ellipsis: string;
81
57
  ellipsisIcon: string;
82
- firstIcon: string;
83
- prevIcon: string;
84
- nextIcon: string;
85
- lastIcon: string;
86
58
  };
87
59
  sm: {
88
60
  list: string;
89
61
  item: string;
90
62
  ellipsis: string;
91
63
  ellipsisIcon: string;
92
- firstIcon: string;
93
- prevIcon: string;
94
- nextIcon: string;
95
- lastIcon: string;
96
64
  };
97
65
  md: {
98
66
  list: string;
99
67
  item: string;
100
68
  ellipsis: string;
101
69
  ellipsisIcon: string;
102
- firstIcon: string;
103
- prevIcon: string;
104
- nextIcon: string;
105
- lastIcon: string;
106
70
  };
107
71
  lg: {
108
72
  list: string;
109
73
  item: string;
110
74
  ellipsis: string;
111
75
  ellipsisIcon: string;
112
- firstIcon: string;
113
- prevIcon: string;
114
- nextIcon: string;
115
- lastIcon: string;
116
76
  };
117
77
  xl: {
118
78
  list: string;
119
79
  item: string;
120
80
  ellipsis: string;
121
81
  ellipsisIcon: string;
122
- firstIcon: string;
123
- prevIcon: string;
124
- nextIcon: string;
125
- lastIcon: string;
126
82
  };
127
83
  };
128
84
  disabled: {
@@ -140,10 +96,6 @@ export declare const paginationVariants: import("tailwind-variants").TVReturnTyp
140
96
  next: string;
141
97
  last: string;
142
98
  ellipsisIcon: string;
143
- firstIcon: string;
144
- prevIcon: string;
145
- nextIcon: string;
146
- lastIcon: string;
147
99
  }, import("tailwind-variants").TVReturnType<{
148
100
  size: {
149
101
  xs: {
@@ -151,50 +103,30 @@ export declare const paginationVariants: import("tailwind-variants").TVReturnTyp
151
103
  item: string;
152
104
  ellipsis: string;
153
105
  ellipsisIcon: string;
154
- firstIcon: string;
155
- prevIcon: string;
156
- nextIcon: string;
157
- lastIcon: string;
158
106
  };
159
107
  sm: {
160
108
  list: string;
161
109
  item: string;
162
110
  ellipsis: string;
163
111
  ellipsisIcon: string;
164
- firstIcon: string;
165
- prevIcon: string;
166
- nextIcon: string;
167
- lastIcon: string;
168
112
  };
169
113
  md: {
170
114
  list: string;
171
115
  item: string;
172
116
  ellipsis: string;
173
117
  ellipsisIcon: string;
174
- firstIcon: string;
175
- prevIcon: string;
176
- nextIcon: string;
177
- lastIcon: string;
178
118
  };
179
119
  lg: {
180
120
  list: string;
181
121
  item: string;
182
122
  ellipsis: string;
183
123
  ellipsisIcon: string;
184
- firstIcon: string;
185
- prevIcon: string;
186
- nextIcon: string;
187
- lastIcon: string;
188
124
  };
189
125
  xl: {
190
126
  list: string;
191
127
  item: string;
192
128
  ellipsis: string;
193
129
  ellipsisIcon: string;
194
- firstIcon: string;
195
- prevIcon: string;
196
- nextIcon: string;
197
- lastIcon: string;
198
130
  };
199
131
  };
200
132
  disabled: {
@@ -212,10 +144,6 @@ export declare const paginationVariants: import("tailwind-variants").TVReturnTyp
212
144
  next: string;
213
145
  last: string;
214
146
  ellipsisIcon: string;
215
- firstIcon: string;
216
- prevIcon: string;
217
- nextIcon: string;
218
- lastIcon: string;
219
147
  }, undefined, unknown, unknown, undefined>>;
220
148
  export type PaginationVariantProps = VariantProps<typeof paginationVariants>;
221
149
  export type PaginationSlots = keyof ReturnType<typeof paginationVariants>;
@@ -68,11 +68,7 @@ export const paginationVariants = tv({
68
68
  prev: '',
69
69
  next: '',
70
70
  last: '',
71
- ellipsisIcon: navIcon,
72
- firstIcon: navIcon,
73
- prevIcon: navIcon,
74
- nextIcon: navIcon,
75
- lastIcon: navIcon
71
+ ellipsisIcon: navIcon
76
72
  },
77
73
  variants: {
78
74
  size: {
@@ -80,51 +76,31 @@ export const paginationVariants = tv({
80
76
  list: 'gap-0.5',
81
77
  item: 'size-7 text-xs',
82
78
  ellipsis: 'size-7 text-xs',
83
- ellipsisIcon: 'size-3',
84
- firstIcon: 'size-3',
85
- prevIcon: 'size-3',
86
- nextIcon: 'size-3',
87
- lastIcon: 'size-3'
79
+ ellipsisIcon: 'size-3'
88
80
  },
89
81
  sm: {
90
82
  list: 'gap-0.5',
91
83
  item: 'size-8 text-xs',
92
84
  ellipsis: 'size-8 text-xs',
93
- ellipsisIcon: 'size-3.5',
94
- firstIcon: 'size-3.5',
95
- prevIcon: 'size-3.5',
96
- nextIcon: 'size-3.5',
97
- lastIcon: 'size-3.5'
85
+ ellipsisIcon: 'size-3.5'
98
86
  },
99
87
  md: {
100
88
  list: 'gap-1',
101
89
  item: 'size-9 text-sm',
102
90
  ellipsis: 'size-9 text-sm',
103
- ellipsisIcon: 'size-4',
104
- firstIcon: 'size-4',
105
- prevIcon: 'size-4',
106
- nextIcon: 'size-4',
107
- lastIcon: 'size-4'
91
+ ellipsisIcon: 'size-4'
108
92
  },
109
93
  lg: {
110
94
  list: 'gap-1',
111
95
  item: 'size-10 text-sm',
112
96
  ellipsis: 'size-10 text-sm',
113
- ellipsisIcon: 'size-5',
114
- firstIcon: 'size-5',
115
- prevIcon: 'size-5',
116
- nextIcon: 'size-5',
117
- lastIcon: 'size-5'
97
+ ellipsisIcon: 'size-5'
118
98
  },
119
99
  xl: {
120
100
  list: 'gap-1.5',
121
101
  item: 'size-11 text-base',
122
102
  ellipsis: 'size-11 text-base',
123
- ellipsisIcon: 'size-5',
124
- firstIcon: 'size-5',
125
- prevIcon: 'size-5',
126
- nextIcon: 'size-5',
127
- lastIcon: 'size-5'
103
+ ellipsisIcon: 'size-5'
128
104
  }
129
105
  },
130
106
  disabled: {
@@ -105,7 +105,7 @@
105
105
  {#if children}
106
106
  <Popover.Trigger>
107
107
  {#snippet child({ props })}
108
- <span {...props} class={className as string}>
108
+ <span {...props} class={[className]}>
109
109
  {@render children({ open })}
110
110
  </span>
111
111
  {/snippet}
@@ -5,6 +5,8 @@ import type { PopoverRootPropsWithoutHTML, PopoverContentPropsWithoutHTML, Popov
5
5
  type RootProps = Pick<PopoverRootPropsWithoutHTML, 'open' | 'onOpenChange' | 'onOpenChangeComplete'>;
6
6
  type ContentProps = Pick<PopoverContentPropsWithoutHTML, 'side' | 'sideOffset' | 'align' | 'alignOffset' | 'avoidCollisions' | 'collisionBoundary' | 'collisionPadding' | 'sticky' | 'hideWhenDetached' | 'trapFocus' | 'preventScroll' | 'onOpenAutoFocus' | 'onCloseAutoFocus' | 'onEscapeKeydown' | 'onInteractOutside' | 'forceMount'>;
7
7
  export interface PopoverProps extends RootProps, ContentProps {
8
+ /** Custom data attributes are forwarded to the content element. */
9
+ [key: `data-${string}`]: string | number | boolean | null | undefined;
8
10
  /**
9
11
  * Bindable reference to the content DOM element.
10
12
  */
@@ -80,6 +80,19 @@
80
80
  }
81
81
  })
82
82
 
83
+ const stepClasses = $derived.by(() => {
84
+ const make = (step: 'active' | 'first' | 'last' | 'other') =>
85
+ progressVariants({ size, orientation, inverted, step }).step({
86
+ class: [config.slots.step, ui?.step]
87
+ })
88
+ return {
89
+ active: make('active'),
90
+ first: make('first'),
91
+ last: make('last'),
92
+ other: make('other')
93
+ }
94
+ })
95
+
83
96
  const state = $derived(isIndeterminate ? 'indeterminate' : 'determinate')
84
97
  </script>
85
98
 
@@ -108,12 +121,7 @@
108
121
  {#if hasSteps && Array.isArray(max)}
109
122
  <div class={classes.steps}>
110
123
  {#each max as step, index (index)}
111
- {@const stepClass = progressVariants({
112
- size,
113
- orientation,
114
- inverted,
115
- step: stepVariant(index)
116
- }).step({ class: [config.slots.step, ui?.step] })}
124
+ {@const stepClass = stepClasses[stepVariant(index)]}
117
125
  <div class={stepClass}>
118
126
  {#if stepSlot}
119
127
  {@render stepSlot({ step, index })}
@@ -54,6 +54,7 @@
54
54
  const resolvedId = $derived(id ?? formFieldContext?.ariaId ?? autoId)
55
55
  const resolvedName = $derived(name ?? formFieldContext?.name)
56
56
  const isDisabled = $derived(disabled || loading)
57
+ const legendId = $derived(`${resolvedId}-legend`)
57
58
 
58
59
  const ariaDescribedBy = $derived(
59
60
  !formFieldContext
@@ -186,13 +187,14 @@
186
187
  {orientation}
187
188
  aria-describedby={ariaDescribedBy}
188
189
  aria-invalid={hasError ? true : undefined}
190
+ aria-labelledby={legend && !legendSlot ? legendId : undefined}
189
191
  class={layoutClasses.fieldset}
190
192
  >
191
193
  {#if legend || legendSlot}
192
194
  {#if legendSlot}
193
195
  {@render legendSlot({ legend })}
194
196
  {:else}
195
- <span class={layoutClasses.legend}>{legend}</span>
197
+ <span id={legendId} class={layoutClasses.legend}>{legend}</span>
196
198
  {/if}
197
199
  {/if}
198
200
 
@@ -67,7 +67,8 @@
67
67
  itemLabel: itemLabelSlot,
68
68
  itemTrailing,
69
69
  selected: selectedSlot,
70
- content: contentSlot
70
+ content: contentSlot,
71
+ ...restProps
71
72
  }: Props = $props()
72
73
 
73
74
  // ---- Form context ----
@@ -371,6 +372,7 @@
371
372
  {/if}
372
373
 
373
374
  <Select.Trigger
375
+ {...restProps}
374
376
  id={resolvedId}
375
377
  name={resolvedName}
376
378
  aria-describedby={ariaDescribedBy}
@@ -2,7 +2,7 @@ import type { Snippet } from 'svelte';
2
2
  import type { ClassNameValue } from 'tailwind-merge';
3
3
  import type { SelectVariantProps, SelectSlots } from './select.variants.js';
4
4
  import type { AvatarProps } from '../Avatar/avatar.types.js';
5
- import type { SelectRootPropsWithoutHTML, SelectContentPropsWithoutHTML } from 'bits-ui';
5
+ import type { SelectRootPropsWithoutHTML, SelectContentPropsWithoutHTML, SelectTriggerProps } from 'bits-ui';
6
6
  /**
7
7
  * The value shape for the Select.
8
8
  * - When `multiple` is `false` (or omitted), the value is a single string (or undefined).
@@ -102,7 +102,10 @@ type ContentProps = Pick<SelectContentPropsWithoutHTML, 'side' | 'sideOffset' |
102
102
  *
103
103
  * @see https://bits-ui.com/docs/components/select
104
104
  */
105
- export interface SelectProps extends RootProps, ContentProps {
105
+ type TriggerHTMLProps = Pick<SelectTriggerProps, 'style' | 'title' | 'role' | 'tabindex' | 'aria-label' | 'aria-labelledby' | 'onclick' | 'onkeydown' | 'onmouseenter' | 'onmouseleave' | 'onfocus' | 'onblur'>;
106
+ export interface SelectProps extends RootProps, ContentProps, TriggerHTMLProps {
107
+ /** Custom data attributes are forwarded to the trigger element. */
108
+ [key: `data-${string}`]: string | number | boolean | null | undefined;
106
109
  /**
107
110
  * Bindable reference to the root DOM element.
108
111
  */
@@ -114,13 +117,6 @@ export interface SelectProps extends RootProps, ContentProps {
114
117
  * - When `multiple` is `true`, this is a `string[]`.
115
118
  */
116
119
  value?: string | string[];
117
- /**
118
- * The default selected value when uncontrolled.
119
- *
120
- * - When `multiple` is `false`/omitted, this is a `string`.
121
- * - When `multiple` is `true`, this is a `string[]`.
122
- */
123
- defaultValue?: string | string[];
124
120
  /**
125
121
  * Whether multiple items can be selected at once.
126
122
  * When `true`, `value` becomes a `string[]` and the trigger displays