@makolabs/ripple 2.5.9 → 3.0.1

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 (186) hide show
  1. package/README.md +403 -497
  2. package/dist/adapters/storage/S3Adapter.d.ts +49 -1
  3. package/dist/adapters/storage/S3Adapter.js +38 -1
  4. package/dist/adapters/storage/types.d.ts +20 -0
  5. package/dist/ai/AIChatInterface.svelte +2 -1
  6. package/dist/ai/AIChatInterface.svelte.d.ts +2 -1
  7. package/dist/ai/CodeRenderer.svelte +7 -2
  8. package/dist/ai/CodeRenderer.svelte.d.ts +2 -1
  9. package/dist/ai/ComposeDropdown.svelte +1 -1
  10. package/dist/ai/MessageBox.svelte +3 -3
  11. package/dist/ai/MessageBox.svelte.d.ts +3 -2
  12. package/dist/ai/ThinkingDisplay.svelte +4 -3
  13. package/dist/ai/ThinkingDisplay.svelte.d.ts +2 -1
  14. package/dist/ai/ai-types.d.ts +55 -1
  15. package/dist/button/Button.svelte +5 -5
  16. package/dist/button/button-types.d.ts +49 -4
  17. package/dist/button/button.d.ts +9 -9
  18. package/dist/button/button.js +6 -6
  19. package/dist/charts/Chart.svelte +8 -16
  20. package/dist/charts/chart-types.d.ts +78 -1
  21. package/dist/drawer/Drawer.svelte +6 -26
  22. package/dist/drawer/drawer-types.d.ts +33 -12
  23. package/dist/drawer/drawer.d.ts +3 -3
  24. package/dist/drawer/drawer.js +1 -1
  25. package/dist/elements/accordion/Accordion.svelte +6 -17
  26. package/dist/elements/accordion/accordion-types.d.ts +53 -6
  27. package/dist/elements/alert/Alert.svelte +3 -0
  28. package/dist/elements/badge/Badge.svelte +1 -1
  29. package/dist/elements/badge/badge-types.d.ts +22 -0
  30. package/dist/elements/badge/badge.d.ts +3 -3
  31. package/dist/elements/badge/badge.js +1 -1
  32. package/dist/elements/combobox/ComboBox.svelte +244 -0
  33. package/dist/elements/combobox/ComboBox.svelte.d.ts +4 -0
  34. package/dist/elements/combobox/combobox-types.d.ts +41 -0
  35. package/dist/elements/combobox/combobox-types.js +1 -0
  36. package/dist/elements/context-menu/ContextMenu.svelte +137 -0
  37. package/dist/elements/context-menu/ContextMenu.svelte.d.ts +4 -0
  38. package/dist/elements/context-menu/context-menu-types.d.ts +40 -0
  39. package/dist/elements/context-menu/context-menu-types.js +1 -0
  40. package/dist/elements/dropdown/Dropdown.svelte +1 -1
  41. package/dist/elements/dropdown/Select.svelte +4 -1
  42. package/dist/elements/dropdown/dropdown-types.d.ts +114 -0
  43. package/dist/elements/dropdown/dropdown.d.ts +3 -3
  44. package/dist/elements/dropdown/dropdown.js +2 -2
  45. package/dist/elements/dropdown/select.d.ts +3 -108
  46. package/dist/elements/dropdown/select.js +38 -47
  47. package/dist/elements/empty-state/EmptyState.svelte +1 -1
  48. package/dist/elements/empty-state/empty-state-types.d.ts +32 -1
  49. package/dist/elements/empty-state/empty-state.d.ts +3 -3
  50. package/dist/elements/empty-state/empty-state.js +2 -2
  51. package/dist/elements/file-upload/FileUpload.svelte +5 -0
  52. package/dist/elements/file-upload/file-upload-types.d.ts +59 -0
  53. package/dist/elements/pagination/Pagination.svelte +53 -21
  54. package/dist/elements/pagination/Pagination.svelte.d.ts +33 -5
  55. package/dist/elements/popover/Popover.svelte +254 -0
  56. package/dist/elements/popover/Popover.svelte.d.ts +4 -0
  57. package/dist/elements/popover/index.d.ts +2 -0
  58. package/dist/elements/popover/index.js +1 -0
  59. package/dist/elements/popover/popover-types.d.ts +60 -0
  60. package/dist/elements/popover/popover-types.js +1 -0
  61. package/dist/elements/progress/Progress.svelte +32 -7
  62. package/dist/elements/progress/progress-types.d.ts +48 -1
  63. package/dist/elements/skeleton/Skeleton.svelte +56 -0
  64. package/dist/elements/skeleton/Skeleton.svelte.d.ts +4 -0
  65. package/dist/elements/skeleton/index.d.ts +2 -0
  66. package/dist/elements/skeleton/index.js +1 -0
  67. package/dist/elements/skeleton/skeleton-types.d.ts +50 -0
  68. package/dist/elements/skeleton/skeleton-types.js +1 -0
  69. package/dist/elements/spinner/Spinner.svelte +1 -1
  70. package/dist/elements/spinner/spinner-types.d.ts +20 -0
  71. package/dist/elements/spinner/spinner.d.ts +3 -3
  72. package/dist/elements/spinner/spinner.js +2 -2
  73. package/dist/elements/tooltip/Tooltip.svelte +108 -11
  74. package/dist/elements/tooltip/tooltip-types.d.ts +49 -1
  75. package/dist/file-browser/FileBrowser.svelte +21 -12
  76. package/dist/filters/CompactFilters.svelte +221 -33
  77. package/dist/filters/CompactFilters.svelte.d.ts +1 -1
  78. package/dist/filters/FilterBar.svelte +184 -0
  79. package/dist/filters/FilterBar.svelte.d.ts +4 -0
  80. package/dist/filters/FilterPopover.svelte +346 -0
  81. package/dist/filters/FilterPopover.svelte.d.ts +4 -0
  82. package/dist/filters/date-presets.d.ts +15 -0
  83. package/dist/filters/date-presets.js +107 -0
  84. package/dist/filters/filter-types.d.ts +69 -3
  85. package/dist/filters/index.d.ts +5 -0
  86. package/dist/filters/index.js +4 -0
  87. package/dist/filters/sync-filters-to-url.svelte.d.ts +37 -0
  88. package/dist/filters/sync-filters-to-url.svelte.js +114 -0
  89. package/dist/forms/Checkbox.svelte +24 -9
  90. package/dist/forms/DateRange.svelte +23 -6
  91. package/dist/forms/Input.svelte +19 -19
  92. package/dist/forms/MarketSelector.svelte +9 -4
  93. package/dist/forms/NumberInput.svelte +14 -18
  94. package/dist/forms/RadioGroup.svelte +127 -0
  95. package/dist/forms/RadioGroup.svelte.d.ts +4 -0
  96. package/dist/forms/SegmentedControl.svelte +11 -4
  97. package/dist/forms/Slider.svelte +72 -3
  98. package/dist/forms/Tags.svelte +44 -14
  99. package/dist/forms/Textarea.svelte +121 -0
  100. package/dist/forms/Textarea.svelte.d.ts +4 -0
  101. package/dist/forms/Toggle.svelte +30 -22
  102. package/dist/forms/calendar/Calendar.svelte +315 -0
  103. package/dist/forms/calendar/Calendar.svelte.d.ts +4 -0
  104. package/dist/forms/calendar/calendar-types.d.ts +54 -0
  105. package/dist/forms/calendar/calendar-types.js +1 -0
  106. package/dist/forms/calendar/index.d.ts +2 -0
  107. package/dist/forms/calendar/index.js +1 -0
  108. package/dist/forms/date-picker/DatePicker.svelte +141 -0
  109. package/dist/forms/date-picker/DatePicker.svelte.d.ts +4 -0
  110. package/dist/forms/date-picker/date-picker-types.d.ts +29 -0
  111. package/dist/forms/date-picker/date-picker-types.js +1 -0
  112. package/dist/forms/form-size.d.ts +37 -0
  113. package/dist/forms/form-size.js +67 -0
  114. package/dist/forms/form-types.d.ts +430 -6
  115. package/dist/forms/market/market-selector-types.d.ts +52 -1
  116. package/dist/forms/segmented-control.d.ts +5 -2
  117. package/dist/forms/segmented-control.js +25 -13
  118. package/dist/forms/slider.d.ts +3 -3
  119. package/dist/forms/slider.js +37 -30
  120. package/dist/funcs/user-management.remote.js +1 -1
  121. package/dist/header/Breadcrumbs.svelte +4 -20
  122. package/dist/header/PageHeader.svelte +6 -14
  123. package/dist/header/breadcrumbs.d.ts +3 -11
  124. package/dist/header/breadcrumbs.js +10 -5
  125. package/dist/header/header-types.d.ts +62 -11
  126. package/dist/index.d.ts +35 -9
  127. package/dist/index.js +24 -4
  128. package/dist/layout/activity-list/ActivityList.svelte +13 -7
  129. package/dist/layout/activity-list/activity-list-types.d.ts +46 -7
  130. package/dist/layout/card/Card.svelte +12 -15
  131. package/dist/layout/card/MetricCard.svelte +50 -32
  132. package/dist/layout/card/card-types.d.ts +114 -4
  133. package/dist/layout/navbar/navbar-types.d.ts +48 -0
  134. package/dist/layout/navbar/navbar.d.ts +3 -3
  135. package/dist/layout/navbar/navbar.js +2 -2
  136. package/dist/layout/sidebar/Sidebar.svelte +87 -11
  137. package/dist/layout/sidebar/sidebar-types.d.ts +60 -1
  138. package/dist/layout/stepper/Stepper.svelte +288 -0
  139. package/dist/layout/stepper/Stepper.svelte.d.ts +4 -0
  140. package/dist/layout/stepper/stepper-types.d.ts +80 -0
  141. package/dist/layout/stepper/stepper-types.js +1 -0
  142. package/dist/layout/table/Table.svelte +91 -85
  143. package/dist/layout/table/table-types.d.ts +148 -24
  144. package/dist/layout/table/table.d.ts +3 -3
  145. package/dist/layout/table/table.js +2 -2
  146. package/dist/layout/tabs/Tab.svelte +6 -2
  147. package/dist/layout/tabs/Tab.svelte.d.ts +4 -1
  148. package/dist/layout/tabs/TabGroup.svelte +9 -2
  149. package/dist/layout/tabs/tabs-types.d.ts +63 -0
  150. package/dist/layout/tabs/tabs.d.ts +3 -3
  151. package/dist/layout/tabs/tabs.js +12 -6
  152. package/dist/modal/ConfirmDialog.svelte +65 -0
  153. package/dist/modal/ConfirmDialog.svelte.d.ts +4 -0
  154. package/dist/modal/Modal.svelte +6 -26
  155. package/dist/modal/confirm-dialog-types.d.ts +39 -0
  156. package/dist/modal/confirm-dialog-types.js +1 -0
  157. package/dist/modal/modal-types.d.ts +51 -12
  158. package/dist/modal/modal.d.ts +3 -3
  159. package/dist/modal/modal.js +3 -3
  160. package/dist/pipeline/Pipeline.svelte +8 -3
  161. package/dist/pipeline/pipeline-types.d.ts +55 -3
  162. package/dist/pipeline/pipeline.d.ts +18 -3
  163. package/dist/pipeline/pipeline.js +7 -2
  164. package/dist/server/s3.d.ts +35 -3
  165. package/dist/sonner/Toaster.svelte +29 -0
  166. package/dist/sonner/Toaster.svelte.d.ts +4 -0
  167. package/dist/sonner/index.d.ts +21 -0
  168. package/dist/sonner/index.js +20 -0
  169. package/dist/user-management/UserManagement.svelte +22 -16
  170. package/dist/user-management/UserModal.svelte +10 -7
  171. package/dist/user-management/UserTable.svelte +16 -17
  172. package/dist/user-management/UserViewModal.svelte +11 -11
  173. package/dist/user-management/user-management-types.d.ts +118 -31
  174. package/dist/variants.d.ts +1 -1
  175. package/dist/variants.js +1 -1
  176. package/package.json +7 -4
  177. package/dist/config/ai.d.ts +0 -13
  178. package/dist/config/ai.js +0 -44
  179. package/dist/elements/empty-state/EmptyStateTestWrapper.svelte +0 -25
  180. package/dist/elements/empty-state/EmptyStateTestWrapper.svelte.d.ts +0 -8
  181. package/dist/elements/tooltip/TooltipTestWrapper.svelte +0 -14
  182. package/dist/elements/tooltip/TooltipTestWrapper.svelte.d.ts +0 -7
  183. package/dist/helper/deprecation.d.ts +0 -14
  184. package/dist/helper/deprecation.js +0 -24
  185. package/dist/modal/ModalFooterTestWrapper.svelte +0 -17
  186. package/dist/modal/ModalFooterTestWrapper.svelte.d.ts +0 -8
@@ -2,53 +2,149 @@ import type { ClassValue } from 'tailwind-variants';
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { Component } from 'svelte';
4
4
  import type { VariantSizes } from '../../index.js';
5
+ /** Single menu entry in a `<Dropdown>` section. */
5
6
  export type DropdownItem = {
7
+ /** Visible text. */
6
8
  label: string;
9
+ /** If set, renders the item as a link; otherwise as a button. Typed to SvelteKit routes. */
7
10
  href?: `/${string}`;
11
+ /** Optional icon rendered on the left. */
8
12
  icon?: Component;
13
+ /** Click handler (ignored when `href` is set — native navigation wins). */
9
14
  onclick?: () => void;
15
+ /** Visually highlight the item as the current route/selection. */
10
16
  active?: boolean;
11
17
  };
18
+ /** A visually grouped subset of items — renders with a separator between sections. */
12
19
  export type DropSection = {
13
20
  items: DropdownItem[];
14
21
  };
22
+ /**
23
+ * Optional header at the top of the dropdown panel (user profile snippet,
24
+ * workspace switcher heading, etc.).
25
+ */
15
26
  export type DropHeaderConfig = {
16
27
  title?: string;
17
28
  subtitle?: string;
29
+ /** Custom header content. Takes precedence over `title`/`subtitle`. */
18
30
  content?: Snippet<[]>;
19
31
  class?: ClassValue;
20
32
  titleClass?: ClassValue;
21
33
  subtitleClass?: ClassValue;
34
+ /** Click handler for the header row. */
22
35
  onclick?: () => void;
23
36
  };
37
+ /**
38
+ * Props for `<Dropdown>` — an action menu attached to a trigger button.
39
+ * Use for context actions, overflow menus, user profile menus, etc.
40
+ *
41
+ * For *form* selection (picking one of many values), use `<Select>`
42
+ * instead — that's a controlled form input.
43
+ *
44
+ * @example
45
+ * ```svelte
46
+ * <Dropdown
47
+ * label="Actions"
48
+ * sections={[
49
+ * {
50
+ * items: [
51
+ * { label: 'Edit', icon: EditIcon, onclick: () => edit() },
52
+ * { label: 'Duplicate', icon: CopyIcon, onclick: () => duplicate() }
53
+ * ]
54
+ * },
55
+ * { items: [{ label: 'Delete', icon: TrashIcon, onclick: () => remove() }] }
56
+ * ]}
57
+ * />
58
+ * ```
59
+ */
24
60
  export type DropdownMenuProps = {
61
+ /** Bindable open state. @default false */
25
62
  open?: boolean;
63
+ /** Ordered sections of items. A divider renders between adjacent sections. */
26
64
  sections: DropSection[];
65
+ /** Trigger button label. */
27
66
  label?: string;
67
+ /** Trigger button icon (rendered instead of or alongside `label`). */
28
68
  icon?: Component;
69
+ /** Classes on the outer positioned wrapper. */
29
70
  containerClass?: ClassValue;
71
+ /** Classes on each item button. */
30
72
  itemClass?: ClassValue;
73
+ /** Classes on the trigger button. */
31
74
  class?: ClassValue;
32
75
  size?: VariantSizes;
33
76
  disabled?: boolean;
77
+ /**
78
+ * Panel placement anchored to the trigger's corner:
79
+ * - `'bottom-right'` (default) — typical dropdown to the right
80
+ * - `'bottom-left'` — dropdown aligned to the trigger's left edge
81
+ * - `'top-right'` / `'top-left'` — upward-opening (use when near page bottom)
82
+ */
34
83
  position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
84
+ /**
85
+ * Explicit panel width. Accepts any CSS value (`'200px'`, `'12rem'`,
86
+ * `'100%'`). @default auto-sized to content
87
+ */
35
88
  width?: string;
89
+ /** Optional header shown above the first section. */
36
90
  header?: DropHeaderConfig;
37
91
  testId?: string;
38
92
  };
93
+ /** Single option in a `<Select>` list. */
39
94
  export type SelectItem = {
95
+ /** Visible text. */
40
96
  label: string;
97
+ /** Underlying form value. */
41
98
  value: string;
42
99
  disabled?: boolean;
100
+ /** Optional icon rendered next to the label. */
43
101
  icon?: Component;
102
+ /** Short helper text shown below the label in the dropdown. */
44
103
  description?: string;
104
+ /**
105
+ * Group name — items with the same `group` are rendered together
106
+ * under a group heading. Items without `group` render at the top.
107
+ */
45
108
  group?: string;
46
109
  };
110
+ /**
111
+ * Props for `<Select>` — a controlled single- or multi-select form input
112
+ * with optional search. For free-typing + filter UX prefer `<ComboBox>`;
113
+ * for a short list of radio-style options use `<RadioGroup>`.
114
+ *
115
+ * @example
116
+ * ```svelte
117
+ * <Select
118
+ * items={[
119
+ * { value: 'draft', label: 'Draft' },
120
+ * { value: 'published', label: 'Published' },
121
+ * { value: 'archived', label: 'Archived' }
122
+ * ]}
123
+ * bind:value={status}
124
+ * />
125
+ * ```
126
+ *
127
+ * @example
128
+ * ```svelte
129
+ * <!-- Multi-select with server-side search -->
130
+ * <Select
131
+ * multiple
132
+ * searchable
133
+ * items={[]}
134
+ * onsearch={async (q) => await api.searchTags(q)}
135
+ * bind:value={selectedTags}
136
+ * />
137
+ * ```
138
+ */
47
139
  export type SelectProps = {
140
+ /** Static list of options. Omit + pair with `onsearch` for server-side search. */
48
141
  items?: SelectItem[];
142
+ /** Bindable selected value (string) or values (`multiple` mode). */
49
143
  value?: string | string[];
144
+ /** Allow selecting multiple items. Changes `value` to `string[]`. @default false */
50
145
  multiple?: boolean;
51
146
  placeholder?: string;
147
+ /** Show a search input at the top of the dropdown. @default false */
52
148
  searchable?: boolean;
53
149
  disabled?: boolean;
54
150
  size?: VariantSizes;
@@ -58,21 +154,39 @@ export type SelectProps = {
58
154
  itemClass?: ClassValue;
59
155
  triggerClass?: ClassValue;
60
156
  searchInputClass?: ClassValue;
157
+ /** Show a × when a value is selected. @default true */
61
158
  clearable?: boolean;
159
+ /** Icon rendered in the trigger (e.g. search icon for an "Add filter" menu). */
62
160
  icon?: Component;
63
161
  iconClass?: ClassValue;
64
162
  errors?: string[];
163
+ /** Fires on selection change. Value shape depends on `multiple`. */
65
164
  onselect?: ({ value }: {
66
165
  value: string | string[];
67
166
  }) => void;
167
+ /** Fires when the dropdown panel opens. */
68
168
  onopen?: () => void;
169
+ /** Fires when the dropdown panel closes. */
69
170
  onclose?: () => void;
70
171
  testId?: string;
172
+ /**
173
+ * Server-side search handler. When set, local filtering is bypassed
174
+ * and this is called (debounced by `debounceMs`) whenever the user
175
+ * types. Return items to display.
176
+ */
71
177
  onsearch?: (query: string) => SelectItem[] | Promise<SelectItem[]>;
178
+ /** Debounce delay for `onsearch`. @default 200 */
72
179
  debounceMs?: number;
180
+ /** Minimum query length before `onsearch` fires. @default 0 */
73
181
  minSearchLength?: number;
182
+ /** Text shown while an async `onsearch` is in flight. @default 'Loading…' */
74
183
  loadingText?: string;
184
+ /** Text shown when the item list is empty. @default 'No results' */
75
185
  emptyText?: string;
186
+ /**
187
+ * Per-item custom rendering. Receives the item and its state flags.
188
+ * Use for rich options (avatars, two-line cards, etc.).
189
+ */
76
190
  itemSnippet?: Snippet<[SelectItem, {
77
191
  highlighted: boolean;
78
192
  selected: boolean;
@@ -30,7 +30,7 @@ export declare const dropdownMenu: import("tailwind-variants").TVReturnType<{
30
30
  headerTitle: string;
31
31
  headerSubtitle: string;
32
32
  };
33
- base: {
33
+ md: {
34
34
  trigger: string;
35
35
  item: string;
36
36
  itemIcon: string;
@@ -113,7 +113,7 @@ export declare const dropdownMenu: import("tailwind-variants").TVReturnType<{
113
113
  headerTitle: string;
114
114
  headerSubtitle: string;
115
115
  };
116
- base: {
116
+ md: {
117
117
  trigger: string;
118
118
  item: string;
119
119
  itemIcon: string;
@@ -196,7 +196,7 @@ export declare const dropdownMenu: import("tailwind-variants").TVReturnType<{
196
196
  headerTitle: string;
197
197
  headerSubtitle: string;
198
198
  };
199
- base: {
199
+ md: {
200
200
  trigger: string;
201
201
  item: string;
202
202
  itemIcon: string;
@@ -44,7 +44,7 @@ export const dropdownMenu = tv({
44
44
  headerTitle: 'text-xs',
45
45
  headerSubtitle: 'text-xs'
46
46
  },
47
- [Size.BASE]: {
47
+ [Size.MD]: {
48
48
  trigger: 'px-3 py-2 text-sm',
49
49
  item: 'px-4 py-2 text-sm',
50
50
  itemIcon: 'mr-3 size-5',
@@ -88,7 +88,7 @@ export const dropdownMenu = tv({
88
88
  },
89
89
  defaultVariants: {
90
90
  position: 'bottom-right',
91
- size: Size.BASE,
91
+ size: Size.MD,
92
92
  isOpen: false,
93
93
  iconOnly: false
94
94
  }
@@ -1,45 +1,10 @@
1
1
  export declare const selectTV: import("tailwind-variants").TVReturnType<{
2
2
  size: {
3
- xs: {
3
+ [k: string]: {
4
4
  trigger: string;
5
5
  triggerIcon: string;
6
- container: string;
7
- item: string;
8
- base: string;
9
- };
10
- sm: {
11
- trigger: string;
12
- triggerIcon: string;
13
- container: string;
14
6
  item: string;
15
- base: string;
16
- };
17
- base: {
18
- trigger: string;
19
- triggerIcon: string;
20
7
  container: string;
21
- item: string;
22
- base: string;
23
- };
24
- lg: {
25
- trigger: string;
26
- triggerIcon: string;
27
- container: string;
28
- item: string;
29
- base: string;
30
- };
31
- xl: {
32
- trigger: string;
33
- triggerIcon: string;
34
- container: string;
35
- item: string;
36
- base: string;
37
- };
38
- "2xl": {
39
- trigger: string;
40
- triggerIcon: string;
41
- container: string;
42
- item: string;
43
8
  base: string;
44
9
  };
45
10
  };
@@ -71,46 +36,11 @@ export declare const selectTV: import("tailwind-variants").TVReturnType<{
71
36
  emptyMessage: string;
72
37
  }, undefined, {
73
38
  size: {
74
- xs: {
75
- trigger: string;
76
- triggerIcon: string;
77
- container: string;
78
- item: string;
79
- base: string;
80
- };
81
- sm: {
82
- trigger: string;
83
- triggerIcon: string;
84
- container: string;
85
- item: string;
86
- base: string;
87
- };
88
- base: {
89
- trigger: string;
90
- triggerIcon: string;
91
- container: string;
92
- item: string;
93
- base: string;
94
- };
95
- lg: {
39
+ [k: string]: {
96
40
  trigger: string;
97
41
  triggerIcon: string;
98
- container: string;
99
42
  item: string;
100
- base: string;
101
- };
102
- xl: {
103
- trigger: string;
104
- triggerIcon: string;
105
43
  container: string;
106
- item: string;
107
- base: string;
108
- };
109
- "2xl": {
110
- trigger: string;
111
- triggerIcon: string;
112
- container: string;
113
- item: string;
114
44
  base: string;
115
45
  };
116
46
  };
@@ -142,46 +72,11 @@ export declare const selectTV: import("tailwind-variants").TVReturnType<{
142
72
  emptyMessage: string;
143
73
  }, import("tailwind-variants").TVReturnType<{
144
74
  size: {
145
- xs: {
75
+ [k: string]: {
146
76
  trigger: string;
147
77
  triggerIcon: string;
148
- container: string;
149
78
  item: string;
150
- base: string;
151
- };
152
- sm: {
153
- trigger: string;
154
- triggerIcon: string;
155
79
  container: string;
156
- item: string;
157
- base: string;
158
- };
159
- base: {
160
- trigger: string;
161
- triggerIcon: string;
162
- container: string;
163
- item: string;
164
- base: string;
165
- };
166
- lg: {
167
- trigger: string;
168
- triggerIcon: string;
169
- container: string;
170
- item: string;
171
- base: string;
172
- };
173
- xl: {
174
- trigger: string;
175
- triggerIcon: string;
176
- container: string;
177
- item: string;
178
- base: string;
179
- };
180
- "2xl": {
181
- trigger: string;
182
- triggerIcon: string;
183
- container: string;
184
- item: string;
185
80
  base: string;
186
81
  };
187
82
  };
@@ -1,15 +1,49 @@
1
1
  import { tv } from 'tailwind-variants';
2
2
  import { Size } from '../../variants.js';
3
+ import { formSizeTokens } from '../../forms/form-size.js';
4
+ // Build the per-size slot overrides from the canonical form-size tokens
5
+ // so Select coordinates visually with Input/Textarea/NumberInput at the
6
+ // same `size` prop. Container max-heights and base min-widths stay here
7
+ // because they're Select-specific (not tied to field sizing).
8
+ const containerHeights = {
9
+ [Size.XS]: 'max-h-32',
10
+ [Size.SM]: 'max-h-40',
11
+ [Size.MD]: 'max-h-56',
12
+ [Size.LG]: 'max-h-64',
13
+ [Size.XL]: 'max-h-72',
14
+ [Size.XXL]: 'max-h-80'
15
+ };
16
+ const minWidths = {
17
+ [Size.XS]: 'min-w-20',
18
+ [Size.SM]: 'min-w-28',
19
+ [Size.MD]: 'min-w-32',
20
+ [Size.LG]: 'min-w-40',
21
+ [Size.XL]: 'min-w-48',
22
+ [Size.XXL]: 'min-w-56'
23
+ };
24
+ const sizeVariants = Object.fromEntries(Object.keys(formSizeTokens).map((key) => {
25
+ const t = formSizeTokens[key];
26
+ return [
27
+ key,
28
+ {
29
+ trigger: `${t.height} ${t.padX} ${t.padY} ${t.text} ${t.gap} ${t.radius} ${t.shadow}`,
30
+ triggerIcon: t.iconSize,
31
+ item: `${t.padX} ${t.padY} ${t.text}`,
32
+ container: containerHeights[key],
33
+ base: minWidths[key]
34
+ }
35
+ ];
36
+ }));
3
37
  export const selectTV = tv({
4
38
  slots: {
5
39
  base: 'w-full',
6
40
  trigger: `relative flex items-center justify-between w-full text-left bg-white border
7
- border-default-300 text-sm focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:border-primary-500 focus-within:ring-primary-500 rounded-lg shadow-xs cursor-pointer transition-colors hover:border-default-400`,
41
+ border-default-300 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:border-primary-500 focus-within:ring-primary-500 cursor-pointer transition-colors hover:border-default-400`,
8
42
  triggerIcon: 'transition-transform duration-200 text-default-500',
9
43
  container: 'absolute z-50 w-full mt-1 bg-white overflow-clip border border-default-200 rounded-md shadow-sm origin-top-left top-full left-0 mt-2',
10
44
  searchInput: 'flex items-center gap-x-3 w-full outline-none px-2 h-10 border-b border-b-default-200',
11
45
  list: 'py-1 max-h-60 overflow-x-clip overflow-y-auto h-full',
12
- item: `w-full px-3 py-2 text-sm text-left
46
+ item: `w-full text-left
13
47
  data-[highlighted=true]:bg-default-100 data-[highlighted=true]:text-default-700
14
48
  data-[selected=true]:bg-info-100 data-[selected=true]:text-info-500 data-[selected=true]:font-medium
15
49
  data-[selected=true]:data-[highlighted=true]:bg-info-200 data-[selected=true]:data-[highlighted=true]:text-info-500
@@ -17,50 +51,7 @@ export const selectTV = tv({
17
51
  emptyMessage: 'px-3 py-2 text-sm text-default-500'
18
52
  },
19
53
  variants: {
20
- size: {
21
- [Size.XS]: {
22
- trigger: 'h-6 px-2 py-1 text-xs gap-1',
23
- triggerIcon: 'h-3 w-3',
24
- container: 'max-h-40',
25
- item: 'px-2 py-1 text-xs',
26
- base: 'min-w-24'
27
- },
28
- [Size.SM]: {
29
- trigger: 'h-8 px-3 py-2 text-sm gap-1.5',
30
- triggerIcon: 'h-3.5 w-3.5',
31
- container: 'max-h-48',
32
- item: 'px-2.5 py-1.5 text-xs',
33
- base: 'min-w-32'
34
- },
35
- [Size.BASE]: {
36
- trigger: 'h-10 px-3 py-2 text-base gap-2',
37
- triggerIcon: 'h-4 w-4',
38
- container: 'max-h-60',
39
- item: 'px-3 py-2 text-sm',
40
- base: 'min-w-40'
41
- },
42
- [Size.LG]: {
43
- trigger: 'h-12 px-3 py-2 text-lg gap-2.5',
44
- triggerIcon: 'h-5 w-5',
45
- container: 'max-h-72',
46
- item: 'px-4 py-2.5 text-base',
47
- base: 'min-w-48'
48
- },
49
- [Size.XL]: {
50
- trigger: 'h-12 px-5 py-3 text-lg gap-3',
51
- triggerIcon: 'h-6 w-6',
52
- container: 'max-h-80',
53
- item: 'px-5 py-3 text-lg',
54
- base: 'min-w-56'
55
- },
56
- [Size.XXL]: {
57
- trigger: 'h-14 px-6 py-3.5 text-xl gap-4',
58
- triggerIcon: 'h-7 w-7',
59
- container: 'max-h-96',
60
- item: 'px-6 py-3.5 text-xl',
61
- base: 'min-w-64'
62
- }
63
- },
54
+ size: sizeVariants,
64
55
  disabled: {
65
56
  true: {
66
57
  trigger: 'opacity-50 cursor-not-allowed hover:border-default-300',
@@ -80,7 +71,7 @@ export const selectTV = tv({
80
71
  }
81
72
  },
82
73
  defaultVariants: {
83
- size: 'base',
74
+ size: 'md',
84
75
  disabled: false,
85
76
  multiple: false,
86
77
  error: false
@@ -8,7 +8,7 @@
8
8
  let {
9
9
  title,
10
10
  description,
11
- size = Size.BASE,
11
+ size = Size.MD,
12
12
  class: className = '',
13
13
  icon,
14
14
  action,
@@ -1,12 +1,43 @@
1
1
  import type { ClassValue } from 'tailwind-variants';
2
2
  import type { Snippet } from 'svelte';
3
- export type EmptyStateSize = 'sm' | 'base' | 'lg' | 'xl';
3
+ /** Density variants specific to EmptyState. */
4
+ export type EmptyStateSize = 'sm' | 'md' | 'lg' | 'xl';
5
+ /**
6
+ * Props for `<EmptyState>` — centered placeholder shown when a list,
7
+ * table, or panel has no content to display yet. Put an illustration,
8
+ * a clear title, a helpful description, and a primary action that
9
+ * breaks the blank-page anxiety.
10
+ *
11
+ * @example
12
+ * ```svelte
13
+ * <EmptyState
14
+ * title="No customers yet"
15
+ * description="Once you import or create a customer they'll appear here."
16
+ * >
17
+ * {#snippet icon()}
18
+ * <svg viewBox="0 0 24 24">…</svg>
19
+ * {/snippet}
20
+ * {#snippet action()}
21
+ * <Button color="primary" onclick={create}>Add customer</Button>
22
+ * {/snippet}
23
+ * </EmptyState>
24
+ * ```
25
+ */
4
26
  export type EmptyStateProps = {
27
+ /** Heading — keep short, focus on what's missing. */
5
28
  title: string;
29
+ /** One-sentence explanation of what's missing and what to do. */
6
30
  description?: string;
31
+ /** @default 'md' */
7
32
  size?: EmptyStateSize;
8
33
  class?: ClassValue;
34
+ /**
35
+ * Icon/illustration snippet. Unlike other components that take an icon
36
+ * `Component`, EmptyState uses a `Snippet` so consumers can inline SVGs
37
+ * or illustrations with arbitrary markup (common empty-state pattern).
38
+ */
9
39
  icon?: Snippet;
40
+ /** Primary action snippet — usually a single Button. */
10
41
  action?: Snippet;
11
42
  testId?: string;
12
43
  };
@@ -6,7 +6,7 @@ export declare const emptyState: import("tailwind-variants").TVReturnType<{
6
6
  title: string;
7
7
  description: string;
8
8
  };
9
- base: {
9
+ md: {
10
10
  wrapper: string;
11
11
  iconWrapper: string;
12
12
  title: string;
@@ -39,7 +39,7 @@ export declare const emptyState: import("tailwind-variants").TVReturnType<{
39
39
  title: string;
40
40
  description: string;
41
41
  };
42
- base: {
42
+ md: {
43
43
  wrapper: string;
44
44
  iconWrapper: string;
45
45
  title: string;
@@ -72,7 +72,7 @@ export declare const emptyState: import("tailwind-variants").TVReturnType<{
72
72
  title: string;
73
73
  description: string;
74
74
  };
75
- base: {
75
+ md: {
76
76
  wrapper: string;
77
77
  iconWrapper: string;
78
78
  title: string;
@@ -16,7 +16,7 @@ export const emptyState = tv({
16
16
  title: 'text-sm',
17
17
  description: 'text-xs'
18
18
  },
19
- [Size.BASE]: {
19
+ [Size.MD]: {
20
20
  wrapper: 'gap-3 p-8',
21
21
  iconWrapper: 'h-10 w-10',
22
22
  title: 'text-base',
@@ -37,6 +37,6 @@ export const emptyState = tv({
37
37
  }
38
38
  },
39
39
  defaultVariants: {
40
- size: Size.BASE
40
+ size: Size.MD
41
41
  }
42
42
  });
@@ -4,6 +4,9 @@
4
4
  import Button from '../../button/Button.svelte';
5
5
  import Spinner from '../spinner/Spinner.svelte';
6
6
  import { Size, Color } from '../../variants.js';
7
+ import { fade } from 'svelte/transition';
8
+ import { flip } from 'svelte/animate';
9
+ import { quintOut } from 'svelte/easing';
7
10
  import type { FileUploadProps, StagedFile } from '../../index.js';
8
11
 
9
12
  let {
@@ -330,6 +333,8 @@
330
333
  class={cn('flex items-center gap-3 px-3 py-2', status === 'success' && 'opacity-60')}
331
334
  data-fileupload-row=""
332
335
  data-status={status}
336
+ transition:fade={{ duration: 300, easing: quintOut }}
337
+ animate:flip={{ duration: 350, easing: quintOut }}
333
338
  >
334
339
  {#if status === 'ready'}
335
340
  <span
@@ -24,6 +24,54 @@ export interface StagedFile {
24
24
  /** Optional error message rendered under the file name while status='error'. */
25
25
  error?: string;
26
26
  }
27
+ /**
28
+ * Props for `<FileUpload>` — a flexible drag-and-drop zone that supports
29
+ * single-file pick, multi-file staging, and "rich mode" with per-file
30
+ * upload progress.
31
+ *
32
+ * **Mode selection** is via `maxFiles`:
33
+ * - `maxFiles=1` (default) → single-file: `onfiles` fires immediately.
34
+ * - `maxFiles>1` (omit `bind:files`) → simple multi-file staging.
35
+ * - `maxFiles>1` + `bind:files` + `clearAfterUpload={false}` → rich mode
36
+ * with per-file status icons + progress bars driven by the consumer.
37
+ *
38
+ * For browsing files already on a remote storage (S3, GDrive), use
39
+ * `<FileBrowser>` instead.
40
+ *
41
+ * @example
42
+ * ```svelte
43
+ * <!-- Simple single-file -->
44
+ * <FileUpload allowedMimeTypes={['.csv']} onfiles={(files) => upload(files[0])} />
45
+ * ```
46
+ *
47
+ * @example
48
+ * ```svelte
49
+ * <!-- Multi-file rich mode with per-row progress -->
50
+ * <script lang="ts">
51
+ * let files = $state<StagedFile[]>([]);
52
+ * async function handleFiles(toUpload: File[]) {
53
+ * for (const file of toUpload) {
54
+ * const item = files.find(f => f.file === file)!;
55
+ * item.status = 'uploading';
56
+ * try {
57
+ * await api.upload(file, (pct) => (item.progress = pct));
58
+ * item.status = 'success';
59
+ * } catch (err) {
60
+ * item.status = 'error';
61
+ * item.error = String(err);
62
+ * }
63
+ * }
64
+ * }
65
+ * </script>
66
+ *
67
+ * <FileUpload
68
+ * maxFiles={10}
69
+ * bind:files
70
+ * clearAfterUpload={false}
71
+ * onfiles={handleFiles}
72
+ * />
73
+ * ```
74
+ */
27
75
  export interface FileUploadProps {
28
76
  /**
29
77
  * Array of allowed file MIME types or extensions.
@@ -119,12 +167,23 @@ export interface FileUploadProps {
119
167
  /** Optional snippet rendered above the dropzone (for titles, selects, banners). */
120
168
  header?: Snippet;
121
169
  }
170
+ /**
171
+ * Props for `<FilesPreview>` — renders a list of already-uploaded files
172
+ * with per-row delete affordance. Pair with `<FileUpload>` to show the
173
+ * "files uploaded so far" beneath the dropzone.
174
+ */
122
175
  export interface FilePreviewProps {
123
176
  files: UploadedFile[];
177
+ /** Fires when the user clicks the × on a file row. */
124
178
  ondelete?: (fileId: string, index: number) => void;
125
179
  class?: ClassValue;
126
180
  testId?: string;
127
181
  }
182
+ /**
183
+ * A file that has already been uploaded to your backend (vs `StagedFile`,
184
+ * which represents a file in flight). Field naming mirrors common
185
+ * server-returned shapes — adapt as needed.
186
+ */
128
187
  export interface UploadedFile {
129
188
  FileID: string;
130
189
  OriginalFilename: string;