sv5ui 1.2.0 → 1.4.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 (71) hide show
  1. package/README.md +16 -11
  2. package/dist/CheckboxGroup/CheckboxGroup.svelte +215 -0
  3. package/dist/CheckboxGroup/CheckboxGroup.svelte.d.ts +5 -0
  4. package/dist/CheckboxGroup/checkbox-group.types.d.ts +130 -0
  5. package/dist/CheckboxGroup/checkbox-group.types.js +1 -0
  6. package/dist/CheckboxGroup/checkbox-group.variants.d.ts +553 -0
  7. package/dist/CheckboxGroup/checkbox-group.variants.js +231 -0
  8. package/dist/CheckboxGroup/index.d.ts +2 -0
  9. package/dist/CheckboxGroup/index.js +1 -0
  10. package/dist/Collapsible/Collapsible.svelte +69 -0
  11. package/dist/Collapsible/Collapsible.svelte.d.ts +6 -0
  12. package/dist/Collapsible/CollapsibleTestWrapper.svelte +17 -0
  13. package/dist/Collapsible/CollapsibleTestWrapper.svelte.d.ts +4 -0
  14. package/dist/Collapsible/collapsible.types.d.ts +75 -0
  15. package/dist/Collapsible/collapsible.types.js +1 -0
  16. package/dist/Collapsible/collapsible.variants.d.ts +53 -0
  17. package/dist/Collapsible/collapsible.variants.js +21 -0
  18. package/dist/Collapsible/index.d.ts +2 -0
  19. package/dist/Collapsible/index.js +1 -0
  20. package/dist/Command/Command.svelte +183 -0
  21. package/dist/Command/Command.svelte.d.ts +6 -0
  22. package/dist/Command/CommandTestWrapper.svelte +13 -0
  23. package/dist/Command/CommandTestWrapper.svelte.d.ts +4 -0
  24. package/dist/Command/command.types.d.ts +98 -0
  25. package/dist/Command/command.types.js +1 -0
  26. package/dist/Command/command.variants.d.ts +226 -0
  27. package/dist/Command/command.variants.js +86 -0
  28. package/dist/Command/index.d.ts +2 -0
  29. package/dist/Command/index.js +1 -0
  30. package/dist/FileUpload/FileUpload.svelte +561 -0
  31. package/dist/FileUpload/FileUpload.svelte.d.ts +8 -0
  32. package/dist/FileUpload/file-upload.types.d.ts +164 -0
  33. package/dist/FileUpload/file-upload.types.js +1 -0
  34. package/dist/FileUpload/file-upload.variants.d.ts +397 -0
  35. package/dist/FileUpload/file-upload.variants.js +224 -0
  36. package/dist/FileUpload/index.d.ts +2 -0
  37. package/dist/FileUpload/index.js +1 -0
  38. package/dist/PinInput/PinInput.svelte +150 -0
  39. package/dist/PinInput/PinInput.svelte.d.ts +6 -0
  40. package/dist/PinInput/index.d.ts +2 -0
  41. package/dist/PinInput/index.js +1 -0
  42. package/dist/PinInput/pin-input.types.d.ts +99 -0
  43. package/dist/PinInput/pin-input.types.js +1 -0
  44. package/dist/PinInput/pin-input.variants.d.ts +303 -0
  45. package/dist/PinInput/pin-input.variants.js +196 -0
  46. package/dist/Select/select.variants.js +1 -1
  47. package/dist/SelectMenu/select-menu.variants.js +1 -1
  48. package/dist/Slider/Slider.svelte +135 -0
  49. package/dist/Slider/Slider.svelte.d.ts +6 -0
  50. package/dist/Slider/index.d.ts +2 -0
  51. package/dist/Slider/index.js +1 -0
  52. package/dist/Slider/slider.types.d.ts +55 -0
  53. package/dist/Slider/slider.types.js +1 -0
  54. package/dist/Slider/slider.variants.d.ts +383 -0
  55. package/dist/Slider/slider.variants.js +102 -0
  56. package/dist/Toast/Toaster.svelte +618 -0
  57. package/dist/Toast/Toaster.svelte.d.ts +5 -0
  58. package/dist/Toast/index.d.ts +4 -0
  59. package/dist/Toast/index.js +2 -0
  60. package/dist/Toast/toast.d.ts +38 -0
  61. package/dist/Toast/toast.js +73 -0
  62. package/dist/Toast/toast.types.d.ts +19 -0
  63. package/dist/Toast/toast.types.js +1 -0
  64. package/dist/Toast/toast.variants.d.ts +7 -0
  65. package/dist/Toast/toast.variants.js +5 -0
  66. package/dist/config.d.ts +5 -0
  67. package/dist/config.js +6 -1
  68. package/dist/index.d.ts +7 -0
  69. package/dist/index.js +7 -0
  70. package/dist/theme.css +36 -0
  71. package/package.json +2 -1
package/README.md CHANGED
@@ -129,17 +129,22 @@ pnpm add sv5ui
129
129
 
130
130
  ### Form
131
131
 
132
- | Component | Description |
133
- | :----------------------------------- | :------------------------------------------------------------------------------------------------------ |
134
- | [**Input**](src/lib/Input) | Text input with 5 variants, icons, avatar, loading state, and FormField integration |
135
- | [**Textarea**](src/lib/Textarea) | Multi-line text input with 5 variants, icons, autoresize with maxrows, and FormField integration |
136
- | [**Select**](src/lib/Select) | Dropdown select with 5 variants, icons, avatars, groups, descriptions, and FormField support |
137
- | [**Switch**](src/lib/Switch) | Toggle switch with 8 colors, 5 sizes, checked/unchecked icons, loading state, and FormField integration |
138
- | [**Checkbox**](src/lib/Checkbox) | Checkbox with 8 colors, 5 sizes, indeterminate state, custom icons, and FormField integration |
139
- | [**RadioGroup**](src/lib/RadioGroup) | Radio group for single-selection with items API, legend, orientation, and FormField integration |
140
- | [**FormField**](src/lib/FormField) | Form control wrapper providing label, description, hint, help, and error handling |
141
- | [**FieldGroup**](src/lib/FieldGroup) | Groups buttons and inputs with seamless borders and shared size/orientation context |
142
- | [**Calendar**](src/lib/Calendar) | Date picker calendar with single, multiple, and range selection modes |
132
+ | Component | Description |
133
+ | :----------------------------------------- | :------------------------------------------------------------------------------------------------------ |
134
+ | [**Input**](src/lib/Input) | Text input with 5 variants, icons, avatar, loading state, and FormField integration |
135
+ | [**Textarea**](src/lib/Textarea) | Multi-line text input with 5 variants, icons, autoresize with maxrows, and FormField integration |
136
+ | [**Select**](src/lib/Select) | Dropdown select with 5 variants, icons, avatars, groups, descriptions, and FormField support |
137
+ | [**SelectMenu**](src/lib/SelectMenu) | Searchable multi-select menu with chips, groups, and FormField integration |
138
+ | [**Switch**](src/lib/Switch) | Toggle switch with 8 colors, 5 sizes, checked/unchecked icons, loading state, and FormField integration |
139
+ | [**Checkbox**](src/lib/Checkbox) | Checkbox with 8 colors, 5 sizes, indeterminate state, custom icons, and FormField integration |
140
+ | [**CheckboxGroup**](src/lib/CheckboxGroup) | Grouped checkboxes with single/multiple selection, per-item disabled, and FormField integration |
141
+ | [**RadioGroup**](src/lib/RadioGroup) | Radio group for single-selection with items API, legend, orientation, and FormField integration |
142
+ | [**Slider**](src/lib/Slider) | Range slider with single/range values, step, orientation, tooltip labels, and FormField integration |
143
+ | [**PinInput**](src/lib/PinInput) | PIN/OTP input with masking, numeric filtering, OTP autocomplete, and FormField integration |
144
+ | [**FileUpload**](src/lib/FileUpload) | Drag-and-drop file upload with preview list, image thumbnails, accept filter, and multiple files |
145
+ | [**FormField**](src/lib/FormField) | Form control wrapper providing label, description, hint, help, and error handling |
146
+ | [**FieldGroup**](src/lib/FieldGroup) | Groups buttons and inputs with seamless borders and shared size/orientation context |
147
+ | [**Calendar**](src/lib/Calendar) | Date picker calendar with single, multiple, and range selection modes |
143
148
 
144
149
  ## Theming
145
150
 
@@ -0,0 +1,215 @@
1
+ <script lang="ts" module>
2
+ import type { CheckboxGroupProps } from './checkbox-group.types.js'
3
+
4
+ export type Props = CheckboxGroupProps
5
+ </script>
6
+
7
+ <script lang="ts">
8
+ import { Checkbox, Label, useId } from 'bits-ui'
9
+ import { checkboxGroupVariants, checkboxGroupDefaults } from './checkbox-group.variants.js'
10
+ import { getComponentConfig, iconsDefaults } from '../config.js'
11
+ import { getContext } from 'svelte'
12
+ import Icon from '../Icon/Icon.svelte'
13
+ import type { FormFieldProps } from '../FormField/form-field.types.js'
14
+ import type { CheckboxGroupItem } from './checkbox-group.types.js'
15
+
16
+ const config = getComponentConfig('checkboxGroup', checkboxGroupDefaults)
17
+ const icons = getComponentConfig('icons', iconsDefaults)
18
+
19
+ let {
20
+ ref = $bindable(null),
21
+ value = $bindable([]),
22
+ onValueChange,
23
+ items = [],
24
+ ui,
25
+ id,
26
+ name,
27
+ color = config.defaultVariants.color,
28
+ size,
29
+ variant = config.defaultVariants.variant,
30
+ indicator = config.defaultVariants.indicator,
31
+ orientation = config.defaultVariants.orientation,
32
+ disabled = false,
33
+ required = false,
34
+ loading = false,
35
+ loadingIcon = icons.loading,
36
+ icon = icons.check,
37
+ legend,
38
+ legendSlot,
39
+ labelSlot,
40
+ descriptionSlot,
41
+ class: className,
42
+ ...restProps
43
+ }: Props = $props()
44
+
45
+ const formFieldContext = getContext<
46
+ | {
47
+ name?: string
48
+ size: NonNullable<FormFieldProps['size']>
49
+ error?: string | boolean
50
+ ariaId: string
51
+ }
52
+ | undefined
53
+ >('formField')
54
+
55
+ const hasError = $derived(
56
+ formFieldContext?.error !== undefined && formFieldContext?.error !== false
57
+ )
58
+ const resolvedSize = $derived(size ?? formFieldContext?.size ?? config.defaultVariants.size)
59
+ const resolvedColor = $derived(hasError ? 'error' : color)
60
+ const autoId = useId()
61
+ const resolvedId = $derived(id ?? formFieldContext?.ariaId ?? autoId)
62
+ const resolvedName = $derived(name ?? formFieldContext?.name)
63
+ const isDisabled = $derived(disabled || loading)
64
+
65
+ const ariaDescribedBy = $derived(
66
+ !formFieldContext
67
+ ? undefined
68
+ : hasError
69
+ ? `${formFieldContext.ariaId}-error`
70
+ : `${formFieldContext.ariaId}-description ${formFieldContext.ariaId}-help`
71
+ )
72
+
73
+ const slots = $derived(
74
+ checkboxGroupVariants({
75
+ color: resolvedColor,
76
+ size: resolvedSize,
77
+ variant,
78
+ indicator,
79
+ orientation,
80
+ loading,
81
+ required,
82
+ disabled: isDisabled ? true : undefined
83
+ })
84
+ )
85
+
86
+ const layoutClasses = $derived.by(() => ({
87
+ root: slots.root({ class: [config.slots.root, className, ui?.root] }),
88
+ fieldset: slots.fieldset({ class: [config.slots.fieldset, ui?.fieldset] }),
89
+ legend: slots.legend({ class: [config.slots.legend, ui?.legend] }),
90
+ item: slots.item({ class: [config.slots.item, ui?.item] }),
91
+ container: slots.container({ class: [config.slots.container, ui?.container] }),
92
+ wrapper: slots.wrapper({ class: [config.slots.wrapper, ui?.wrapper] })
93
+ }))
94
+
95
+ const elementClasses = $derived.by(() => ({
96
+ base: slots.base({ class: [config.slots.base, ui?.base] }),
97
+ indicator: slots.indicator({ class: [config.slots.indicator, ui?.indicator] }),
98
+ icon: slots.icon({ class: [config.slots.icon, ui?.icon] }),
99
+ label: slots.label({ class: [config.slots.label, ui?.label] }),
100
+ description: slots.description({ class: [config.slots.description, ui?.description] })
101
+ }))
102
+
103
+ function toggleItem(itemValue: string, checked: boolean) {
104
+ if (checked) {
105
+ value = [...value, itemValue]
106
+ } else {
107
+ value = value.filter((v) => v !== itemValue)
108
+ }
109
+ onValueChange?.(value)
110
+ }
111
+
112
+ function handleCardItemClick(e: MouseEvent, btnId: string, itemDisabled: boolean) {
113
+ if (itemDisabled) return
114
+ if ((e.target as Element).closest('button')) return
115
+ document.getElementById(btnId)?.click()
116
+ }
117
+ </script>
118
+
119
+ {#snippet itemContent(checkboxItem: CheckboxGroupItem)}
120
+ {@const itemId = `${resolvedId}-${checkboxItem.value}`}
121
+ {@const itemDisabled = isDisabled || !!checkboxItem.disabled}
122
+ <div class={layoutClasses.container}>
123
+ <Checkbox.Root
124
+ checked={value.includes(checkboxItem.value)}
125
+ onCheckedChange={(checked) => toggleItem(checkboxItem.value, checked)}
126
+ id={itemId}
127
+ name={resolvedName}
128
+ value={checkboxItem.value}
129
+ disabled={itemDisabled}
130
+ class={elementClasses.base}
131
+ >
132
+ {#snippet children({ checked: isChecked })}
133
+ {#if isChecked || loading}
134
+ <span class={elementClasses.indicator}>
135
+ <Icon name={loading ? loadingIcon : icon} class={elementClasses.icon} />
136
+ </span>
137
+ {/if}
138
+ {/snippet}
139
+ </Checkbox.Root>
140
+ </div>
141
+
142
+ {#if checkboxItem.label || checkboxItem.description || labelSlot || descriptionSlot}
143
+ <div class={layoutClasses.wrapper}>
144
+ {#if labelSlot}
145
+ {@render labelSlot({ item: checkboxItem })}
146
+ {:else if checkboxItem.label}
147
+ {#if variant === 'card'}
148
+ <span
149
+ class={[elementClasses.label, itemDisabled && 'cursor-not-allowed']
150
+ .filter(Boolean)
151
+ .join(' ')}>{checkboxItem.label}</span
152
+ >
153
+ {:else}
154
+ <Label.Root
155
+ for={itemId}
156
+ class={[elementClasses.label, itemDisabled && 'cursor-not-allowed']
157
+ .filter(Boolean)
158
+ .join(' ')}
159
+ >
160
+ {checkboxItem.label}
161
+ </Label.Root>
162
+ {/if}
163
+ {/if}
164
+
165
+ {#if descriptionSlot}
166
+ {@render descriptionSlot({ item: checkboxItem })}
167
+ {:else if checkboxItem.description}
168
+ <p
169
+ class={[elementClasses.description, itemDisabled && 'cursor-not-allowed']
170
+ .filter(Boolean)
171
+ .join(' ')}
172
+ >
173
+ {checkboxItem.description}
174
+ </p>
175
+ {/if}
176
+ </div>
177
+ {/if}
178
+ {/snippet}
179
+
180
+ <div {...restProps} bind:this={ref} class={layoutClasses.root}>
181
+ <fieldset class={layoutClasses.fieldset} aria-describedby={ariaDescribedBy}>
182
+ {#if legend || legendSlot}
183
+ {#if legendSlot}
184
+ {@render legendSlot({ legend })}
185
+ {:else}
186
+ <legend class={layoutClasses.legend}>{legend}</legend>
187
+ {/if}
188
+ {/if}
189
+
190
+ {#each items as checkboxItem (checkboxItem.value)}
191
+ {#if variant === 'card'}
192
+ <div
193
+ role="none"
194
+ class={layoutClasses.item}
195
+ class:opacity-75={checkboxItem.disabled && !isDisabled}
196
+ onclick={(e) =>
197
+ handleCardItemClick(
198
+ e,
199
+ `${resolvedId}-${checkboxItem.value}`,
200
+ isDisabled || !!checkboxItem.disabled
201
+ )}
202
+ >
203
+ {@render itemContent(checkboxItem)}
204
+ </div>
205
+ {:else}
206
+ <div
207
+ class={layoutClasses.item}
208
+ class:opacity-75={checkboxItem.disabled && !isDisabled}
209
+ >
210
+ {@render itemContent(checkboxItem)}
211
+ </div>
212
+ {/if}
213
+ {/each}
214
+ </fieldset>
215
+ </div>
@@ -0,0 +1,5 @@
1
+ import type { CheckboxGroupProps } from './checkbox-group.types.js';
2
+ export type Props = CheckboxGroupProps;
3
+ declare const CheckboxGroup: import("svelte").Component<CheckboxGroupProps, {}, "ref" | "value">;
4
+ type CheckboxGroup = ReturnType<typeof CheckboxGroup>;
5
+ export default CheckboxGroup;
@@ -0,0 +1,130 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { ClassNameValue } from 'tailwind-merge';
4
+ import type { CheckboxGroupVariantProps, CheckboxGroupSlots } from './checkbox-group.variants.js';
5
+ export type CheckboxGroupItem = {
6
+ /**
7
+ * The unique value for this checkbox item.
8
+ */
9
+ value: string;
10
+ /**
11
+ * Label text displayed next to the checkbox.
12
+ */
13
+ label?: string;
14
+ /**
15
+ * Description text displayed below the label.
16
+ */
17
+ description?: string;
18
+ /**
19
+ * Whether this individual checkbox item is disabled.
20
+ * @default false
21
+ */
22
+ disabled?: boolean;
23
+ };
24
+ export type CheckboxGroupProps = Omit<HTMLAttributes<HTMLElement>, 'class'> & {
25
+ /**
26
+ * Bindable reference to the root DOM element.
27
+ */
28
+ ref?: HTMLElement | null;
29
+ /**
30
+ * The list of selected values. Supports two-way binding with `bind:value`.
31
+ * @default []
32
+ */
33
+ value?: string[];
34
+ /**
35
+ * Callback when the selected values change.
36
+ */
37
+ onValueChange?: (value: string[]) => void;
38
+ /**
39
+ * The list of checkbox items to render.
40
+ */
41
+ items?: CheckboxGroupItem[];
42
+ /**
43
+ * Sets the color scheme for the checkboxes.
44
+ * @default 'primary'
45
+ */
46
+ color?: NonNullable<CheckboxGroupVariantProps['color']>;
47
+ /**
48
+ * Controls the dimensions of the checkbox group.
49
+ * @default 'md'
50
+ */
51
+ size?: NonNullable<CheckboxGroupVariantProps['size']>;
52
+ /**
53
+ * Controls the visual style of each checkbox item.
54
+ * @default 'list'
55
+ */
56
+ variant?: NonNullable<CheckboxGroupVariantProps['variant']>;
57
+ /**
58
+ * Controls the position of the checkbox indicator.
59
+ * @default 'start'
60
+ */
61
+ indicator?: NonNullable<CheckboxGroupVariantProps['indicator']>;
62
+ /**
63
+ * Controls the layout direction of the items.
64
+ * @default 'vertical'
65
+ */
66
+ orientation?: NonNullable<CheckboxGroupVariantProps['orientation']>;
67
+ /**
68
+ * The name attribute for the checkbox inputs (used in form submission).
69
+ */
70
+ name?: string;
71
+ /**
72
+ * Whether the checkbox group is disabled.
73
+ * @default false
74
+ */
75
+ disabled?: boolean;
76
+ /**
77
+ * Whether the checkbox group is required.
78
+ * @default false
79
+ */
80
+ required?: boolean;
81
+ /**
82
+ * Renders a loading spinner and disables interaction.
83
+ * @default false
84
+ */
85
+ loading?: boolean;
86
+ /**
87
+ * Icon displayed as the loading indicator.
88
+ * @default Uses `icons.loading` from app config
89
+ */
90
+ loadingIcon?: string;
91
+ /**
92
+ * Icon displayed when a checkbox is checked.
93
+ * @default Uses `icons.check` from app config
94
+ */
95
+ icon?: string;
96
+ /**
97
+ * Legend text displayed above the checkbox group.
98
+ */
99
+ legend?: string;
100
+ /**
101
+ * The HTML id attribute for the checkbox group.
102
+ */
103
+ id?: string;
104
+ /**
105
+ * Custom snippet for the legend.
106
+ */
107
+ legendSlot?: Snippet<[{
108
+ legend?: string;
109
+ }]>;
110
+ /**
111
+ * Custom snippet for each item's label.
112
+ */
113
+ labelSlot?: Snippet<[{
114
+ item: CheckboxGroupItem;
115
+ }]>;
116
+ /**
117
+ * Custom snippet for each item's description.
118
+ */
119
+ descriptionSlot?: Snippet<[{
120
+ item: CheckboxGroupItem;
121
+ }]>;
122
+ /**
123
+ * Additional CSS classes for the root element.
124
+ */
125
+ class?: ClassNameValue;
126
+ /**
127
+ * Override styles for specific checkbox group slots.
128
+ */
129
+ ui?: Partial<Record<CheckboxGroupSlots, ClassNameValue>>;
130
+ };
@@ -0,0 +1 @@
1
+ export {};