@svgrid/grid 2.2.16 → 2.2.17

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 (290) hide show
  1. package/README.md +1 -1
  2. package/dist/GridFooter.svelte +12 -11
  3. package/dist/SvAnchor.svelte +65 -0
  4. package/dist/SvAnchor.svelte.d.ts +24 -0
  5. package/dist/SvAspectRatio.svelte +38 -0
  6. package/dist/SvAspectRatio.svelte.d.ts +16 -0
  7. package/dist/SvAutoComplete.svelte +52 -7
  8. package/dist/SvAutoComplete.svelte.d.ts +4 -1
  9. package/dist/SvBlockquote.svelte +43 -0
  10. package/dist/SvBlockquote.svelte.d.ts +16 -0
  11. package/dist/SvCalendar.svelte +33 -2
  12. package/dist/SvCalendar.svelte.d.ts +8 -1
  13. package/dist/SvCheckBox.svelte +6 -2
  14. package/dist/SvCode.svelte +52 -0
  15. package/dist/SvCode.svelte.d.ts +19 -0
  16. package/dist/SvCollapsible.svelte +75 -0
  17. package/dist/SvCollapsible.svelte.d.ts +27 -0
  18. package/dist/SvColorInput.svelte +11 -17
  19. package/dist/SvColorInput.svelte.d.ts +2 -0
  20. package/dist/SvComboBox.svelte +85 -8
  21. package/dist/SvComboBox.svelte.d.ts +14 -0
  22. package/dist/SvCountryInput.svelte +2 -2
  23. package/dist/SvCountryInput.svelte.d.ts +1 -1
  24. package/dist/SvDropDownList.svelte +154 -51
  25. package/dist/SvDropDownList.svelte.d.ts +17 -3
  26. package/dist/SvDurationInput.svelte +59 -41
  27. package/dist/SvDurationInput.svelte.d.ts +18 -0
  28. package/dist/SvField.svelte +203 -12
  29. package/dist/SvField.svelte.d.ts +45 -8
  30. package/dist/SvForm.svelte +195 -21
  31. package/dist/SvForm.svelte.d.ts +23 -0
  32. package/dist/SvGrid.controller.svelte.d.ts +12 -1
  33. package/dist/SvGrid.controller.svelte.js +87 -7
  34. package/dist/SvGrid.svelte +383 -181
  35. package/dist/SvGrid.types.d.ts +123 -2
  36. package/dist/SvGridChartView.svelte +70 -0
  37. package/dist/SvGridChartView.svelte.d.ts +11 -0
  38. package/dist/SvGridDropdown.svelte +9 -2
  39. package/dist/SvGridSelect.svelte +5 -2
  40. package/dist/SvGridSelect.svelte.d.ts +1 -1
  41. package/dist/SvGroup.svelte +41 -0
  42. package/dist/SvGroup.svelte.d.ts +27 -0
  43. package/dist/SvHoverCard.svelte +70 -0
  44. package/dist/SvHoverCard.svelte.d.ts +41 -0
  45. package/dist/SvKbd.svelte +51 -0
  46. package/dist/SvKbd.svelte.d.ts +18 -0
  47. package/dist/SvList.svelte +55 -0
  48. package/dist/SvList.svelte.d.ts +23 -0
  49. package/dist/SvListBox.svelte +166 -77
  50. package/dist/SvListBox.svelte.d.ts +17 -4
  51. package/dist/SvLoadingOverlay.svelte +53 -0
  52. package/dist/SvLoadingOverlay.svelte.d.ts +28 -0
  53. package/dist/SvMark.svelte +36 -0
  54. package/dist/SvMark.svelte.d.ts +14 -0
  55. package/dist/SvMaskedInput.svelte +50 -35
  56. package/dist/SvMaskedInput.svelte.d.ts +17 -2
  57. package/dist/SvMenuList.svelte +32 -3
  58. package/dist/SvMenubar.svelte +200 -0
  59. package/dist/SvMenubar.svelte.d.ts +18 -0
  60. package/dist/SvMultiSelect.svelte +7 -4
  61. package/dist/SvMultiSelect.svelte.d.ts +1 -1
  62. package/dist/SvNumberInput.svelte +79 -42
  63. package/dist/SvNumberInput.svelte.d.ts +25 -0
  64. package/dist/SvOtpInput.svelte +2 -2
  65. package/dist/SvPasswordInput.svelte +51 -31
  66. package/dist/SvPasswordInput.svelte.d.ts +17 -0
  67. package/dist/SvPhoneInput.svelte +39 -28
  68. package/dist/SvPhoneInput.svelte.d.ts +4 -0
  69. package/dist/SvPopconfirm.svelte +79 -0
  70. package/dist/SvPopconfirm.svelte.d.ts +42 -0
  71. package/dist/SvPopover.svelte +87 -29
  72. package/dist/SvPopover.svelte.d.ts +18 -4
  73. package/dist/SvRadioGroup.svelte +5 -1
  74. package/dist/SvResult.svelte +73 -0
  75. package/dist/SvResult.svelte.d.ts +28 -0
  76. package/dist/SvSegmented.svelte +114 -0
  77. package/dist/SvSegmented.svelte.d.ts +29 -0
  78. package/dist/SvSimpleGrid.svelte +41 -0
  79. package/dist/SvSimpleGrid.svelte.d.ts +25 -0
  80. package/dist/SvSlider.svelte +23 -10
  81. package/dist/SvSpinner.svelte +43 -0
  82. package/dist/SvSpinner.svelte.d.ts +20 -0
  83. package/dist/SvStack.svelte +37 -0
  84. package/dist/SvStack.svelte.d.ts +24 -0
  85. package/dist/SvSwitchButton.svelte +6 -1
  86. package/dist/SvTagsInput.svelte +9 -5
  87. package/dist/SvText.svelte +76 -0
  88. package/dist/SvText.svelte.d.ts +31 -0
  89. package/dist/SvTextInput.svelte +75 -43
  90. package/dist/SvTextInput.svelte.d.ts +28 -1
  91. package/dist/SvTimePicker.svelte +32 -2
  92. package/dist/SvTimePicker.svelte.d.ts +8 -9
  93. package/dist/SvTitle.svelte +57 -0
  94. package/dist/SvTitle.svelte.d.ts +24 -0
  95. package/dist/SvToaster.svelte +41 -6
  96. package/dist/SvToggleButton.svelte +4 -1
  97. package/dist/SvTooltip.svelte +68 -34
  98. package/dist/SvTooltip.svelte.d.ts +14 -2
  99. package/dist/SvTree.svelte +81 -21
  100. package/dist/SvTree.svelte.d.ts +3 -2
  101. package/dist/SvTreeSelect.svelte +5 -2
  102. package/dist/SvTreeSelect.svelte.d.ts +1 -1
  103. package/dist/SvVisuallyHidden.svelte +49 -0
  104. package/dist/SvVisuallyHidden.svelte.d.ts +19 -0
  105. package/dist/ai.d.ts +289 -0
  106. package/dist/ai.js +1013 -0
  107. package/dist/board-view.svelte.d.ts +22 -0
  108. package/dist/board-view.svelte.js +13 -0
  109. package/dist/build-api.js +36 -6
  110. package/dist/cdn/GridMenus-0AK9O7qG.js +420 -0
  111. package/dist/cdn/GridMenus-BjUoCXoD.js +416 -0
  112. package/dist/cdn/SvDateTimePicker-CYC7gRER.js +2176 -0
  113. package/dist/cdn/SvDateTimePicker-DtQKd4Ns.js +2198 -0
  114. package/dist/cdn/SvGridChart-BcLCYvw9.js +1195 -0
  115. package/dist/cdn/SvGridChart-BhnFdLd0.js +1203 -0
  116. package/dist/cdn/SvGridChartPanel-Cmx9DHAS.js +561 -0
  117. package/dist/cdn/SvGridChartPanel-DvjwxLvK.js +577 -0
  118. package/dist/cdn/SvGridChartView-B40DTJSX.js +54 -0
  119. package/dist/cdn/SvGridChartView-PwqI4s02.js +53 -0
  120. package/dist/cdn/SvGridDropdown-DjALc_4f.js +255 -0
  121. package/dist/cdn/SvGridDropdown-hpnHvOGt.js +254 -0
  122. package/dist/cdn/chart-T1usDN0o.js +1212 -0
  123. package/dist/cdn/disclose-version-DoD9AFD_.js +2958 -0
  124. package/dist/cdn/export-format-JT5pWVT8.js +561 -0
  125. package/dist/cdn/popover-P-9P2YYn.js +69 -0
  126. package/dist/cdn/rolldown-runtime-Dy4uBu1J.js +11 -0
  127. package/dist/cdn/src-BLhdLmoN.js +25707 -0
  128. package/dist/cdn/src-BwnUVj3T.js +25623 -0
  129. package/dist/cdn/svgrid.js +9 -32897
  130. package/dist/cdn/svgrid.svelte-external.js +9 -30052
  131. package/dist/cell-formatting.d.ts +2 -2
  132. package/dist/cell-render.js +4 -4
  133. package/dist/chart-view.svelte.d.ts +25 -0
  134. package/dist/chart-view.svelte.js +14 -0
  135. package/dist/createCombobox.svelte.d.ts +5 -0
  136. package/dist/createCombobox.svelte.js +21 -5
  137. package/dist/createDropdownList.svelte.d.ts +3 -0
  138. package/dist/createDropdownList.svelte.js +8 -2
  139. package/dist/createForm.svelte.d.ts +18 -0
  140. package/dist/createForm.svelte.js +51 -6
  141. package/dist/createMenu.svelte.js +27 -0
  142. package/dist/createPopoverSelect.svelte.d.ts +3 -0
  143. package/dist/createPopoverSelect.svelte.js +9 -1
  144. package/dist/createSlider.svelte.d.ts +8 -21
  145. package/dist/createSlider.svelte.js +34 -0
  146. package/dist/createTooltip.svelte.d.ts +12 -0
  147. package/dist/createTooltip.svelte.js +72 -9
  148. package/dist/editor-contract.d.ts +15 -0
  149. package/dist/export-provider.d.ts +27 -0
  150. package/dist/export-provider.js +9 -0
  151. package/dist/filter-operators.d.ts +6 -0
  152. package/dist/filter-operators.js +33 -0
  153. package/dist/form-field.d.ts +45 -2
  154. package/dist/grid-messages.d.ts +61 -0
  155. package/dist/grid-messages.js +72 -0
  156. package/dist/group-display.d.ts +62 -0
  157. package/dist/group-display.js +78 -0
  158. package/dist/index.d.ts +36 -4
  159. package/dist/index.js +43 -2
  160. package/dist/js-scroller.svelte.d.ts +35 -0
  161. package/dist/js-scroller.svelte.js +154 -0
  162. package/dist/list-option.d.ts +46 -0
  163. package/dist/list-option.js +53 -0
  164. package/dist/menus.js +25 -11
  165. package/dist/pivot-view.svelte.d.ts +72 -0
  166. package/dist/pivot-view.svelte.js +13 -0
  167. package/dist/positioning.d.ts +111 -0
  168. package/dist/positioning.js +191 -0
  169. package/dist/scheduler-model.d.ts +3 -0
  170. package/dist/scheduler-model.js +22 -5
  171. package/dist/svgrid-wrapper.types.d.ts +18 -0
  172. package/dist/toast-store.svelte.d.ts +54 -0
  173. package/dist/toast-store.svelte.js +65 -15
  174. package/package.json +9 -1
  175. package/src/GridFooter.svelte +12 -11
  176. package/src/SvAnchor.svelte +65 -0
  177. package/src/SvAspectRatio.svelte +38 -0
  178. package/src/SvAutoComplete.svelte +52 -7
  179. package/src/SvBlockquote.svelte +43 -0
  180. package/src/SvCalendar.svelte +33 -2
  181. package/src/SvCalendar.test.ts +15 -0
  182. package/src/SvCheckBox.svelte +6 -2
  183. package/src/SvCode.svelte +52 -0
  184. package/src/SvCollapsible.svelte +75 -0
  185. package/src/SvColorInput.svelte +11 -17
  186. package/src/SvComboBox.svelte +85 -8
  187. package/src/SvCountryInput.svelte +2 -2
  188. package/src/SvDropDownList.svelte +154 -51
  189. package/src/SvDurationInput.svelte +59 -41
  190. package/src/SvField.svelte +203 -12
  191. package/src/SvForm.svelte +195 -21
  192. package/src/SvForm.test.ts +112 -0
  193. package/src/SvGrid.controller.svelte.ts +88 -7
  194. package/src/SvGrid.svelte +383 -181
  195. package/src/SvGrid.types.ts +125 -1
  196. package/src/SvGridChartView.svelte +70 -0
  197. package/src/SvGridDropdown.svelte +9 -2
  198. package/src/SvGridSelect.svelte +5 -2
  199. package/src/SvGroup.svelte +41 -0
  200. package/src/SvHoverCard.svelte +70 -0
  201. package/src/SvKbd.svelte +51 -0
  202. package/src/SvList.svelte +55 -0
  203. package/src/SvListBox.svelte +166 -77
  204. package/src/SvLoadingOverlay.svelte +53 -0
  205. package/src/SvMark.svelte +36 -0
  206. package/src/SvMaskedInput.svelte +50 -35
  207. package/src/SvMenuList.svelte +32 -3
  208. package/src/SvMenubar.svelte +200 -0
  209. package/src/SvMultiSelect.svelte +7 -4
  210. package/src/SvNumberInput.svelte +79 -42
  211. package/src/SvOtpInput.svelte +2 -2
  212. package/src/SvPasswordInput.svelte +51 -31
  213. package/src/SvPhoneInput.svelte +39 -28
  214. package/src/SvPopconfirm.svelte +79 -0
  215. package/src/SvPopover.svelte +87 -29
  216. package/src/SvRadioGroup.svelte +5 -1
  217. package/src/SvResult.svelte +73 -0
  218. package/src/SvSegmented.svelte +114 -0
  219. package/src/SvSimpleGrid.svelte +41 -0
  220. package/src/SvSlider.svelte +23 -10
  221. package/src/SvSpinner.svelte +43 -0
  222. package/src/SvStack.svelte +37 -0
  223. package/src/SvSwitchButton.svelte +6 -1
  224. package/src/SvTagsInput.svelte +9 -5
  225. package/src/SvText.svelte +76 -0
  226. package/src/SvTextInput.svelte +75 -43
  227. package/src/SvTimePicker.svelte +32 -2
  228. package/src/SvTitle.svelte +57 -0
  229. package/src/SvToaster.svelte +41 -6
  230. package/src/SvToaster.test.ts +32 -0
  231. package/src/SvToggleButton.svelte +4 -1
  232. package/src/SvTooltip.svelte +68 -34
  233. package/src/SvTree.svelte +81 -21
  234. package/src/SvTreeSelect.svelte +5 -2
  235. package/src/SvVisuallyHidden.svelte +49 -0
  236. package/src/ai.test.ts +502 -0
  237. package/src/ai.ts +1391 -0
  238. package/src/board-view.svelte.ts +33 -0
  239. package/src/build-api.coverage.test.ts +101 -0
  240. package/src/build-api.ts +43 -18
  241. package/src/builtin-editors.grid.test.ts +1 -1
  242. package/src/cell-formatting.ts +5 -5
  243. package/src/cell-render.ts +4 -4
  244. package/src/chart-view.svelte.ts +36 -0
  245. package/src/createCombobox.svelte.ts +17 -5
  246. package/src/createDropdownList.svelte.ts +8 -2
  247. package/src/createForm.svelte.ts +59 -6
  248. package/src/createMenu.svelte.ts +23 -0
  249. package/src/createPopoverSelect.svelte.ts +8 -1
  250. package/src/createSlider.svelte.ts +20 -0
  251. package/src/createTooltip.svelte.ts +67 -9
  252. package/src/editor-contract.ts +16 -0
  253. package/src/export-provider.ts +40 -0
  254. package/src/filter-operators.ts +37 -0
  255. package/src/form-field.ts +42 -2
  256. package/src/grid-messages.test.ts +24 -0
  257. package/src/grid-messages.ts +137 -0
  258. package/src/group-display.test.ts +77 -0
  259. package/src/group-display.ts +117 -0
  260. package/src/i18n.grid.test.ts +73 -0
  261. package/src/index.ts +91 -2
  262. package/src/js-scroller.svelte.ts +173 -0
  263. package/src/list-option.test.ts +56 -0
  264. package/src/list-option.ts +81 -0
  265. package/src/menus.test.ts +32 -0
  266. package/src/menus.ts +25 -12
  267. package/src/pivot-view.svelte.ts +90 -0
  268. package/src/pivot-view.test.ts +38 -0
  269. package/src/pivot.grid.test.ts +102 -0
  270. package/src/positioning.test.ts +141 -0
  271. package/src/positioning.ts +266 -0
  272. package/src/scheduler-model.test.ts +16 -0
  273. package/src/scheduler-model.ts +24 -5
  274. package/src/svgrid-wrapper.types.ts +23 -0
  275. package/src/svgrid.charting.test.ts +8 -1
  276. package/src/svgrid.comments-autocomplete.test.ts +7 -2
  277. package/src/svgrid.context-menu.test.ts +8 -3
  278. package/src/toast-store.svelte.ts +98 -0
  279. package/src/toast-store.test.ts +62 -1
  280. package/src/ui-breadth.test.ts +138 -0
  281. package/src/ui-buttons.test.ts +39 -0
  282. package/src/ui-inputs.test.ts +2 -2
  283. package/src/ui-range.test.ts +9 -0
  284. package/src/ui-selection.test.ts +36 -0
  285. package/src/ui-tier1.test.ts +1 -1
  286. package/src/virtual.test.ts +20 -6
  287. package/dist/SvGridBoard.svelte +0 -2339
  288. package/dist/SvGridBoard.svelte.d.ts +0 -31
  289. package/src/SvGridBoard.svelte +0 -2339
  290. package/src/board.test.ts +0 -927
@@ -0,0 +1,73 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvResult - a centered result / status page for the outcome of an operation or
4
+ * a route state: success, error, warning, info, or not-found. An icon (built-in
5
+ * per status, or your own), a title, an optional description, and an actions
6
+ * slot. For empty data tables prefer SvEmptyState; use this for full-page
7
+ * outcomes ("Payment complete", "Something went wrong", "404").
8
+ *
9
+ * ```svelte
10
+ * <SvResult status="success" title="Payment complete" description="A receipt is on its way.">
11
+ * {#snippet actions()}<SvButton>Back to dashboard</SvButton>{/snippet}
12
+ * </SvResult>
13
+ * ```
14
+ */
15
+ import type { Snippet } from 'svelte'
16
+
17
+ type Status = 'success' | 'error' | 'warning' | 'info' | 'notfound'
18
+
19
+ type Props = {
20
+ status?: Status
21
+ title: string
22
+ description?: string
23
+ /** Replace the built-in status icon. */
24
+ icon?: Snippet
25
+ /** Action buttons row under the text. */
26
+ actions?: Snippet
27
+ children?: Snippet
28
+ }
29
+
30
+ let { status = 'info', title, description, icon, actions, children }: Props = $props()
31
+ </script>
32
+
33
+ <div class="sv-result sv-result--{status}" role="status">
34
+ <div class="sv-result__icon" aria-hidden="true">
35
+ {#if icon}{@render icon()}
36
+ {:else if status === 'success'}
37
+ <svg viewBox="0 0 24 24" width="30" height="30" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
38
+ {:else if status === 'error'}
39
+ <svg viewBox="0 0 24 24" width="30" height="30" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12" /></svg>
40
+ {:else if status === 'warning'}
41
+ <svg viewBox="0 0 24 24" width="30" height="30" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z" /></svg>
42
+ {:else if status === 'notfound'}
43
+ <span class="sv-result__code">404</span>
44
+ {:else}
45
+ <svg viewBox="0 0 24 24" width="30" height="30" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9" /><path d="M12 8h.01M11 12h1v4h1" /></svg>
46
+ {/if}
47
+ </div>
48
+ <h2 class="sv-result__title">{title}</h2>
49
+ {#if description}<p class="sv-result__desc">{description}</p>{/if}
50
+ {#if children}<div class="sv-result__body">{@render children()}</div>{/if}
51
+ {#if actions}<div class="sv-result__actions">{@render actions()}</div>{/if}
52
+ </div>
53
+
54
+ <style>
55
+ .sv-result {
56
+ --_c: var(--sg-accent, #2563eb);
57
+ display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px;
58
+ padding: 40px 24px; max-width: 460px; margin: 0 auto;
59
+ }
60
+ .sv-result--success { --_c: var(--sg-success, #16a34a); }
61
+ .sv-result--error { --_c: var(--sg-danger, #dc2626); }
62
+ .sv-result--warning { --_c: var(--sg-warning, #f59e0b); }
63
+ .sv-result--notfound { --_c: var(--sg-muted, #64748b); }
64
+ .sv-result__icon {
65
+ display: grid; place-items: center; width: 60px; height: 60px; border-radius: 50%; margin-bottom: 4px;
66
+ color: var(--_c); background: color-mix(in srgb, var(--_c) 12%, transparent);
67
+ }
68
+ .sv-result__code { font-size: 22px; font-weight: 800; letter-spacing: 0.02em; }
69
+ .sv-result__title { margin: 0; font-size: 19px; font-weight: 700; color: var(--sg-fg, #0f172a); }
70
+ .sv-result__desc { margin: 0; font-size: 14px; line-height: 1.5; color: var(--sg-muted, #64748b); }
71
+ .sv-result__body { margin-top: 6px; }
72
+ .sv-result__actions { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; justify-content: center; }
73
+ </style>
@@ -0,0 +1,28 @@
1
+ /**
2
+ * SvResult - a centered result / status page for the outcome of an operation or
3
+ * a route state: success, error, warning, info, or not-found. An icon (built-in
4
+ * per status, or your own), a title, an optional description, and an actions
5
+ * slot. For empty data tables prefer SvEmptyState; use this for full-page
6
+ * outcomes ("Payment complete", "Something went wrong", "404").
7
+ *
8
+ * ```svelte
9
+ * <SvResult status="success" title="Payment complete" description="A receipt is on its way.">
10
+ * {#snippet actions()}<SvButton>Back to dashboard</SvButton>{/snippet}
11
+ * </SvResult>
12
+ * ```
13
+ */
14
+ import type { Snippet } from 'svelte';
15
+ type Status = 'success' | 'error' | 'warning' | 'info' | 'notfound';
16
+ type Props = {
17
+ status?: Status;
18
+ title: string;
19
+ description?: string;
20
+ /** Replace the built-in status icon. */
21
+ icon?: Snippet;
22
+ /** Action buttons row under the text. */
23
+ actions?: Snippet;
24
+ children?: Snippet;
25
+ };
26
+ declare const SvResult: import("svelte").Component<Props, {}, "">;
27
+ type SvResult = ReturnType<typeof SvResult>;
28
+ export default SvResult;
@@ -0,0 +1,114 @@
1
+ <script lang="ts" module>
2
+ export type { RadioOption as SegmentedOption } from './createRadioGroup.svelte'
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ /**
7
+ * SvSegmented - a segmented control: a compact row of mutually-exclusive
8
+ * options in a shared track (the modern alternative to a small radio group or a
9
+ * tab strip for a setting). Single-select, keyboard-accessible (it reuses the
10
+ * radio-group core: arrow keys roam, Space/Enter select), and themed from the
11
+ * shared `--sg-*` tokens.
12
+ *
13
+ * ```svelte
14
+ * <SvSegmented options={[{value:'list',label:'List'},{value:'grid',label:'Grid'}]} bind:value />
15
+ * ```
16
+ */
17
+ import type { Snippet } from 'svelte'
18
+ import SvField from './SvField.svelte'
19
+ import { createRadioGroup, type RadioOption } from './createRadioGroup.svelte'
20
+ import { nextEditorId, type SvEditorProps } from './editor-contract'
21
+
22
+ type SegOption = RadioOption & { icon?: Snippet }
23
+
24
+ type Props = Pick<
25
+ SvEditorProps,
26
+ 'disabled' | 'size' | 'dir' | 'id' | 'ariaLabel' | 'label' | 'hint' | 'error' | 'required' | 'invalid'
27
+ > & {
28
+ options: ReadonlyArray<SegOption>
29
+ value?: string | number | null
30
+ onChange?: (value: string | number) => void
31
+ /** Stretch the control (and split options evenly) to the container width. */
32
+ block?: boolean
33
+ name?: string
34
+ }
35
+
36
+ let {
37
+ options,
38
+ value = $bindable<string | number | null>(null),
39
+ onChange,
40
+ disabled = false,
41
+ size = 'md',
42
+ dir,
43
+ id,
44
+ ariaLabel,
45
+ label,
46
+ hint,
47
+ error,
48
+ required = false,
49
+ invalid = false,
50
+ block = false,
51
+ name,
52
+ }: Props = $props()
53
+
54
+ const autoId = nextEditorId('sv-seg')
55
+ const uid = $derived(id ?? autoId)
56
+
57
+ const rg = createRadioGroup({
58
+ options: () => options,
59
+ value: () => value,
60
+ onChange: (v) => { value = v; onChange?.(v) },
61
+ disabled: () => disabled,
62
+ ariaLabel: () => ariaLabel ?? label,
63
+ id: () => uid,
64
+ invalid: () => invalid,
65
+ required: () => required,
66
+ error: () => error,
67
+ })
68
+ </script>
69
+
70
+ <SvField id={uid} {label} {hint} {error} {required} {dir}>
71
+ <div class="sv-seg sv-seg--{size}" class:is-block={block} class:is-disabled={disabled} class:is-invalid={invalid} {...rg.groupProps()}>
72
+ {#each options as opt (opt.value)}
73
+ <button
74
+ class="sv-seg__opt"
75
+ class:is-selected={rg.isChecked(opt)}
76
+ {...rg.radioProps(opt)}
77
+ >
78
+ {#if opt.icon}<span class="sv-seg__icon">{@render opt.icon()}</span>{/if}
79
+ <span class="sv-seg__label">{opt.label}</span>
80
+ </button>
81
+ {/each}
82
+ {#if name}<input type="hidden" {name} value={value ?? ''} />{/if}
83
+ </div>
84
+ </SvField>
85
+
86
+ <style>
87
+ .sv-seg {
88
+ --_accent: var(--sg-accent, #2563eb);
89
+ display: inline-flex; gap: 2px; padding: 2px; box-sizing: border-box;
90
+ background: var(--sg-row-hover-bg, #f1f5f9); border-radius: calc(var(--sg-radius, 8px) + 2px);
91
+ border: 1px solid var(--sg-border, #e2e8f0);
92
+ }
93
+ .sv-seg.is-block { display: flex; width: 100%; }
94
+ .sv-seg.is-disabled { opacity: 0.6; }
95
+ .sv-seg__opt {
96
+ flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
97
+ padding: 0 12px; border: 0; border-radius: var(--sg-radius, 8px); background: none; cursor: pointer;
98
+ font: inherit; font-weight: 550; color: var(--sg-muted, #64748b); white-space: nowrap;
99
+ transition: background 0.14s, color 0.14s, box-shadow 0.14s;
100
+ }
101
+ .sv-seg--sm .sv-seg__opt { height: 26px; font-size: 12px; }
102
+ .sv-seg--md .sv-seg__opt { height: 32px; font-size: 13px; }
103
+ .sv-seg--lg .sv-seg__opt { height: 38px; font-size: 14.5px; }
104
+ .sv-seg__opt:hover:not(.is-selected):not([disabled]) { color: var(--sg-fg, #0f172a); }
105
+ .sv-seg__opt.is-selected {
106
+ background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
107
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.12);
108
+ }
109
+ .sv-seg__opt[disabled] { opacity: 0.5; cursor: default; }
110
+ .sv-seg__opt:focus-visible { outline: 2px solid var(--sg-focus-ring, var(--_accent)); outline-offset: -2px; }
111
+ .sv-seg.is-invalid { border-color: var(--sg-danger, #dc2626); }
112
+ .sv-seg__icon { display: inline-flex; }
113
+ @media (prefers-reduced-motion: reduce) { .sv-seg__opt { transition: none; } }
114
+ </style>
@@ -0,0 +1,29 @@
1
+ export type { RadioOption as SegmentedOption } from './createRadioGroup.svelte';
2
+ /**
3
+ * SvSegmented - a segmented control: a compact row of mutually-exclusive
4
+ * options in a shared track (the modern alternative to a small radio group or a
5
+ * tab strip for a setting). Single-select, keyboard-accessible (it reuses the
6
+ * radio-group core: arrow keys roam, Space/Enter select), and themed from the
7
+ * shared `--sg-*` tokens.
8
+ *
9
+ * ```svelte
10
+ * <SvSegmented options={[{value:'list',label:'List'},{value:'grid',label:'Grid'}]} bind:value />
11
+ * ```
12
+ */
13
+ import type { Snippet } from 'svelte';
14
+ import { type RadioOption } from './createRadioGroup.svelte';
15
+ import { type SvEditorProps } from './editor-contract';
16
+ type SegOption = RadioOption & {
17
+ icon?: Snippet;
18
+ };
19
+ type Props = Pick<SvEditorProps, 'disabled' | 'size' | 'dir' | 'id' | 'ariaLabel' | 'label' | 'hint' | 'error' | 'required' | 'invalid'> & {
20
+ options: ReadonlyArray<SegOption>;
21
+ value?: string | number | null;
22
+ onChange?: (value: string | number) => void;
23
+ /** Stretch the control (and split options evenly) to the container width. */
24
+ block?: boolean;
25
+ name?: string;
26
+ };
27
+ declare const SvSegmented: import("svelte").Component<Props, {}, "value">;
28
+ type SvSegmented = ReturnType<typeof SvSegmented>;
29
+ export default SvSegmented;
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvSimpleGrid - a responsive grid primitive: lays children into `cols` equal
4
+ * columns that auto-fit down to a `minChildWidth` before wrapping, with a
5
+ * consistent `gap`. Use it for card galleries, stat tiles, and dashboards.
6
+ *
7
+ * ```svelte
8
+ * <SvSimpleGrid minChildWidth={220} gap={12}>{#each tiles as t}<Card {t} />{/each}</SvSimpleGrid>
9
+ * ```
10
+ */
11
+ import type { Snippet } from 'svelte'
12
+
13
+ type Props = {
14
+ /**
15
+ * Fixed column count. When omitted, columns auto-fit based on
16
+ * `minChildWidth` (responsive by default).
17
+ */
18
+ cols?: number
19
+ /** Minimum child width (px) before wrapping, for the auto-fit layout. Default 200. */
20
+ minChildWidth?: number
21
+ /** Gap between cells (px, or any CSS length). Default 12. */
22
+ gap?: number | string
23
+ children?: Snippet
24
+ }
25
+
26
+ let { cols, minChildWidth = 200, gap = 12, children }: Props = $props()
27
+ const g = $derived(typeof gap === 'number' ? `${gap}px` : gap)
28
+ const template = $derived(
29
+ cols != null
30
+ ? `repeat(${cols}, minmax(0, 1fr))`
31
+ : `repeat(auto-fit, minmax(min(${minChildWidth}px, 100%), 1fr))`,
32
+ )
33
+ </script>
34
+
35
+ <div class="sv-simplegrid" style:gap={g} style:grid-template-columns={template}>
36
+ {@render children?.()}
37
+ </div>
38
+
39
+ <style>
40
+ .sv-simplegrid { display: grid; min-width: 0; }
41
+ </style>
@@ -0,0 +1,25 @@
1
+ /**
2
+ * SvSimpleGrid - a responsive grid primitive: lays children into `cols` equal
3
+ * columns that auto-fit down to a `minChildWidth` before wrapping, with a
4
+ * consistent `gap`. Use it for card galleries, stat tiles, and dashboards.
5
+ *
6
+ * ```svelte
7
+ * <SvSimpleGrid minChildWidth={220} gap={12}>{#each tiles as t}<Card {t} />{/each}</SvSimpleGrid>
8
+ * ```
9
+ */
10
+ import type { Snippet } from 'svelte';
11
+ type Props = {
12
+ /**
13
+ * Fixed column count. When omitted, columns auto-fit based on
14
+ * `minChildWidth` (responsive by default).
15
+ */
16
+ cols?: number;
17
+ /** Minimum child width (px) before wrapping, for the auto-fit layout. Default 200. */
18
+ minChildWidth?: number;
19
+ /** Gap between cells (px, or any CSS length). Default 12. */
20
+ gap?: number | string;
21
+ children?: Snippet;
22
+ };
23
+ declare const SvSimpleGrid: import("svelte").Component<Props, {}, "">;
24
+ type SvSimpleGrid = ReturnType<typeof SvSimpleGrid>;
25
+ export default SvSimpleGrid;
@@ -39,6 +39,8 @@
39
39
  labels = 'none',
40
40
  showValue = false,
41
41
  disabled = false,
42
+ readonly = false,
43
+ size = 'md',
42
44
  orientation = 'horizontal',
43
45
  name,
44
46
  ariaLabel,
@@ -60,7 +62,7 @@
60
62
  // in the headless `createSlider` core; the component keeps the DOM measuring.
61
63
  const slider = createSlider({
62
64
  value: () => value,
63
- onChange: (v) => onChange?.(v),
65
+ onChange: (v) => { if (readonly) return; onChange?.(v) },
64
66
  min: () => min,
65
67
  max: () => max,
66
68
  step: () => step,
@@ -69,6 +71,11 @@
69
71
  disabled: () => disabled,
70
72
  ariaLabel: () => ariaLabel ?? label,
71
73
  rtl: () => resolvedDir === 'rtl',
74
+ id: () => uid,
75
+ invalid: () => invalid,
76
+ required: () => required,
77
+ error: () => error,
78
+ hint: () => hint,
72
79
  })
73
80
  const lo = $derived(slider.lo)
74
81
  const hi = $derived(slider.hi)
@@ -87,7 +94,7 @@
87
94
  // The rect is measured here (a DOM concern) and passed INTO the core.
88
95
  let trackEl: HTMLDivElement | null = null
89
96
  function onTrackDown(e: PointerEvent) {
90
- if (disabled) return
97
+ if (disabled || readonly) return
91
98
  slider.pointerDown({ x: e.clientX, y: e.clientY }, trackEl!.getBoundingClientRect())
92
99
  trackEl?.setPointerCapture(e.pointerId)
93
100
  }
@@ -102,8 +109,9 @@
102
109
 
103
110
  <SvField id={uid} {label} {hint} {error} {required} {dir}>
104
111
  <div
105
- class="sv-slider sv-slider--{orientation}"
112
+ class="sv-slider sv-slider--{orientation} sv-slider--{size}"
106
113
  class:is-disabled={disabled}
114
+ class:is-readonly={readonly}
107
115
  dir={resolvedDir}
108
116
  >
109
117
  <!-- svelte-ignore a11y_no_static_element_interactions -->
@@ -126,14 +134,14 @@
126
134
  {/each}
127
135
 
128
136
  {#if range}
129
- <div class="sv-slider__thumb" style:--p={`${pct(lo)}%`} {...slider.thumbProps(0)}>
137
+ <div class="sv-slider__thumb" style:--p={`${pct(lo)}%`} {...slider.thumbProps(0)} aria-readonly={readonly ? 'true' : undefined}>
130
138
  {#if showValue}<span class="sv-slider__bubble">{fmt(lo)}</span>{/if}
131
139
  </div>
132
- <div class="sv-slider__thumb" style:--p={`${pct(hi)}%`} {...slider.thumbProps(1)}>
140
+ <div class="sv-slider__thumb" style:--p={`${pct(hi)}%`} {...slider.thumbProps(1)} aria-readonly={readonly ? 'true' : undefined}>
133
141
  {#if showValue}<span class="sv-slider__bubble">{fmt(hi)}</span>{/if}
134
142
  </div>
135
143
  {:else}
136
- <div class="sv-slider__thumb" style:--p={`${pct(hi)}%`} {...slider.thumbProps(0)}>
144
+ <div class="sv-slider__thumb" style:--p={`${pct(hi)}%`} {...slider.thumbProps(0)} aria-readonly={readonly ? 'true' : undefined}>
137
145
  {#if showValue}<span class="sv-slider__bubble">{fmt(hi)}</span>{/if}
138
146
  </div>
139
147
  {/if}
@@ -152,15 +160,20 @@
152
160
  </SvField>
153
161
 
154
162
  <style>
155
- .sv-slider { --_accent: var(--sg-accent, #2563eb); --_track: var(--sg-border, #e2e8f0); padding: 10px; }
163
+ .sv-slider { --_accent: var(--sg-accent, #2563eb); --_track: var(--sg-border, #e2e8f0); --_th: 16px; --_trk: 6px; padding: 10px; }
164
+ .sv-slider--sm { --_th: 13px; --_trk: 4px; }
165
+ .sv-slider--lg { --_th: 20px; --_trk: 8px; }
156
166
  .sv-slider--horizontal { width: 240px; }
167
+ .sv-slider--horizontal.sv-slider--sm { width: 180px; }
168
+ .sv-slider--horizontal.sv-slider--lg { width: 300px; }
157
169
  .sv-slider--vertical { height: 200px; width: 40px; }
158
170
  .sv-slider.is-disabled { opacity: 0.5; pointer-events: none; }
171
+ .sv-slider.is-readonly .sv-slider__track, .sv-slider.is-readonly .sv-slider__thumb { cursor: default; }
159
172
  .sv-slider__track {
160
173
  position: relative; background: var(--_track); border-radius: 999px; cursor: pointer; touch-action: none;
161
174
  }
162
- .sv-slider--horizontal .sv-slider__track { height: 6px; }
163
- .sv-slider--vertical .sv-slider__track { width: 6px; height: 100%; margin: 0 auto; }
175
+ .sv-slider--horizontal .sv-slider__track { height: var(--_trk); }
176
+ .sv-slider--vertical .sv-slider__track { width: var(--_trk); height: 100%; margin: 0 auto; }
164
177
  .sv-slider__scale { position: relative; height: 15px; margin-top: 8px; font-size: 11px; color: var(--sg-muted, #64748b); font-variant-numeric: tabular-nums; }
165
178
  .sv-slider__scale--ends { display: flex; justify-content: space-between; }
166
179
  .sv-slider__scale-lbl { position: absolute; inset-inline-start: var(--p); transform: translateX(-50%); white-space: nowrap; }
@@ -168,7 +181,7 @@
168
181
  .sv-slider--horizontal .sv-slider__fill { inset-inline-start: var(--a); inset-inline-end: calc(100% - var(--b)); top: 0; bottom: 0; }
169
182
  .sv-slider--vertical .sv-slider__fill { bottom: var(--a); top: calc(100% - var(--b)); left: 0; right: 0; }
170
183
  .sv-slider__thumb {
171
- position: absolute; width: 16px; height: 16px; border-radius: 50%;
184
+ position: absolute; width: var(--_th); height: var(--_th); border-radius: 50%;
172
185
  background: #fff; border: 2px solid var(--_accent); box-shadow: 0 1px 3px rgba(0,0,0,0.25);
173
186
  cursor: grab; touch-action: none;
174
187
  }
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvSpinner - a dedicated indeterminate loading spinner (distinct from the
4
+ * determinate SvProgress bars). Sizeable, colorable, and it respects
5
+ * `prefers-reduced-motion`. Give it a `label` for screen readers.
6
+ *
7
+ * ```svelte
8
+ * <SvSpinner size="lg" label="Loading results" />
9
+ * ```
10
+ */
11
+ type Props = {
12
+ /** Diameter in px, or a named size. Default `md` (20px). */
13
+ size?: 'sm' | 'md' | 'lg' | number
14
+ /** Stroke color (defaults to the accent token). */
15
+ color?: string
16
+ /** Accessible label; when omitted the spinner is `aria-hidden`. */
17
+ label?: string
18
+ }
19
+
20
+ let { size = 'md', color, label }: Props = $props()
21
+ const px = $derived(typeof size === 'number' ? size : size === 'sm' ? 15 : size === 'lg' ? 28 : 20)
22
+ </script>
23
+
24
+ <span
25
+ class="sv-spinner"
26
+ role={label ? 'status' : undefined}
27
+ aria-label={label}
28
+ aria-hidden={label ? undefined : 'true'}
29
+ style:width={`${px}px`}
30
+ style:height={`${px}px`}
31
+ style:color={color}
32
+ ></span>
33
+
34
+ <style>
35
+ .sv-spinner {
36
+ display: inline-block; box-sizing: border-box; flex: none; border-radius: 50%;
37
+ border: 2px solid color-mix(in srgb, currentcolor 25%, transparent);
38
+ border-top-color: currentcolor; color: var(--sg-accent, #2563eb);
39
+ animation: sv-spinner-rot 0.6s linear infinite;
40
+ }
41
+ @keyframes sv-spinner-rot { to { transform: rotate(360deg); } }
42
+ @media (prefers-reduced-motion: reduce) { .sv-spinner { animation-duration: 1.4s; } }
43
+ </style>
@@ -0,0 +1,20 @@
1
+ /**
2
+ * SvSpinner - a dedicated indeterminate loading spinner (distinct from the
3
+ * determinate SvProgress bars). Sizeable, colorable, and it respects
4
+ * `prefers-reduced-motion`. Give it a `label` for screen readers.
5
+ *
6
+ * ```svelte
7
+ * <SvSpinner size="lg" label="Loading results" />
8
+ * ```
9
+ */
10
+ type Props = {
11
+ /** Diameter in px, or a named size. Default `md` (20px). */
12
+ size?: 'sm' | 'md' | 'lg' | number;
13
+ /** Stroke color (defaults to the accent token). */
14
+ color?: string;
15
+ /** Accessible label; when omitted the spinner is `aria-hidden`. */
16
+ label?: string;
17
+ };
18
+ declare const SvSpinner: import("svelte").Component<Props, {}, "">;
19
+ type SvSpinner = ReturnType<typeof SvSpinner>;
20
+ export default SvSpinner;
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvStack - a vertical flex layout primitive: stacks children in a column with a
4
+ * consistent `gap` and optional cross-axis `align`. The building block for form
5
+ * rows, card bodies, and sidebars. (For a horizontal row use SvGroup.)
6
+ *
7
+ * ```svelte
8
+ * <SvStack gap={12}><A /><B /><C /></SvStack>
9
+ * ```
10
+ */
11
+ import type { Snippet } from 'svelte'
12
+
13
+ type Props = {
14
+ /** Gap between children (px, or any CSS length). Default 12. */
15
+ gap?: number | string
16
+ /** Cross-axis alignment. */
17
+ align?: 'start' | 'center' | 'end' | 'stretch'
18
+ /** Main-axis distribution. */
19
+ justify?: 'start' | 'center' | 'end' | 'between' | 'around'
20
+ /** Wrapping element tag. Default `div`. */
21
+ as?: string
22
+ children?: Snippet
23
+ }
24
+
25
+ let { gap = 12, align = 'stretch', justify = 'start', as = 'div', children }: Props = $props()
26
+ const g = $derived(typeof gap === 'number' ? `${gap}px` : gap)
27
+ const alignMap = { start: 'flex-start', center: 'center', end: 'flex-end', stretch: 'stretch' } as const
28
+ const justifyMap = { start: 'flex-start', center: 'center', end: 'flex-end', between: 'space-between', around: 'space-around' } as const
29
+ </script>
30
+
31
+ <svelte:element this={as} class="sv-stack" style:gap={g} style:align-items={alignMap[align]} style:justify-content={justifyMap[justify]}>
32
+ {@render children?.()}
33
+ </svelte:element>
34
+
35
+ <style>
36
+ .sv-stack { display: flex; flex-direction: column; min-width: 0; }
37
+ </style>
@@ -0,0 +1,24 @@
1
+ /**
2
+ * SvStack - a vertical flex layout primitive: stacks children in a column with a
3
+ * consistent `gap` and optional cross-axis `align`. The building block for form
4
+ * rows, card bodies, and sidebars. (For a horizontal row use SvGroup.)
5
+ *
6
+ * ```svelte
7
+ * <SvStack gap={12}><A /><B /><C /></SvStack>
8
+ * ```
9
+ */
10
+ import type { Snippet } from 'svelte';
11
+ type Props = {
12
+ /** Gap between children (px, or any CSS length). Default 12. */
13
+ gap?: number | string;
14
+ /** Cross-axis alignment. */
15
+ align?: 'start' | 'center' | 'end' | 'stretch';
16
+ /** Main-axis distribution. */
17
+ justify?: 'start' | 'center' | 'end' | 'between' | 'around';
18
+ /** Wrapping element tag. Default `div`. */
19
+ as?: string;
20
+ children?: Snippet;
21
+ };
22
+ declare const SvStack: import("svelte").Component<Props, {}, "">;
23
+ type SvStack = ReturnType<typeof SvStack>;
24
+ export default SvStack;
@@ -20,6 +20,7 @@
20
20
  checked = false,
21
21
  onChange,
22
22
  disabled = false,
23
+ readonly = false,
23
24
  size = 'md',
24
25
  name,
25
26
  ariaLabel,
@@ -40,7 +41,7 @@
40
41
  // The styled switch is just a renderer over the headless core.
41
42
  const sw = createSwitch({
42
43
  checked: () => checked,
43
- onChange: (v) => onChange?.(v),
44
+ onChange: (v) => { if (readonly) return; onChange?.(v) },
44
45
  disabled: () => disabled,
45
46
  ariaLabel: () => ariaLabel,
46
47
  id: () => uid,
@@ -53,9 +54,12 @@
53
54
 
54
55
  <SvField id={uid} {label} {hint} {error} {required} {dir}>
55
56
  <button
57
+ role="switch"
56
58
  class="sv-switch sv-switch--{size}"
57
59
  class:is-on={checked}
60
+ class:is-readonly={readonly}
58
61
  {...sw.switchProps()}
62
+ aria-readonly={readonly ? 'true' : undefined}
59
63
  >
60
64
  <span class="sv-switch__track">
61
65
  {#if onLabel || offLabel}
@@ -77,6 +81,7 @@
77
81
  .sv-switch--sm { --_h: 18px; --_w: 32px; }
78
82
  .sv-switch--lg { --_h: 28px; --_w: 52px; }
79
83
  .sv-switch[disabled] { opacity: 0.5; cursor: not-allowed; }
84
+ .sv-switch.is-readonly { cursor: default; }
80
85
  .sv-switch__track {
81
86
  position: relative; width: var(--_w); height: var(--_h); border-radius: 999px;
82
87
  background: var(--sg-border, #cbd5e1); transition: background 0.16s;
@@ -33,6 +33,7 @@
33
33
  disabled = false,
34
34
  unique = true,
35
35
  max = Infinity,
36
+ size = 'md',
36
37
  name,
37
38
  ariaLabel,
38
39
  invalid = false,
@@ -68,7 +69,7 @@
68
69
  </script>
69
70
 
70
71
  <SvField id={uid} {label} {hint} {error} {required} {dir}>
71
- <div class="sv-tags" class:is-disabled={disabled} class:is-invalid={invalid} {...ti.rootProps()}>
72
+ <div class="sv-tags sv-tags--{size}" class:is-disabled={disabled} class:is-invalid={invalid} {...ti.rootProps()}>
72
73
  {#each value as tag, i (tag + i)}
73
74
  <span class="sv-tags__chip" {...ti.tagProps(i)}>
74
75
  <span class="sv-tags__label">{tag}</span>
@@ -89,20 +90,23 @@
89
90
  <style>
90
91
  .sv-tags {
91
92
  --_accent: var(--sg-accent, #2563eb);
92
- display: flex; flex-wrap: wrap; gap: 5px; align-items: center; width: 280px; min-height: 34px; padding: 4px 6px;
93
+ --_minh: 34px; --_chip-h: 22px; --_fs: 13px;
94
+ display: flex; flex-wrap: wrap; gap: 5px; align-items: center; width: 280px; min-height: var(--_minh); padding: 4px 6px;
93
95
  background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
94
96
  border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px);
95
97
  }
98
+ .sv-tags--sm { --_minh: 28px; --_chip-h: 19px; --_fs: 12px; }
99
+ .sv-tags--lg { --_minh: 40px; --_chip-h: 26px; --_fs: 15px; }
96
100
  .sv-tags:focus-within { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); }
97
101
  .sv-tags.is-invalid { border-color: var(--sg-danger, #dc2626); }
98
102
  .sv-tags.is-invalid:focus-within { box-shadow: 0 0 0 2px color-mix(in srgb, var(--sg-danger, #dc2626) 22%, transparent); }
99
103
  .sv-tags.is-disabled { opacity: 0.6; }
100
104
  .sv-tags__chip {
101
- display: inline-flex; align-items: center; gap: 4px; height: 22px; padding-block: 0; padding-inline: 8px 4px;
105
+ display: inline-flex; align-items: center; gap: 4px; height: var(--_chip-h); padding-block: 0; padding-inline: 8px 4px;
102
106
  background: color-mix(in srgb, var(--_accent) 14%, transparent); color: var(--_accent);
103
- border-radius: 5px; font-size: 12px; font-weight: 600;
107
+ border-radius: 5px; font-size: calc(var(--_fs) - 1px); font-weight: 600;
104
108
  }
105
109
  .sv-tags__x { background: none; border: 0; color: inherit; cursor: pointer; font-size: 15px; line-height: 1; padding: 0 2px; opacity: 0.7; }
106
110
  .sv-tags__x:hover { opacity: 1; }
107
- .sv-tags__input { flex: 1; min-width: 80px; border: 0; background: none; outline: none; color: inherit; font: inherit; font-size: 13px; height: 24px; }
111
+ .sv-tags__input { flex: 1; min-width: 80px; border: 0; background: none; outline: none; color: inherit; font: inherit; font-size: var(--_fs); height: 24px; }
108
112
  </style>