@placeholderco/placeholder-ui 1.0.11 → 2.0.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 (289) 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 +270 -137
  99. package/dist/form/Autocomplete.svelte.d.ts +58 -10
  100. package/dist/form/AutocompleteMulti.svelte +385 -227
  101. package/dist/form/AutocompleteMulti.svelte.d.ts +59 -10
  102. package/dist/form/Checkbox.svelte +124 -43
  103. package/dist/form/Checkbox.svelte.d.ts +26 -2
  104. package/dist/form/Chips.svelte +47 -17
  105. package/dist/form/Chips.svelte.d.ts +24 -3
  106. package/dist/form/ComboBox.svelte +30 -20
  107. package/dist/form/ComboBox.svelte.d.ts +1 -1
  108. package/dist/form/ComboBoxItemBuilder.svelte +161 -188
  109. package/dist/form/ComboBoxItemBuilder.svelte.d.ts +19 -2
  110. package/dist/form/ComboBoxMulti.svelte +38 -24
  111. package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
  112. package/dist/form/CronBuilder.svelte +84 -67
  113. package/dist/form/CronBuilder.svelte.d.ts +16 -3
  114. package/dist/form/DatePicker.svelte +177 -191
  115. package/dist/form/DatePicker.svelte.d.ts +17 -2
  116. package/dist/form/DateRangePicker.svelte +775 -0
  117. package/dist/form/DateRangePicker.svelte.d.ts +23 -0
  118. package/dist/form/DateTimePicker.svelte +168 -209
  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 +71 -29
  123. package/dist/form/Number.svelte.d.ts +39 -6
  124. package/dist/form/Radio.svelte +174 -0
  125. package/dist/form/Radio.svelte.d.ts +21 -0
  126. package/dist/form/RadioGroup.svelte +52 -138
  127. package/dist/form/RadioGroup.svelte.d.ts +19 -2
  128. package/dist/form/SegmentedControl.svelte +103 -57
  129. package/dist/form/SegmentedControl.svelte.d.ts +12 -2
  130. package/dist/form/Select.svelte +160 -229
  131. package/dist/form/Select.svelte.d.ts +35 -6
  132. package/dist/form/SelectMulti.svelte +166 -277
  133. package/dist/form/SelectMulti.svelte.d.ts +37 -6
  134. package/dist/form/Slider.svelte +185 -268
  135. package/dist/form/Slider.svelte.d.ts +33 -16
  136. package/dist/form/StringArrayBuilder.svelte +249 -0
  137. package/dist/form/StringArrayBuilder.svelte.d.ts +15 -0
  138. package/dist/form/Switch.svelte +164 -106
  139. package/dist/form/Switch.svelte.d.ts +22 -3
  140. package/dist/form/TextArea.svelte +80 -45
  141. package/dist/form/TextArea.svelte.d.ts +35 -10
  142. package/dist/form/Textbox.svelte +80 -47
  143. package/dist/form/Textbox.svelte.d.ts +41 -8
  144. package/dist/form/TimePicker.svelte +42 -47
  145. package/dist/form/TimePicker.svelte.d.ts +12 -2
  146. package/dist/form/comboBoxCore.svelte.d.ts +99 -0
  147. package/dist/form/comboBoxCore.svelte.js +243 -0
  148. package/dist/icon/Icon.svelte +8 -3
  149. package/dist/icon/Icon.svelte.d.ts +8 -3
  150. package/dist/icon/cube-send.svg +1 -0
  151. package/dist/icon/file-type-bmp.svg +1 -0
  152. package/dist/icon/file-type-csv.svg +1 -0
  153. package/dist/icon/file-type-doc.svg +1 -0
  154. package/dist/icon/file-type-docx.svg +1 -0
  155. package/dist/icon/file-type-jpg.svg +1 -0
  156. package/dist/icon/file-type-pdf.svg +1 -0
  157. package/dist/icon/file-type-png.svg +1 -0
  158. package/dist/icon/file-type-ppt.svg +1 -0
  159. package/dist/icon/file-type-svg.svg +1 -0
  160. package/dist/icon/file-type-txt.svg +1 -0
  161. package/dist/icon/file-type-xls.svg +1 -0
  162. package/dist/icon/file-type-zip.svg +1 -0
  163. package/dist/icon/index.d.ts +166 -145
  164. package/dist/icon/index.js +166 -146
  165. package/dist/icon/layout-sidebar-left-collapse.svg +1 -0
  166. package/dist/icon/layout-sidebar-left-expand.svg +1 -0
  167. package/dist/icon/logo-placeholder.svg +6 -0
  168. package/dist/icon/paperclip.svg +1 -0
  169. package/dist/icon/source-code.svg +1 -0
  170. package/dist/icon/sun-moon.svg +1 -0
  171. package/dist/icon/table.svg +6 -0
  172. package/dist/icon/thumb-down.svg +1 -0
  173. package/dist/icon/thumb-up.svg +1 -0
  174. package/dist/index.d.ts +93 -22
  175. package/dist/index.js +28 -27
  176. package/dist/layout/AppShell.svelte +12 -162
  177. package/dist/layout/AppShell.svelte.d.ts +6 -27
  178. package/dist/layout/CustomNavbar.svelte +9 -7
  179. package/dist/layout/CustomNavbar.svelte.d.ts +4 -2
  180. package/dist/layout/Navbar.svelte +158 -110
  181. package/dist/layout/Navbar.svelte.d.ts +26 -12
  182. package/dist/layout/NavbarItemDisplay.svelte +2 -2
  183. package/dist/layout/NavbarItemView.svelte +182 -0
  184. package/dist/layout/NavbarItemView.svelte.d.ts +10 -0
  185. package/dist/layout/Sidenav.svelte +280 -341
  186. package/dist/layout/Sidenav.svelte.d.ts +36 -4
  187. package/dist/models/ComboBoxItem.d.ts +2 -0
  188. package/dist/models/Employee.d.ts +53 -0
  189. package/dist/models/Employee.js +23 -0
  190. package/dist/models/Hyperlink.d.ts +3 -1
  191. package/dist/models/LinkCollectionItem.d.ts +3 -1
  192. package/dist/models/NavbarItem.d.ts +6 -2
  193. package/dist/theme.svelte.d.ts +0 -1
  194. package/dist/theme.svelte.js +46 -58
  195. package/dist/ui/Accordion.svelte +81 -242
  196. package/dist/ui/Accordion.svelte.d.ts +37 -14
  197. package/dist/ui/AccordionItem.svelte +303 -0
  198. package/dist/ui/AccordionItem.svelte.d.ts +21 -0
  199. package/dist/ui/ActionIcon.svelte +25 -21
  200. package/dist/ui/ActionIcon.svelte.d.ts +15 -2
  201. package/dist/ui/Badge.svelte +170 -161
  202. package/dist/ui/Badge.svelte.d.ts +16 -4
  203. package/dist/ui/Button.svelte +178 -205
  204. package/dist/ui/Button.svelte.d.ts +19 -2
  205. package/dist/ui/ButtonVariant.d.ts +15 -1
  206. package/dist/ui/ContextMenu.svelte +146 -0
  207. package/dist/ui/ContextMenu.svelte.d.ts +37 -0
  208. package/dist/ui/ContextMenuList.svelte +188 -0
  209. package/dist/ui/ContextMenuList.svelte.d.ts +12 -0
  210. package/dist/ui/Dialog.svelte +183 -104
  211. package/dist/ui/Dialog.svelte.d.ts +21 -2
  212. package/dist/ui/Drawer.svelte +237 -184
  213. package/dist/ui/Drawer.svelte.d.ts +20 -2
  214. package/dist/ui/Dropdown.svelte +24 -14
  215. package/dist/ui/Dropdown.svelte.d.ts +11 -2
  216. package/dist/ui/Dropzone.svelte +159 -57
  217. package/dist/ui/Dropzone.svelte.d.ts +29 -2
  218. package/dist/ui/Link.svelte +12 -4
  219. package/dist/ui/Link.svelte.d.ts +8 -2
  220. package/dist/ui/Loader.svelte +23 -18
  221. package/dist/ui/Loader.svelte.d.ts +5 -2
  222. package/dist/ui/Logo.svelte +37 -0
  223. package/dist/ui/Logo.svelte.d.ts +16 -0
  224. package/dist/ui/MultiSortable.svelte +287 -0
  225. package/dist/ui/MultiSortable.svelte.d.ts +50 -0
  226. package/dist/ui/Pagination.svelte +12 -6
  227. package/dist/ui/Pagination.svelte.d.ts +6 -2
  228. package/dist/ui/Popover.svelte +43 -65
  229. package/dist/ui/Popover.svelte.d.ts +14 -5
  230. package/dist/ui/ProgressBar.svelte +169 -0
  231. package/dist/ui/ProgressBar.svelte.d.ts +30 -0
  232. package/dist/ui/ProgressBarVariant.d.ts +7 -0
  233. package/dist/ui/ProgressBarVariant.js +1 -0
  234. package/dist/ui/SegmentedControl.svelte +0 -0
  235. package/dist/ui/SegmentedControl.svelte.d.ts +26 -0
  236. package/dist/ui/Sortable.svelte +163 -0
  237. package/dist/ui/Sortable.svelte.d.ts +47 -0
  238. package/dist/ui/Table.svelte +497 -56
  239. package/dist/ui/Table.svelte.d.ts +64 -2
  240. package/dist/ui/Tabs.svelte +22 -18
  241. package/dist/ui/Tabs.svelte.d.ts +6 -2
  242. package/dist/ui/ThemeSwitcher.svelte +26 -7
  243. package/dist/ui/ThemeSwitcher.svelte.d.ts +4 -2
  244. package/dist/ui/Tooltip.svelte +312 -180
  245. package/dist/ui/Tooltip.svelte.d.ts +4 -3
  246. package/dist/uiTheme.svelte.d.ts +86 -0
  247. package/dist/uiTheme.svelte.js +214 -0
  248. package/dist/util/DateFunctions.js +1 -1
  249. package/dist/util/DragDrop.d.ts +50 -0
  250. package/dist/util/DragDrop.js +154 -0
  251. package/dist/util/NavigateTo.js +2 -2
  252. package/dist/util/dayjs.d.ts +4 -0
  253. package/dist/util/dayjs.js +15 -0
  254. package/dist/util/interceptLinkClick.d.ts +13 -0
  255. package/dist/util/interceptLinkClick.js +33 -0
  256. package/package.json +66 -26
  257. package/dist/display/Alert.svelte +0 -179
  258. package/dist/display/Alert.svelte.d.ts +0 -13
  259. package/dist/form/FileInput.svelte +0 -235
  260. package/dist/form/FileInput.svelte.d.ts +0 -23
  261. package/dist/form/PasswordInput.svelte +0 -252
  262. package/dist/form/PasswordInput.svelte.d.ts +0 -33
  263. package/dist/form/Rating.svelte +0 -235
  264. package/dist/form/Rating.svelte.d.ts +0 -21
  265. package/dist/styles/components.css +0 -199
  266. package/dist/styles/dark.css +0 -146
  267. package/dist/styles/index.css +0 -116
  268. package/dist/styles/reset.css +0 -110
  269. package/dist/styles/semantic.css +0 -86
  270. package/dist/styles/tokens.css +0 -203
  271. package/dist/styles/utilities.css +0 -523
  272. package/dist/ui/Breadcrumbs.svelte +0 -131
  273. package/dist/ui/Breadcrumbs.svelte.d.ts +0 -16
  274. package/dist/ui/LoadingOverlay.svelte +0 -53
  275. package/dist/ui/LoadingOverlay.svelte.d.ts +0 -11
  276. package/dist/ui/Progress.svelte +0 -191
  277. package/dist/ui/Progress.svelte.d.ts +0 -15
  278. package/dist/ui/RingProgress.svelte +0 -141
  279. package/dist/ui/RingProgress.svelte.d.ts +0 -18
  280. package/dist/ui/Skeleton.svelte +0 -85
  281. package/dist/ui/Skeleton.svelte.d.ts +0 -12
  282. package/dist/ui/Stepper.svelte +0 -355
  283. package/dist/ui/Stepper.svelte.d.ts +0 -24
  284. package/dist/ui/Timeline.svelte +0 -225
  285. package/dist/ui/Timeline.svelte.d.ts +0 -23
  286. /package/dist/{actions → util}/ClickOutside.d.ts +0 -0
  287. /package/dist/{actions → util}/ClickOutside.js +0 -0
  288. /package/dist/{transitions → util}/Transitions.d.ts +0 -0
  289. /package/dist/{transitions → util}/Transitions.js +0 -0
@@ -1,33 +1,64 @@
1
- import type { ComboBoxGroup, ComboBoxItem, FetchFunctionType, RetrieveLabelFunctionType, SearchFunctionType } from "../models/ComboBoxItem.js";
2
- import { type Snippet } from "svelte";
3
- interface Props {
1
+ import type { ComboBoxGroup, ComboBoxItem, FetchFunctionType, RetrieveLabelFunctionType, SearchFunctionType } from '../models/ComboBoxItem.js';
2
+ import { type Snippet } from 'svelte';
3
+ export interface SelectMultiProps {
4
+ /** HTML name attribute for the select (falls back to label, then auto-generated) */
5
+ name?: string;
6
+ /** Label text displayed above the select */
4
7
  label?: string;
8
+ /** Array of selected values (bindable) */
5
9
  values?: string[];
10
+ /**
11
+ * Array of full selected item objects (bindable). Can be passed initially to preset
12
+ * the selection with known labels — no `values` or retrieveLabelFunction needed.
13
+ */
6
14
  rawValues?: ComboBoxItem[];
15
+ /** Placeholder text when no values are selected */
7
16
  placeholder?: string;
17
+ /** CSS classes for the select element */
8
18
  class?: string;
19
+ /** CSS classes for the container element */
9
20
  containerClass?: string;
21
+ /** Disable the select */
10
22
  disabled?: boolean;
23
+ /** Mark field as required (shows asterisk) */
11
24
  required?: boolean;
25
+ /** Show error state styling */
12
26
  showError?: boolean;
27
+ /** Error message to display */
13
28
  errorText?: string;
29
+ /** Auto-focus on mount (first dialog open only) */
14
30
  autofocus?: boolean;
31
+ /** Auto-focus on every dialog open */
15
32
  autofocusDialog?: boolean;
33
+ /** Enable search/filter within options */
16
34
  allowSearch?: boolean;
17
- showNoResultsMessage?: boolean;
35
+ /** Hide "no results" message when search finds nothing */
36
+ hideNoResults?: boolean;
37
+ /** Close dropdown after selecting an option */
18
38
  closeOnSelection?: boolean;
39
+ /** Text shown while loading options */
19
40
  loadingText?: string;
41
+ /** Flat list of selectable options */
20
42
  options?: ComboBoxItem[];
43
+ /** Options organized into groups */
21
44
  groupedOptions?: ComboBoxGroup[];
22
- tooltipLocation?: "top" | "bottom" | "left" | "right";
45
+ /** Position of the tooltip */
46
+ tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
47
+ /** Async function to fetch options */
23
48
  fetchFunction?: FetchFunctionType | null;
49
+ /** Async function to search/filter options */
24
50
  searchFunction?: SearchFunctionType | null;
51
+ /** Async function to retrieve labels for values */
25
52
  retrieveLabelFunction?: RetrieveLabelFunctionType | null;
53
+ /** Rich tooltip content using a Svelte snippet */
26
54
  tooltipContent?: Snippet;
55
+ /** Simple tooltip text */
27
56
  tooltipText?: string;
57
+ /** Callback when selection changes (returns value strings) */
28
58
  onchange?: (e: string[]) => void;
59
+ /** Callback when selection changes (returns full item objects) */
29
60
  onchangeRaw?: (e: ComboBoxItem[]) => void;
30
61
  }
31
- declare const SelectMulti: import("svelte").Component<Props, {}, "values" | "rawValues">;
62
+ declare const SelectMulti: import("svelte").Component<SelectMultiProps, {}, "values" | "rawValues">;
32
63
  type SelectMulti = ReturnType<typeof SelectMulti>;
33
64
  export default SelectMulti;
@@ -1,147 +1,137 @@
1
1
  <script lang="ts">
2
- import FormGroup from './FormGroup.svelte';
2
+ import Tooltip from '../ui/Tooltip.svelte';
3
+ import { Icon, iconInfoCircle } from '../icon/index.js';
3
4
 
4
- interface Mark {
5
- value: number;
6
- label?: string;
7
- }
5
+ const autoName = `slider-${crypto.randomUUID()}`;
8
6
 
9
- interface Props {
7
+ export interface SliderProps {
8
+ /** HTML name attribute for the slider (falls back to label, then auto-generated) */
9
+ name?: string;
10
+ /** Label text displayed above the slider */
10
11
  label?: string;
12
+ /** Custom ID for the slider element */
13
+ inputId?: string;
14
+ /** Mark field as required (shows asterisk) */
15
+ required?: boolean;
16
+ /** Disable the slider */
17
+ disabled?: boolean;
18
+ /** CSS classes for the slider element */
19
+ class?: string;
20
+ /** CSS classes for the container element */
21
+ containerClass?: string;
22
+ /** Slider value (bindable) */
11
23
  value?: number;
24
+ /** Minimum allowed value */
12
25
  min?: number;
26
+ /** Maximum allowed value */
13
27
  max?: number;
28
+ /** Increment/decrement step value */
14
29
  step?: number;
15
- marks?: Mark[] | boolean;
16
- showValue?: boolean;
17
- labelAlwaysOn?: boolean;
18
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
19
- color?: 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'danger';
20
- radius?: 'none' | 'sm' | 'md' | 'lg' | 'full';
21
- disabled?: boolean;
22
- class?: string;
23
- containerClass?: string;
24
- required?: boolean;
30
+ /** Show error state styling */
25
31
  showError?: boolean;
32
+ /** Error message to display */
26
33
  errorText?: string;
34
+ /** Position of the tooltip */
27
35
  tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
36
+ /** Simple tooltip text */
28
37
  tooltipText?: string;
38
+ /** Hide the current value next to the label */
39
+ hideValue?: boolean;
40
+ /** Format function for displaying the value */
41
+ formatValue?: (value: number) => string;
42
+ /** Callback when value changes (after interaction ends) */
29
43
  onchange?: (value: number) => void;
44
+ /** Callback on input event (during dragging) */
30
45
  oninput?: (value: number) => void;
46
+ /** Callback when slider gains focus */
47
+ onfocus?: (e: FocusEvent) => void;
48
+ /** Callback when slider loses focus */
49
+ onblur?: (e: FocusEvent) => void;
31
50
  }
32
51
 
33
52
  let {
53
+ name,
34
54
  label = '',
35
- value = $bindable(0),
36
- min = 0,
37
- max = 100,
38
- step = 1,
39
- marks = false,
40
- showValue = false,
41
- labelAlwaysOn = false,
42
- size = 'md',
43
- color = 'primary',
44
- radius = 'full',
55
+ inputId = undefined,
56
+ required = false,
45
57
  disabled = false,
46
58
  class: classes = '',
47
59
  containerClass = '',
48
- required = false,
60
+ value = $bindable(50),
61
+ min = 0,
62
+ max = 100,
63
+ step = 1,
49
64
  showError = false,
50
65
  errorText = '',
51
66
  tooltipLocation = 'top',
52
67
  tooltipText = undefined,
53
- onchange,
54
- oninput
55
- }: Props = $props();
56
-
57
- let isDragging = $state(false);
58
-
59
- const percentage = $derived(((value - min) / (max - min)) * 100);
60
-
61
- // Generate marks if boolean true
62
- const computedMarks = $derived.by(() => {
63
- if (marks === false) return [];
64
- if (marks === true) {
65
- // Generate marks at 0%, 25%, 50%, 75%, 100%
66
- const range = max - min;
67
- return [
68
- { value: min, label: String(min) },
69
- { value: min + range * 0.25, label: String(min + range * 0.25) },
70
- { value: min + range * 0.5, label: String(min + range * 0.5) },
71
- { value: min + range * 0.75, label: String(min + range * 0.75) },
72
- { value: max, label: String(max) }
73
- ];
74
- }
75
- return marks;
68
+ hideValue = false,
69
+ formatValue = (v: number) => v.toString(),
70
+ onchange = undefined,
71
+ oninput = undefined,
72
+ onfocus = undefined,
73
+ onblur = undefined
74
+ }: SliderProps = $props();
75
+
76
+ let resolvedName = $derived((name || label || autoName).replace(/[^a-zA-Z0-9_\-:.]/g, '_'));
77
+
78
+ let id = $derived.by(() => {
79
+ if (inputId) return inputId;
80
+ if (label) return `slider-${label.toLowerCase().replace(/ /g, '-')}`;
81
+ return Math.random().toString(36).substring(2, 8);
76
82
  });
77
83
 
78
- function handleInput(e: Event) {
79
- const target = e.target as HTMLInputElement;
80
- value = Number(target.value);
81
- oninput?.(value);
82
- }
84
+ const extraClasses: string[] = $derived.by(() => {
85
+ const result = [];
86
+ if (disabled) result.push('disabled');
87
+ if (showError) result.push('show-error');
88
+ return result;
89
+ });
83
90
 
84
- function handleChange(e: Event) {
85
- const target = e.target as HTMLInputElement;
86
- value = Number(target.value);
87
- onchange?.(value);
88
- }
91
+ // Calculate fill percentage for the track
92
+ const fillPercent = $derived(((value - min) / (max - min)) * 100);
89
93
  </script>
90
94
 
91
95
  <div class="slider-container {containerClass}">
92
- <FormGroup
93
- {label}
94
- {required}
95
- class={classes}
96
- {tooltipLocation}
97
- {tooltipText}
98
- {showError}
99
- {errorText}
100
- >
101
- <div class="slider-wrapper size-{size}">
102
- {#if showValue}
103
- <div class="slider-value-display">
104
- <span>{value}</span>
105
- </div>
106
- {/if}
107
- <div class="slider-track-wrapper">
108
- <input
109
- type="range"
110
- class="slider color-{color} radius-{radius}"
111
- {min}
112
- {max}
113
- {step}
114
- {disabled}
115
- bind:value
116
- oninput={handleInput}
117
- onchange={handleChange}
118
- onmousedown={() => (isDragging = true)}
119
- onmouseup={() => (isDragging = false)}
120
- ontouchstart={() => (isDragging = true)}
121
- ontouchend={() => (isDragging = false)}
122
- style="--slider-percentage: {percentage}%;"
123
- />
124
- {#if labelAlwaysOn || isDragging}
125
- <div class="slider-thumb-label" style="left: {percentage}%;">
126
- {value}
127
- </div>
96
+ {#if label}
97
+ <div class="label-row">
98
+ <label class="label" for={id}>
99
+ {label}
100
+ {#if required}
101
+ <span class="text-required">*</span>
128
102
  {/if}
129
- </div>
130
- {#if computedMarks.length > 0}
131
- <div class="slider-marks">
132
- {#each computedMarks as mark}
133
- {@const markPercentage = ((mark.value - min) / (max - min)) * 100}
134
- <div class="slider-mark" style="left: {markPercentage}%;">
135
- <div class="mark-dot" class:active={value >= mark.value}></div>
136
- {#if mark.label}
137
- <div class="mark-label">{mark.label}</div>
138
- {/if}
139
- </div>
140
- {/each}
141
- </div>
103
+ {#if tooltipText}
104
+ <Tooltip location={tooltipLocation} text={tooltipText}>
105
+ <Icon svg={iconInfoCircle} size="1em" stroke="var(--accent-color)" />
106
+ </Tooltip>
107
+ {/if}
108
+ </label>
109
+ {#if !hideValue}
110
+ <span class="label-value">{formatValue(value)}</span>
142
111
  {/if}
143
112
  </div>
144
- </FormGroup>
113
+ {/if}
114
+ <div class="slider-wrapper">
115
+ <input
116
+ type="range"
117
+ class="slider {classes} {extraClasses.join(' ')}"
118
+ {id}
119
+ name={resolvedName}
120
+ {min}
121
+ {max}
122
+ {step}
123
+ {disabled}
124
+ bind:value
125
+ style="--fill-percent: {fillPercent}%"
126
+ onchange={() => onchange?.(value)}
127
+ oninput={() => oninput?.(value)}
128
+ {onfocus}
129
+ {onblur}
130
+ />
131
+ </div>
132
+ {#if showError && errorText}
133
+ <div class="error-text">{errorText}</div>
134
+ {/if}
145
135
  </div>
146
136
 
147
137
  <style>
@@ -149,210 +139,137 @@
149
139
  width: 100%;
150
140
  }
151
141
 
152
- .slider-wrapper {
153
- width: 100%;
154
- padding-top: var(--pui-spacing-1);
142
+ .label-row {
143
+ display: flex;
144
+ justify-content: space-between;
145
+ align-items: center;
146
+ margin-bottom: 0.25rem;
155
147
  }
156
148
 
157
- .slider-value-display {
158
- text-align: right;
159
- font-size: var(--pui-font-size-sm);
160
- font-weight: var(--pui-font-weight-medium);
161
- color: var(--pui-text-secondary);
162
- margin-bottom: var(--pui-spacing-1);
149
+ .label {
150
+ font-size: 1rem;
151
+ line-height: 1.5rem;
152
+ color: var(--text-color);
163
153
  }
164
154
 
165
- :global(.dark) .slider-value-display {
166
- color: var(--pui-color-gray-300);
155
+ .text-required {
156
+ color: var(--danger-text);
167
157
  }
168
158
 
169
- .slider-track-wrapper {
170
- position: relative;
171
- width: 100%;
159
+ .label-value {
160
+ font-size: 0.875rem;
161
+ color: var(--text-muted);
162
+ font-variant-numeric: tabular-nums;
163
+ }
164
+
165
+ .slider-wrapper {
166
+ display: flex;
167
+ align-items: center;
168
+ gap: 0.75rem;
169
+ padding: 4px 0 4px 0;
172
170
  }
173
171
 
174
172
  .slider {
175
173
  -webkit-appearance: none;
176
174
  appearance: none;
177
175
  width: 100%;
178
- background: transparent;
179
- cursor: pointer;
180
- }
181
-
182
- .slider:disabled {
183
- opacity: 0.5;
184
- cursor: not-allowed;
185
- }
186
-
187
- /* Track */
188
- .slider::-webkit-slider-runnable-track {
189
- height: var(--track-height, 6px);
190
- background: linear-gradient(
191
- to right,
192
- var(--slider-color, var(--pui-color-primary)) 0%,
193
- var(--slider-color, var(--pui-color-primary)) var(--slider-percentage),
194
- var(--pui-color-gray-300) var(--slider-percentage),
195
- var(--pui-color-gray-300) 100%
196
- );
197
- border-radius: var(--track-radius, var(--pui-radius-full));
198
- }
199
-
200
- :global(.dark) .slider::-webkit-slider-runnable-track {
176
+ height: 6px;
177
+ border-radius: 3px;
201
178
  background: linear-gradient(
202
179
  to right,
203
- var(--slider-color, var(--pui-color-primary)) 0%,
204
- var(--slider-color, var(--pui-color-primary)) var(--slider-percentage),
205
- var(--pui-color-dark-border) var(--slider-percentage),
206
- var(--pui-color-dark-border) 100%
180
+ var(--accent-color) 0%,
181
+ var(--accent-color) var(--fill-percent),
182
+ var(--border-color) var(--fill-percent),
183
+ var(--border-color) 100%
207
184
  );
185
+ outline: none;
186
+ cursor: pointer;
208
187
  }
209
188
 
210
- .slider::-moz-range-track {
211
- height: var(--track-height, 6px);
212
- background: var(--pui-color-gray-300);
213
- border-radius: var(--track-radius, var(--pui-radius-full));
214
- }
215
-
216
- .slider::-moz-range-progress {
217
- background: var(--slider-color, var(--pui-color-primary));
218
- height: var(--track-height, 6px);
219
- border-radius: var(--track-radius, var(--pui-radius-full));
220
- }
221
-
222
- /* Thumb */
223
189
  .slider::-webkit-slider-thumb {
224
190
  -webkit-appearance: none;
225
191
  appearance: none;
226
- width: var(--thumb-size, 16px);
227
- height: var(--thumb-size, 16px);
228
- background: var(--pui-color-white);
229
- border: 2px solid var(--slider-color, var(--pui-color-primary));
192
+ width: 16px;
193
+ height: 16px;
230
194
  border-radius: 50%;
231
- margin-top: calc((var(--track-height, 6px) - var(--thumb-size, 16px)) / 2);
232
- box-shadow: var(--pui-shadow-sm);
233
- transition: transform var(--pui-transition-fast) var(--pui-ease-out);
234
- }
235
-
236
- .slider::-webkit-slider-thumb:hover {
237
- transform: scale(1.1);
195
+ background: var(--accent-color);
196
+ cursor: pointer;
197
+ border: 2px solid var(--bg-color);
198
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
199
+ transition:
200
+ transform 0.15s ease,
201
+ box-shadow 0.15s ease;
238
202
  }
239
203
 
240
204
  .slider::-moz-range-thumb {
241
- width: var(--thumb-size, 16px);
242
- height: var(--thumb-size, 16px);
243
- background: var(--pui-color-white);
244
- border: 2px solid var(--slider-color, var(--pui-color-primary));
205
+ width: 16px;
206
+ height: 16px;
245
207
  border-radius: 50%;
246
- box-shadow: var(--pui-shadow-sm);
208
+ background: var(--accent-color);
209
+ cursor: pointer;
210
+ border: 2px solid var(--bg-color);
211
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
212
+ transition:
213
+ transform 0.15s ease,
214
+ box-shadow 0.15s ease;
247
215
  }
248
216
 
249
- /* Sizes */
250
- .size-xs {
251
- --track-height: 4px;
252
- --thumb-size: 12px;
253
- }
254
- .size-sm {
255
- --track-height: 5px;
256
- --thumb-size: 14px;
257
- }
258
- .size-md {
259
- --track-height: 6px;
260
- --thumb-size: 16px;
261
- }
262
- .size-lg {
263
- --track-height: 8px;
264
- --thumb-size: 20px;
265
- }
266
- .size-xl {
267
- --track-height: 10px;
268
- --thumb-size: 24px;
217
+ .slider::-webkit-slider-thumb:hover {
218
+ transform: scale(1.1);
219
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
269
220
  }
270
221
 
271
- /* Colors */
272
- .color-primary {
273
- --slider-color: var(--pui-color-primary);
274
- }
275
- .color-secondary {
276
- --slider-color: var(--pui-color-secondary);
277
- }
278
- .color-accent {
279
- --slider-color: var(--pui-color-accent);
280
- }
281
- .color-success {
282
- --slider-color: var(--pui-color-success);
283
- }
284
- .color-warning {
285
- --slider-color: var(--pui-color-warning);
286
- }
287
- .color-danger {
288
- --slider-color: var(--pui-color-danger);
222
+ .slider::-moz-range-thumb:hover {
223
+ transform: scale(1.1);
224
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
289
225
  }
290
226
 
291
- /* Radius */
292
- .radius-none {
293
- --track-radius: 0;
227
+ .slider:focus {
228
+ outline: none;
294
229
  }
295
- .radius-sm {
296
- --track-radius: var(--pui-radius-sm);
297
- }
298
- .radius-md {
299
- --track-radius: var(--pui-radius-md);
300
- }
301
- .radius-lg {
302
- --track-radius: var(--pui-radius-lg);
230
+
231
+ .slider:focus::-webkit-slider-thumb {
232
+ box-shadow: 0 0 0 3px rgba(var(--accent-color-rgb, 59, 130, 246), 0.3);
303
233
  }
304
- .radius-full {
305
- --track-radius: var(--pui-radius-full);
234
+
235
+ .slider:focus::-moz-range-thumb {
236
+ box-shadow: 0 0 0 3px rgba(var(--accent-color-rgb, 59, 130, 246), 0.3);
306
237
  }
307
238
 
308
- /* Thumb label */
309
- .slider-thumb-label {
310
- position: absolute;
311
- top: -28px;
312
- transform: translateX(-50%);
313
- background: var(--pui-color-gray-800);
314
- color: var(--pui-color-white);
315
- font-size: var(--pui-font-size-xs);
316
- padding: 2px 6px;
317
- border-radius: var(--pui-radius-sm);
318
- white-space: nowrap;
319
- pointer-events: none;
239
+ .slider.disabled {
240
+ opacity: 0.5;
241
+ cursor: not-allowed;
320
242
  }
321
243
 
322
- /* Marks */
323
- .slider-marks {
324
- position: relative;
325
- width: 100%;
326
- height: 20px;
327
- margin-top: var(--pui-spacing-1);
244
+ .slider.disabled::-webkit-slider-thumb {
245
+ cursor: not-allowed;
328
246
  }
329
247
 
330
- .slider-mark {
331
- position: absolute;
332
- transform: translateX(-50%);
333
- display: flex;
334
- flex-direction: column;
335
- align-items: center;
248
+ .slider.disabled::-moz-range-thumb {
249
+ cursor: not-allowed;
336
250
  }
337
251
 
338
- .mark-dot {
339
- width: 6px;
340
- height: 6px;
341
- border-radius: 50%;
342
- background: var(--pui-color-gray-400);
343
- margin-bottom: var(--pui-spacing-1);
252
+ .slider.show-error {
253
+ background: linear-gradient(
254
+ to right,
255
+ var(--danger-text) 0%,
256
+ var(--danger-text) var(--fill-percent),
257
+ var(--border-color) var(--fill-percent),
258
+ var(--border-color) 100%
259
+ );
344
260
  }
345
261
 
346
- .mark-dot.active {
347
- background: var(--slider-color, var(--pui-color-primary));
262
+ .slider.show-error::-webkit-slider-thumb {
263
+ background: var(--danger-text);
348
264
  }
349
265
 
350
- .mark-label {
351
- font-size: var(--pui-font-size-xs);
352
- color: var(--pui-color-gray-600);
266
+ .slider.show-error::-moz-range-thumb {
267
+ background: var(--danger-text);
353
268
  }
354
269
 
355
- :global(.dark) .mark-label {
356
- color: var(--pui-color-gray-400);
270
+ .error-text {
271
+ color: var(--danger-text);
272
+ font-size: 0.875rem;
273
+ margin-top: 0.25rem;
357
274
  }
358
275
  </style>
@@ -1,30 +1,47 @@
1
- interface Mark {
2
- value: number;
3
- label?: string;
4
- }
5
- interface Props {
1
+ export interface SliderProps {
2
+ /** HTML name attribute for the slider (falls back to label, then auto-generated) */
3
+ name?: string;
4
+ /** Label text displayed above the slider */
6
5
  label?: string;
6
+ /** Custom ID for the slider element */
7
+ inputId?: string;
8
+ /** Mark field as required (shows asterisk) */
9
+ required?: boolean;
10
+ /** Disable the slider */
11
+ disabled?: boolean;
12
+ /** CSS classes for the slider element */
13
+ class?: string;
14
+ /** CSS classes for the container element */
15
+ containerClass?: string;
16
+ /** Slider value (bindable) */
7
17
  value?: number;
18
+ /** Minimum allowed value */
8
19
  min?: number;
20
+ /** Maximum allowed value */
9
21
  max?: number;
22
+ /** Increment/decrement step value */
10
23
  step?: number;
11
- marks?: Mark[] | boolean;
12
- showValue?: boolean;
13
- labelAlwaysOn?: boolean;
14
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
15
- color?: 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'danger';
16
- radius?: 'none' | 'sm' | 'md' | 'lg' | 'full';
17
- disabled?: boolean;
18
- class?: string;
19
- containerClass?: string;
20
- required?: boolean;
24
+ /** Show error state styling */
21
25
  showError?: boolean;
26
+ /** Error message to display */
22
27
  errorText?: string;
28
+ /** Position of the tooltip */
23
29
  tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
30
+ /** Simple tooltip text */
24
31
  tooltipText?: string;
32
+ /** Hide the current value next to the label */
33
+ hideValue?: boolean;
34
+ /** Format function for displaying the value */
35
+ formatValue?: (value: number) => string;
36
+ /** Callback when value changes (after interaction ends) */
25
37
  onchange?: (value: number) => void;
38
+ /** Callback on input event (during dragging) */
26
39
  oninput?: (value: number) => void;
40
+ /** Callback when slider gains focus */
41
+ onfocus?: (e: FocusEvent) => void;
42
+ /** Callback when slider loses focus */
43
+ onblur?: (e: FocusEvent) => void;
27
44
  }
28
- declare const Slider: import("svelte").Component<Props, {}, "value">;
45
+ declare const Slider: import("svelte").Component<SliderProps, {}, "value">;
29
46
  type Slider = ReturnType<typeof Slider>;
30
47
  export default Slider;