@placeholderco/placeholder-ui 1.0.12 → 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 (278) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +134 -130
  3. package/dist/app.css +178 -0
  4. package/dist/bootstrap.min.css +3600 -0
  5. package/dist/cards/GitCard.svelte +115 -0
  6. package/dist/cards/GitCard.svelte.d.ts +22 -0
  7. package/dist/display/Avatar.svelte +29 -17
  8. package/dist/display/Avatar.svelte.d.ts +12 -2
  9. package/dist/display/LinkCollection.svelte +40 -18
  10. package/dist/display/LinkCollection.svelte.d.ts +9 -2
  11. package/dist/display/Paper.svelte +31 -19
  12. package/dist/display/Paper.svelte.d.ts +12 -3
  13. package/dist/display/alert/Alert.svelte +129 -0
  14. package/dist/display/alert/Alert.svelte.d.ts +15 -0
  15. package/dist/display/alert/AlertVariant.d.ts +1 -0
  16. package/dist/display/alert/AlertVariant.js +1 -0
  17. package/dist/display/filetree/FileTree.svelte +259 -0
  18. package/dist/display/filetree/FileTree.svelte.d.ts +76 -0
  19. package/dist/display/filetree/FileTreeItem.svelte +396 -0
  20. package/dist/display/filetree/FileTreeItem.svelte.d.ts +40 -0
  21. package/dist/display/filetree/FileTreeNode.d.ts +46 -0
  22. package/dist/display/filetree/FileTreeNode.js +115 -0
  23. package/dist/display/filetree/index.d.ts +5 -0
  24. package/dist/display/filetree/index.js +3 -0
  25. package/dist/editors/CodeMirror.svelte +306 -0
  26. package/dist/editors/CodeMirror.svelte.d.ts +31 -0
  27. package/dist/editors/tiptap/LinkActionMenu.svelte +307 -0
  28. package/dist/editors/tiptap/LinkActionMenu.svelte.d.ts +8 -0
  29. package/dist/editors/tiptap/TipTap.svelte +856 -0
  30. package/dist/editors/tiptap/TipTap.svelte.d.ts +54 -0
  31. package/dist/editors/tiptap/TipTapBubble.svelte +790 -0
  32. package/dist/editors/tiptap/TipTapBubble.svelte.d.ts +44 -0
  33. package/dist/editors/tiptap/collaboration.d.ts +55 -0
  34. package/dist/editors/tiptap/collaboration.js +1 -0
  35. package/dist/editors/tiptap/extensions/Alert.d.ts +18 -0
  36. package/dist/editors/tiptap/extensions/Alert.js +72 -0
  37. package/dist/editors/tiptap/extensions/CodeBlockEditor.d.ts +21 -0
  38. package/dist/editors/tiptap/extensions/CodeBlockEditor.js +326 -0
  39. package/dist/editors/tiptap/extensions/Div.d.ts +19 -0
  40. package/dist/editors/tiptap/extensions/Div.js +89 -0
  41. package/dist/editors/tiptap/extensions/Span.d.ts +5 -0
  42. package/dist/editors/tiptap/extensions/Span.js +56 -0
  43. package/dist/editors/tiptap/extensions/codeBlockEditor.css +236 -0
  44. package/dist/editors/tiptap/extensions/codeBlockLanguages.d.ts +17 -0
  45. package/dist/editors/tiptap/extensions/codeBlockLanguages.js +124 -0
  46. package/dist/editors/tiptap/extensions/index.d.ts +7 -0
  47. package/dist/editors/tiptap/extensions/index.js +5 -0
  48. package/dist/editors/tiptap/toolbar/AlertButton.svelte +261 -0
  49. package/dist/editors/tiptap/toolbar/AlertButton.svelte.d.ts +7 -0
  50. package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte +18 -0
  51. package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte.d.ts +7 -0
  52. package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte +18 -0
  53. package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte.d.ts +7 -0
  54. package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte +18 -0
  55. package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte.d.ts +7 -0
  56. package/dist/editors/tiptap/toolbar/AlignRightButton.svelte +18 -0
  57. package/dist/editors/tiptap/toolbar/AlignRightButton.svelte.d.ts +7 -0
  58. package/dist/editors/tiptap/toolbar/BoldButton.svelte +18 -0
  59. package/dist/editors/tiptap/toolbar/BoldButton.svelte.d.ts +7 -0
  60. package/dist/editors/tiptap/toolbar/BulletListButton.svelte +18 -0
  61. package/dist/editors/tiptap/toolbar/BulletListButton.svelte.d.ts +7 -0
  62. package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte +18 -0
  63. package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte.d.ts +7 -0
  64. package/dist/editors/tiptap/toolbar/CodeButton.svelte +18 -0
  65. package/dist/editors/tiptap/toolbar/CodeButton.svelte.d.ts +7 -0
  66. package/dist/editors/tiptap/toolbar/ColorButton.svelte +299 -0
  67. package/dist/editors/tiptap/toolbar/ColorButton.svelte.d.ts +20 -0
  68. package/dist/editors/tiptap/toolbar/DocumentButton.svelte +58 -0
  69. package/dist/editors/tiptap/toolbar/DocumentButton.svelte.d.ts +9 -0
  70. package/dist/editors/tiptap/toolbar/HeadingButton.svelte +30 -0
  71. package/dist/editors/tiptap/toolbar/HeadingButton.svelte.d.ts +8 -0
  72. package/dist/editors/tiptap/toolbar/HtmlButton.svelte +68 -0
  73. package/dist/editors/tiptap/toolbar/HtmlButton.svelte.d.ts +7 -0
  74. package/dist/editors/tiptap/toolbar/ImageButton.svelte +54 -0
  75. package/dist/editors/tiptap/toolbar/ImageButton.svelte.d.ts +8 -0
  76. package/dist/editors/tiptap/toolbar/ItalicButton.svelte +18 -0
  77. package/dist/editors/tiptap/toolbar/ItalicButton.svelte.d.ts +7 -0
  78. package/dist/editors/tiptap/toolbar/LinkButton.svelte +257 -0
  79. package/dist/editors/tiptap/toolbar/LinkButton.svelte.d.ts +7 -0
  80. package/dist/editors/tiptap/toolbar/OrderedListButton.svelte +18 -0
  81. package/dist/editors/tiptap/toolbar/OrderedListButton.svelte.d.ts +7 -0
  82. package/dist/editors/tiptap/toolbar/RedoButton.svelte +18 -0
  83. package/dist/editors/tiptap/toolbar/RedoButton.svelte.d.ts +7 -0
  84. package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte +18 -0
  85. package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte.d.ts +7 -0
  86. package/dist/editors/tiptap/toolbar/SubscriptButton.svelte +18 -0
  87. package/dist/editors/tiptap/toolbar/SubscriptButton.svelte.d.ts +7 -0
  88. package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte +18 -0
  89. package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte.d.ts +7 -0
  90. package/dist/editors/tiptap/toolbar/TableButton.svelte +258 -0
  91. package/dist/editors/tiptap/toolbar/TableButton.svelte.d.ts +7 -0
  92. package/dist/editors/tiptap/toolbar/ToolbarButton.svelte +84 -0
  93. package/dist/editors/tiptap/toolbar/ToolbarButton.svelte.d.ts +10 -0
  94. package/dist/editors/tiptap/toolbar/UnderlineButton.svelte +18 -0
  95. package/dist/editors/tiptap/toolbar/UnderlineButton.svelte.d.ts +7 -0
  96. package/dist/editors/tiptap/toolbar/UndoButton.svelte +18 -0
  97. package/dist/editors/tiptap/toolbar/UndoButton.svelte.d.ts +7 -0
  98. package/dist/form/Autocomplete.svelte +86 -135
  99. package/dist/form/Autocomplete.svelte.d.ts +6 -8
  100. package/dist/form/AutocompleteMulti.svelte +385 -227
  101. package/dist/form/AutocompleteMulti.svelte.d.ts +59 -10
  102. package/dist/form/Checkbox.svelte +59 -54
  103. package/dist/form/Checkbox.svelte.d.ts +14 -5
  104. package/dist/form/Chips.svelte +29 -13
  105. package/dist/form/Chips.svelte.d.ts +16 -2
  106. package/dist/form/ColorPicker.svelte +957 -0
  107. package/dist/form/ColorPicker.svelte.d.ts +78 -0
  108. package/dist/form/ComboBox.svelte +30 -20
  109. package/dist/form/ComboBox.svelte.d.ts +1 -1
  110. package/dist/form/ComboBoxItemBuilder.svelte +161 -188
  111. package/dist/form/ComboBoxItemBuilder.svelte.d.ts +19 -2
  112. package/dist/form/ComboBoxMulti.svelte +38 -24
  113. package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
  114. package/dist/form/CronBuilder.svelte +84 -67
  115. package/dist/form/CronBuilder.svelte.d.ts +16 -3
  116. package/dist/form/DatePicker.svelte +148 -195
  117. package/dist/form/DateRangePicker.svelte +101 -98
  118. package/dist/form/DateTimePicker.svelte +167 -208
  119. package/dist/form/DateTimePicker.svelte.d.ts +10 -2
  120. package/dist/form/FormGroup.svelte +33 -10
  121. package/dist/form/FormGroup.svelte.d.ts +12 -2
  122. package/dist/form/Number.svelte +70 -47
  123. package/dist/form/Number.svelte.d.ts +36 -6
  124. package/dist/form/Radio.svelte +18 -18
  125. package/dist/form/RadioGroup.svelte +23 -12
  126. package/dist/form/RadioGroup.svelte.d.ts +13 -2
  127. package/dist/form/SegmentedControl.svelte +76 -56
  128. package/dist/form/SegmentedControl.svelte.d.ts +9 -4
  129. package/dist/form/Select.svelte +150 -233
  130. package/dist/form/Select.svelte.d.ts +29 -5
  131. package/dist/form/SelectMulti.svelte +163 -277
  132. package/dist/form/SelectMulti.svelte.d.ts +36 -7
  133. package/dist/form/Slider.svelte +183 -269
  134. package/dist/form/Slider.svelte.d.ts +32 -17
  135. package/dist/form/StringArrayBuilder.svelte +249 -0
  136. package/dist/form/StringArrayBuilder.svelte.d.ts +15 -0
  137. package/dist/form/Switch.svelte +164 -106
  138. package/dist/form/Switch.svelte.d.ts +22 -3
  139. package/dist/form/TextArea.svelte +49 -29
  140. package/dist/form/TextArea.svelte.d.ts +23 -3
  141. package/dist/form/Textbox.svelte +69 -68
  142. package/dist/form/Textbox.svelte.d.ts +32 -4
  143. package/dist/form/TimePicker.svelte +42 -47
  144. package/dist/form/TimePicker.svelte.d.ts +12 -2
  145. package/dist/form/comboBoxCore.svelte.d.ts +99 -0
  146. package/dist/form/comboBoxCore.svelte.js +243 -0
  147. package/dist/icon/Icon.svelte +8 -3
  148. package/dist/icon/Icon.svelte.d.ts +8 -3
  149. package/dist/icon/file-type-bmp.svg +1 -0
  150. package/dist/icon/file-type-csv.svg +1 -0
  151. package/dist/icon/file-type-doc.svg +1 -0
  152. package/dist/icon/file-type-docx.svg +1 -0
  153. package/dist/icon/file-type-jpg.svg +1 -0
  154. package/dist/icon/file-type-pdf.svg +1 -0
  155. package/dist/icon/file-type-png.svg +1 -0
  156. package/dist/icon/file-type-ppt.svg +1 -0
  157. package/dist/icon/file-type-svg.svg +1 -0
  158. package/dist/icon/file-type-txt.svg +1 -0
  159. package/dist/icon/file-type-xls.svg +1 -0
  160. package/dist/icon/file-type-zip.svg +1 -0
  161. package/dist/icon/index.d.ts +166 -151
  162. package/dist/icon/index.js +166 -152
  163. package/dist/icon/logo-placeholder.svg +6 -0
  164. package/dist/icon/source-code.svg +1 -0
  165. package/dist/icon/sun-moon.svg +1 -0
  166. package/dist/icon/table.svg +6 -0
  167. package/dist/index.d.ts +146 -82
  168. package/dist/index.js +77 -78
  169. package/dist/layout/AppShell.svelte +12 -162
  170. package/dist/layout/AppShell.svelte.d.ts +6 -27
  171. package/dist/layout/CustomNavbar.svelte +9 -7
  172. package/dist/layout/CustomNavbar.svelte.d.ts +4 -2
  173. package/dist/layout/Navbar.svelte +161 -129
  174. package/dist/layout/Navbar.svelte.d.ts +29 -15
  175. package/dist/layout/NavbarItemDisplay.svelte +2 -2
  176. package/dist/layout/NavbarItemView.svelte +182 -0
  177. package/dist/layout/NavbarItemView.svelte.d.ts +10 -0
  178. package/dist/layout/Sidenav.svelte +280 -341
  179. package/dist/layout/Sidenav.svelte.d.ts +36 -4
  180. package/dist/models/ComboBoxItem.d.ts +2 -0
  181. package/dist/models/Employee.d.ts +53 -0
  182. package/dist/models/Employee.js +23 -0
  183. package/dist/models/Hyperlink.d.ts +3 -1
  184. package/dist/models/LinkCollectionItem.d.ts +3 -1
  185. package/dist/models/NavbarItem.d.ts +6 -2
  186. package/dist/theme.svelte.d.ts +0 -1
  187. package/dist/theme.svelte.js +46 -58
  188. package/dist/ui/Accordion.svelte +81 -242
  189. package/dist/ui/Accordion.svelte.d.ts +37 -14
  190. package/dist/ui/AccordionItem.svelte +303 -0
  191. package/dist/ui/AccordionItem.svelte.d.ts +21 -0
  192. package/dist/ui/ActionIcon.svelte +25 -21
  193. package/dist/ui/ActionIcon.svelte.d.ts +15 -2
  194. package/dist/ui/Badge.svelte +163 -171
  195. package/dist/ui/Badge.svelte.d.ts +13 -5
  196. package/dist/ui/Button.svelte +178 -205
  197. package/dist/ui/Button.svelte.d.ts +19 -2
  198. package/dist/ui/ButtonVariant.d.ts +15 -1
  199. package/dist/ui/ContextMenu.svelte +146 -0
  200. package/dist/ui/ContextMenu.svelte.d.ts +37 -0
  201. package/dist/ui/ContextMenuList.svelte +188 -0
  202. package/dist/ui/ContextMenuList.svelte.d.ts +12 -0
  203. package/dist/ui/Dialog.svelte +183 -111
  204. package/dist/ui/Dialog.svelte.d.ts +21 -4
  205. package/dist/ui/Drawer.svelte +237 -184
  206. package/dist/ui/Drawer.svelte.d.ts +20 -2
  207. package/dist/ui/Dropdown.svelte +24 -14
  208. package/dist/ui/Dropdown.svelte.d.ts +11 -2
  209. package/dist/ui/Dropzone.svelte +159 -57
  210. package/dist/ui/Dropzone.svelte.d.ts +29 -2
  211. package/dist/ui/Link.svelte +12 -4
  212. package/dist/ui/Link.svelte.d.ts +8 -2
  213. package/dist/ui/Loader.svelte +23 -18
  214. package/dist/ui/Loader.svelte.d.ts +5 -2
  215. package/dist/ui/Logo.svelte +37 -0
  216. package/dist/ui/Logo.svelte.d.ts +16 -0
  217. package/dist/ui/MultiSortable.svelte +287 -0
  218. package/dist/ui/MultiSortable.svelte.d.ts +50 -0
  219. package/dist/ui/Pagination.svelte +15 -9
  220. package/dist/ui/Pagination.svelte.d.ts +6 -2
  221. package/dist/ui/Popover.svelte +43 -65
  222. package/dist/ui/Popover.svelte.d.ts +14 -5
  223. package/dist/ui/ProgressBar.svelte +28 -30
  224. package/dist/ui/ProgressBarVariant.d.ts +7 -1
  225. package/dist/ui/SegmentedControl.svelte +0 -0
  226. package/dist/ui/SegmentedControl.svelte.d.ts +26 -0
  227. package/dist/ui/Sortable.svelte +163 -0
  228. package/dist/ui/Sortable.svelte.d.ts +47 -0
  229. package/dist/ui/Table.svelte +383 -80
  230. package/dist/ui/Table.svelte.d.ts +43 -2
  231. package/dist/ui/Tabs.svelte +22 -18
  232. package/dist/ui/Tabs.svelte.d.ts +6 -2
  233. package/dist/ui/ThemeSwitcher.svelte +26 -7
  234. package/dist/ui/ThemeSwitcher.svelte.d.ts +4 -2
  235. package/dist/ui/Tooltip.svelte +312 -180
  236. package/dist/ui/Tooltip.svelte.d.ts +4 -3
  237. package/dist/uiTheme.svelte.d.ts +86 -0
  238. package/dist/uiTheme.svelte.js +214 -0
  239. package/dist/util/DateFunctions.js +1 -1
  240. package/dist/util/DragDrop.d.ts +50 -0
  241. package/dist/util/DragDrop.js +154 -0
  242. package/dist/util/NavigateTo.js +2 -2
  243. package/dist/util/dayjs.d.ts +4 -0
  244. package/dist/util/dayjs.js +15 -0
  245. package/package.json +66 -26
  246. package/dist/display/Alert.svelte +0 -179
  247. package/dist/display/Alert.svelte.d.ts +0 -13
  248. package/dist/form/FileInput.svelte +0 -235
  249. package/dist/form/FileInput.svelte.d.ts +0 -23
  250. package/dist/form/PasswordInput.svelte +0 -253
  251. package/dist/form/PasswordInput.svelte.d.ts +0 -34
  252. package/dist/form/Rating.svelte +0 -235
  253. package/dist/form/Rating.svelte.d.ts +0 -21
  254. package/dist/styles/components.css +0 -199
  255. package/dist/styles/dark.css +0 -146
  256. package/dist/styles/index.css +0 -116
  257. package/dist/styles/reset.css +0 -110
  258. package/dist/styles/semantic.css +0 -86
  259. package/dist/styles/tokens.css +0 -203
  260. package/dist/styles/utilities.css +0 -523
  261. package/dist/ui/Breadcrumbs.svelte +0 -131
  262. package/dist/ui/Breadcrumbs.svelte.d.ts +0 -16
  263. package/dist/ui/LoadingOverlay.svelte +0 -53
  264. package/dist/ui/LoadingOverlay.svelte.d.ts +0 -11
  265. package/dist/ui/Progress.svelte +0 -191
  266. package/dist/ui/Progress.svelte.d.ts +0 -15
  267. package/dist/ui/RingProgress.svelte +0 -141
  268. package/dist/ui/RingProgress.svelte.d.ts +0 -18
  269. package/dist/ui/Skeleton.svelte +0 -85
  270. package/dist/ui/Skeleton.svelte.d.ts +0 -12
  271. package/dist/ui/Stepper.svelte +0 -355
  272. package/dist/ui/Stepper.svelte.d.ts +0 -24
  273. package/dist/ui/Timeline.svelte +0 -225
  274. package/dist/ui/Timeline.svelte.d.ts +0 -23
  275. /package/dist/{actions → util}/ClickOutside.d.ts +0 -0
  276. /package/dist/{actions → util}/ClickOutside.js +0 -0
  277. /package/dist/{transitions → util}/Transitions.d.ts +0 -0
  278. /package/dist/{transitions → util}/Transitions.js +0 -0
@@ -0,0 +1,249 @@
1
+ <script module lang="ts">
2
+ export interface StringArrayBuilderProps {
3
+ /** Label text displayed above the builder */
4
+ label?: string;
5
+ /** Array of string values (bindable) */
6
+ items?: string[];
7
+ /** Placeholder for value input field */
8
+ placeholder?: string;
9
+ /** Additional CSS classes */
10
+ class?: string;
11
+ /** Callback when items change */
12
+ onchange?: (items: string[]) => void;
13
+ }
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import ActionIcon from '../ui/ActionIcon.svelte';
18
+ import Button from '../ui/Button.svelte';
19
+ import { iconPlus, iconTrash } from '../icon/index.js';
20
+ import FormGroup from './FormGroup.svelte';
21
+
22
+ let {
23
+ label = '',
24
+ items = $bindable([]),
25
+ placeholder = 'Value',
26
+ class: classes = '',
27
+ onchange
28
+ }: StringArrayBuilderProps = $props();
29
+
30
+ let newValue = $state('');
31
+ let valueInputEl: HTMLInputElement | undefined = $state(undefined);
32
+
33
+ function valueExists(value: string, excludeIndex: number | undefined = undefined): boolean {
34
+ return items.some((item, i) => item === value && i !== excludeIndex);
35
+ }
36
+
37
+ let isDuplicateNewValue = $derived(
38
+ newValue.trim() !== '' && valueExists(newValue.trim())
39
+ );
40
+
41
+ function addItem() {
42
+ const trimmed = newValue.trim();
43
+ if (!trimmed) return;
44
+ if (isDuplicateNewValue) return;
45
+
46
+ items = [...items, trimmed];
47
+ newValue = '';
48
+
49
+ notifyChange();
50
+
51
+ valueInputEl?.focus();
52
+ }
53
+
54
+ function removeItem(index: number) {
55
+ items = items.filter((_, i) => i !== index);
56
+ notifyChange();
57
+ }
58
+
59
+ function updateItem(index: number, newVal: string) {
60
+ if (valueExists(newVal, index)) return;
61
+
62
+ items = items.map((item, i) => (i === index ? newVal : item));
63
+ notifyChange();
64
+ }
65
+
66
+ function notifyChange() {
67
+ onchange?.(items);
68
+ }
69
+
70
+ function handleKeyDown(e: KeyboardEvent) {
71
+ if (e.key === 'Enter') {
72
+ e.preventDefault();
73
+ addItem();
74
+ }
75
+ }
76
+ </script>
77
+
78
+ <div class="string-array-builder {classes}">
79
+ {#if label}
80
+ <FormGroup {label}>
81
+ <div></div>
82
+ </FormGroup>
83
+ {/if}
84
+
85
+ <div class="builder-content">
86
+ <!-- Existing items -->
87
+ {#each items as item, index (index)}
88
+ <div class="item-row">
89
+ <div class="col-value">
90
+ <input
91
+ type="text"
92
+ class="item-input"
93
+ value={item}
94
+ oninput={(e) => updateItem(index, e.currentTarget.value)}
95
+ {placeholder}
96
+ />
97
+ </div>
98
+ <div class="col-actions">
99
+ <ActionIcon
100
+ variant="danger-subtle"
101
+ svg={iconTrash}
102
+ size="1rem"
103
+ onclick={() => removeItem(index)}
104
+ tooltip="Remove item"
105
+ />
106
+ </div>
107
+ </div>
108
+ {/each}
109
+
110
+ <!-- Add new item row -->
111
+ <div class="add-row">
112
+ <div class="col-value">
113
+ <input
114
+ bind:this={valueInputEl}
115
+ type="text"
116
+ class="item-input new-input"
117
+ class:error={isDuplicateNewValue}
118
+ value={newValue}
119
+ oninput={(e) => (newValue = e.currentTarget.value)}
120
+ {placeholder}
121
+ onkeydown={handleKeyDown}
122
+ />
123
+ </div>
124
+ <div class="col-actions">
125
+ <ActionIcon
126
+ variant="auto-subtle"
127
+ svg={iconPlus}
128
+ size="1rem"
129
+ onclick={addItem}
130
+ disabled={!newValue.trim() || isDuplicateNewValue}
131
+ tooltip="Add item"
132
+ />
133
+ </div>
134
+ </div>
135
+
136
+ {#if isDuplicateNewValue}
137
+ <div class="error-message">
138
+ Value "{newValue}" already exists
139
+ </div>
140
+ {/if}
141
+
142
+ <!-- Quick add button for mobile/convenience -->
143
+ {#if newValue.trim() && !isDuplicateNewValue}
144
+ <div class="quick-add">
145
+ <Button variant="auto-subtle" onclick={addItem}>
146
+ Add "{newValue}"
147
+ </Button>
148
+ </div>
149
+ {/if}
150
+ </div>
151
+
152
+ <!-- Summary -->
153
+ {#if items.length > 0}
154
+ <div class="summary">
155
+ <span class="summary-count">{items.length} item{items.length !== 1 ? 's' : ''}</span>
156
+ </div>
157
+ {/if}
158
+ </div>
159
+
160
+ <style>
161
+ .string-array-builder {
162
+ width: 100%;
163
+ }
164
+
165
+ .item-row,
166
+ .add-row {
167
+ display: grid;
168
+ grid-template-columns: 1fr 2.5rem;
169
+ gap: 0.5rem;
170
+ padding: 0.25rem 0;
171
+ align-items: center;
172
+ }
173
+
174
+ .col-actions {
175
+ display: flex;
176
+ justify-content: center;
177
+ align-items: center;
178
+ }
179
+
180
+ .item-input {
181
+ width: 100%;
182
+ padding: 0.375rem 0.5rem;
183
+ border: 1px solid var(--border-color);
184
+ border-radius: 0.25rem;
185
+ background-color: var(--input-bg-color);
186
+ color: var(--text-color);
187
+ font-size: 0.875rem;
188
+ transition: border-color 0.15s;
189
+ }
190
+
191
+ .item-input:focus {
192
+ outline: none;
193
+ border-color: var(--accent-color);
194
+ }
195
+
196
+ .item-input::placeholder {
197
+ color: var(--placeholder-color);
198
+ }
199
+
200
+ .new-input {
201
+ background-color: transparent;
202
+ }
203
+
204
+ .item-input.error {
205
+ border-color: var(--danger-text);
206
+ }
207
+
208
+ .item-input.error:focus {
209
+ border-color: var(--danger-text);
210
+ }
211
+
212
+ .error-message {
213
+ padding: 0.375rem 0;
214
+ font-size: 0.75rem;
215
+ color: var(--danger-text);
216
+ }
217
+
218
+ .quick-add {
219
+ padding: 0.5rem 0;
220
+ display: flex;
221
+ justify-content: flex-end;
222
+ }
223
+
224
+ .summary {
225
+ display: flex;
226
+ gap: 1rem;
227
+ padding: 0.5rem 0;
228
+ font-size: 0.875rem;
229
+ color: var(--text-muted);
230
+ margin-top: 0.5rem;
231
+ }
232
+
233
+ .summary-count {
234
+ font-weight: 500;
235
+ }
236
+
237
+ @media (max-width: 480px) {
238
+ .item-row,
239
+ .add-row {
240
+ grid-template-columns: 1fr 2rem;
241
+ gap: 0.25rem;
242
+ }
243
+
244
+ .item-input {
245
+ padding: 0.25rem 0.375rem;
246
+ font-size: 0.8125rem;
247
+ }
248
+ }
249
+ </style>
@@ -0,0 +1,15 @@
1
+ export interface StringArrayBuilderProps {
2
+ /** Label text displayed above the builder */
3
+ label?: string;
4
+ /** Array of string values (bindable) */
5
+ items?: string[];
6
+ /** Placeholder for value input field */
7
+ placeholder?: string;
8
+ /** Additional CSS classes */
9
+ class?: string;
10
+ /** Callback when items change */
11
+ onchange?: (items: string[]) => void;
12
+ }
13
+ declare const StringArrayBuilder: import("svelte").Component<StringArrayBuilderProps, {}, "items">;
14
+ type StringArrayBuilder = ReturnType<typeof StringArrayBuilder>;
15
+ export default StringArrayBuilder;
@@ -1,113 +1,171 @@
1
+ <script module lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ export interface SwitchProps {
5
+ /** Label text displayed above the switch */
6
+ label?: string;
7
+ /** Mark field as required (shows asterisk) */
8
+ required?: boolean;
9
+ /** Whether the switch is on (bindable) */
10
+ checked: boolean;
11
+ /** Disable the switch */
12
+ disabled?: boolean;
13
+ /** CSS classes for the container element */
14
+ containerClass?: string;
15
+ /** CSS classes for the switch element */
16
+ switchClass?: string;
17
+ /** Custom ID for the switch element */
18
+ inputId?: string;
19
+ /** Callback when switch state changes */
20
+ onchange?: (value: boolean) => void;
21
+ /** Show error state styling */
22
+ showError?: boolean;
23
+ /** Error message to display */
24
+ errorText?: string;
25
+ /** Simple tooltip text */
26
+ tooltipText?: string;
27
+ /** Position of the tooltip */
28
+ tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
29
+ /** Rich tooltip content using a Svelte snippet */
30
+ tooltipContent?: Snippet;
31
+ }
32
+ </script>
33
+
1
34
  <script lang="ts">
2
- import FormGroup from "./FormGroup.svelte";
3
-
4
- interface Props {
5
- label: string;
6
- required?: boolean;
7
- checked: boolean;
8
- disabled?: boolean;
9
- containerClass?: string;
10
- switchClass?: string;
11
- onchange?: (value: boolean) => void;
12
- showError?: boolean;
13
- }
14
-
15
- let {
16
- label,
17
- required = false,
18
- checked = $bindable(),
19
- disabled = false,
20
- containerClass,
21
- switchClass,
22
- onchange,
23
- showError,
24
- }: Props = $props();
25
-
26
- function handleClick(event: Event) {
27
- const target = event.target as HTMLElement;
28
- const state = target.getAttribute("aria-checked");
29
- checked = !(state === "true");
30
- onchange?.(checked);
31
- }
35
+ import { Icon, iconInfoCircle } from '../icon/index.js';
36
+ import Tooltip from '../ui/Tooltip.svelte';
37
+
38
+ let {
39
+ label,
40
+ required = false,
41
+ checked = $bindable(),
42
+ disabled = false,
43
+ containerClass = '',
44
+ switchClass = '',
45
+ inputId = undefined,
46
+ onchange,
47
+ showError = false,
48
+ errorText = '',
49
+ tooltipText = undefined,
50
+ tooltipLocation = 'top',
51
+ tooltipContent = undefined
52
+ }: SwitchProps = $props();
53
+
54
+ const nonce = Math.random().toString(36).substring(2, 15);
55
+
56
+ const id = $derived(inputId ? inputId : label ? `switch-${label}` : `switch-${nonce}`);
57
+
58
+ function handleClick() {
59
+ if (disabled) return;
60
+ checked = !checked;
61
+ onchange?.(checked);
62
+ }
32
63
  </script>
33
64
 
34
- <div class="switch-container {containerClass}">
35
- <FormGroup {required} {label}>
36
- <div
37
- class="switch-track {switchClass}"
38
- class:error={showError}
39
- class:disabled
40
- >
41
- <button
42
- role="switch"
43
- aria-checked={checked}
44
- aria-labelledby="form-{label}"
45
- onclick={handleClick}
46
- {disabled}
47
- ></button>
48
- </div>
49
- </FormGroup>
65
+ <div class="switch-container {containerClass} {disabled ? 'disabled' : ''}">
66
+ <label for={id}>
67
+ <span class="label-text"
68
+ >{label}
69
+ {#if required}
70
+ <span class="required">*</span>
71
+ {/if}
72
+ {#if tooltipContent || tooltipText}
73
+ <Tooltip {tooltipContent} location={tooltipLocation} text={tooltipText}>
74
+ <Icon svg={iconInfoCircle} size="1em" stroke="var(--accent-color)" />
75
+ </Tooltip>
76
+ {/if}</span
77
+ >
78
+ <button
79
+ {id}
80
+ role="switch"
81
+ type="button"
82
+ aria-checked={checked}
83
+ aria-label={label || 'Toggle switch'}
84
+ onclick={handleClick}
85
+ class="switch {switchClass} {showError ? 'error' : ''} {disabled ? 'disabled' : ''}"
86
+ {disabled}
87
+ >
88
+ </button>
89
+ </label>
90
+ {#if showError && errorText}
91
+ <div class="error-text">{errorText}</div>
92
+ {/if}
50
93
  </div>
51
94
 
52
95
  <style>
53
- .switch-container {
54
- --switch-track-color: var(--pui-border-disabled);
55
- }
56
-
57
- :global(.dark) .switch-container {
58
- --switch-track-color: var(--pui-color-gray-600);
59
- }
60
-
61
- .switch-track {
62
- display: flex;
63
- align-items: center;
64
- }
65
-
66
- button {
67
- width: 3em;
68
- height: 1.6em;
69
- position: relative;
70
- margin: 0 0 0 var(--pui-spacing-2);
71
- padding: 0;
72
- background: var(--switch-track-color);
73
- border: none;
74
- border-radius: var(--pui-radius-3xl);
75
- cursor: pointer;
76
- transition: background-color var(--pui-transition-fast)
77
- var(--pui-ease-in-out);
78
- }
79
-
80
- button::before {
81
- content: "";
82
- position: absolute;
83
- width: 1.3em;
84
- height: 1.3em;
85
- top: 0.15em;
86
- right: 1.5em;
87
- background: var(--pui-color-white);
88
- border-radius: var(--pui-radius-full);
89
- transition: transform var(--pui-transition-slow) var(--pui-ease-in-out);
90
- }
91
-
92
- button[aria-checked="true"] {
93
- background-color: var(--pui-color-primary);
94
- }
95
-
96
- button[aria-checked="true"]::before {
97
- transform: translateX(1.3em);
98
- }
99
-
100
- button:focus-visible {
101
- outline: 2px solid var(--pui-color-primary);
102
- outline-offset: var(--pui-focus-ring-offset);
103
- }
104
-
105
- .disabled button {
106
- opacity: 0.5;
107
- cursor: not-allowed;
108
- }
109
-
110
- .error button {
111
- outline: 1px solid var(--pui-text-danger);
112
- }
96
+ :root .switch-container {
97
+ --accent-color: var(--ui-primary);
98
+ --gray: #ccc;
99
+ }
100
+
101
+ :global(.dark) .switch-container {
102
+ --accent-color: var(--ui-primary);
103
+ --gray: #444;
104
+ }
105
+
106
+ label {
107
+ display: flex;
108
+ flex-direction: column;
109
+ align-items: flex-start;
110
+ user-select: none;
111
+ cursor: pointer;
112
+ }
113
+
114
+ .disabled label {
115
+ cursor: not-allowed;
116
+ }
117
+
118
+ .switch {
119
+ width: 3em;
120
+ height: 1.6em;
121
+ position: relative;
122
+ margin: 4px 0 0 0;
123
+ background: var(--gray);
124
+ border: none;
125
+ border-radius: 1.5em;
126
+ cursor: pointer;
127
+ }
128
+
129
+ .switch::before {
130
+ content: '';
131
+ position: absolute;
132
+ width: 1.3em;
133
+ height: 1.3em;
134
+ background: #fff;
135
+ top: 0.13em;
136
+ right: 1.5em;
137
+ border-radius: 100%;
138
+ transition: transform 0.3s;
139
+ }
140
+
141
+ .switch[aria-checked='true'] {
142
+ background-color: var(--ui-primary);
143
+ }
144
+
145
+ .switch[aria-checked='true']::before {
146
+ transform: translateX(1.3em);
147
+ transition: transform 0.3s;
148
+ }
149
+
150
+ .switch:focus {
151
+ outline: 1px solid var(--ui-primary);
152
+ outline-offset: 2px;
153
+ }
154
+
155
+ .switch.disabled {
156
+ cursor: not-allowed;
157
+ opacity: 0.5;
158
+ }
159
+
160
+ .switch.error {
161
+ outline: 1px solid var(--danger-text);
162
+ }
163
+
164
+ .required {
165
+ color: var(--danger-text);
166
+ }
167
+
168
+ .error-text {
169
+ color: var(--danger-text);
170
+ }
113
171
  </style>
@@ -1,13 +1,32 @@
1
- interface Props {
2
- label: string;
1
+ import type { Snippet } from 'svelte';
2
+ export interface SwitchProps {
3
+ /** Label text displayed above the switch */
4
+ label?: string;
5
+ /** Mark field as required (shows asterisk) */
3
6
  required?: boolean;
7
+ /** Whether the switch is on (bindable) */
4
8
  checked: boolean;
9
+ /** Disable the switch */
5
10
  disabled?: boolean;
11
+ /** CSS classes for the container element */
6
12
  containerClass?: string;
13
+ /** CSS classes for the switch element */
7
14
  switchClass?: string;
15
+ /** Custom ID for the switch element */
16
+ inputId?: string;
17
+ /** Callback when switch state changes */
8
18
  onchange?: (value: boolean) => void;
19
+ /** Show error state styling */
9
20
  showError?: boolean;
21
+ /** Error message to display */
22
+ errorText?: string;
23
+ /** Simple tooltip text */
24
+ tooltipText?: string;
25
+ /** Position of the tooltip */
26
+ tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
27
+ /** Rich tooltip content using a Svelte snippet */
28
+ tooltipContent?: Snippet;
10
29
  }
11
- declare const Switch: import("svelte").Component<Props, {}, "checked">;
30
+ declare const Switch: import("svelte").Component<SwitchProps, {}, "checked">;
12
31
  type Switch = ReturnType<typeof Switch>;
13
32
  export default Switch;