@svgrid/grid 1.2.22 → 1.2.24

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 (263) hide show
  1. package/dist/GridFooter.svelte +34 -20
  2. package/dist/GridFooter.svelte.d.ts +8 -0
  3. package/dist/SvAutoComplete.svelte +89 -0
  4. package/dist/SvAutoComplete.svelte.d.ts +16 -0
  5. package/dist/SvButton.svelte +97 -0
  6. package/dist/SvButton.svelte.d.ts +23 -0
  7. package/dist/SvCalendar.svelte +409 -0
  8. package/dist/SvCalendar.svelte.d.ts +52 -0
  9. package/dist/SvCheckBox.svelte +82 -0
  10. package/dist/SvCheckBox.svelte.d.ts +19 -0
  11. package/dist/SvColorInput.svelte +160 -0
  12. package/dist/SvColorInput.svelte.d.ts +15 -0
  13. package/dist/SvComboBox.svelte +108 -0
  14. package/dist/SvComboBox.svelte.d.ts +15 -0
  15. package/dist/SvCountryInput.svelte +125 -0
  16. package/dist/SvCountryInput.svelte.d.ts +14 -0
  17. package/dist/SvDateTimePicker.svelte +265 -0
  18. package/dist/SvDateTimePicker.svelte.d.ts +38 -0
  19. package/dist/SvDropDownList.svelte +120 -0
  20. package/dist/SvDropDownList.svelte.d.ts +15 -0
  21. package/dist/SvForm.svelte +147 -0
  22. package/dist/SvForm.svelte.d.ts +29 -0
  23. package/dist/SvGauge.svelte +97 -0
  24. package/dist/SvGauge.svelte.d.ts +26 -0
  25. package/dist/SvGrid.controller.svelte.d.ts +16 -2
  26. package/dist/SvGrid.controller.svelte.js +63 -8
  27. package/dist/SvGrid.css +84 -31
  28. package/dist/SvGrid.helpers.d.ts +4 -0
  29. package/dist/SvGrid.helpers.js +40 -12
  30. package/dist/SvGrid.svelte +84 -5
  31. package/dist/SvGrid.types.d.ts +36 -0
  32. package/dist/SvGridDropdown.svelte +16 -30
  33. package/dist/SvGridDropdown.svelte.d.ts +4 -0
  34. package/dist/SvListBox.svelte +89 -0
  35. package/dist/SvListBox.svelte.d.ts +22 -0
  36. package/dist/SvMaskedInput.svelte +66 -0
  37. package/dist/SvMaskedInput.svelte.d.ts +15 -0
  38. package/dist/SvNumberInput.svelte +116 -0
  39. package/dist/SvNumberInput.svelte.d.ts +18 -0
  40. package/dist/SvPasswordInput.svelte +100 -0
  41. package/dist/SvPasswordInput.svelte.d.ts +18 -0
  42. package/dist/SvPhoneInput.svelte +87 -0
  43. package/dist/SvPhoneInput.svelte.d.ts +19 -0
  44. package/dist/SvRadioGroup.svelte +85 -0
  45. package/dist/SvRadioGroup.svelte.d.ts +20 -0
  46. package/dist/SvRating.svelte +91 -0
  47. package/dist/SvRating.svelte.d.ts +18 -0
  48. package/dist/SvRepeatButton.svelte +89 -0
  49. package/dist/SvRepeatButton.svelte.d.ts +21 -0
  50. package/dist/SvSlider.svelte +155 -0
  51. package/dist/SvSlider.svelte.d.ts +20 -0
  52. package/dist/SvSwitchButton.svelte +87 -0
  53. package/dist/SvSwitchButton.svelte.d.ts +14 -0
  54. package/dist/SvTabs.svelte +109 -0
  55. package/dist/SvTabs.svelte.d.ts +26 -0
  56. package/dist/SvTagsInput.svelte +70 -0
  57. package/dist/SvTagsInput.svelte.d.ts +14 -0
  58. package/dist/SvTimePicker.svelte +201 -0
  59. package/dist/SvTimePicker.svelte.d.ts +30 -0
  60. package/dist/SvToggleButton.svelte +57 -0
  61. package/dist/SvToggleButton.svelte.d.ts +16 -0
  62. package/dist/SvTree.svelte +131 -0
  63. package/dist/SvTree.svelte.d.ts +27 -0
  64. package/dist/build-api.js +78 -1
  65. package/dist/cdn/svgrid.js +11674 -5907
  66. package/dist/cdn/svgrid.svelte-external.js +10436 -4671
  67. package/dist/cell-render.d.ts +4 -0
  68. package/dist/cell-render.js +35 -1
  69. package/dist/clipboard.js +19 -1
  70. package/dist/collaboration.d.ts +2 -0
  71. package/dist/collaboration.js +4 -0
  72. package/dist/core.d.ts +22 -1
  73. package/dist/countries.d.ts +15 -0
  74. package/dist/countries.js +61 -0
  75. package/dist/createAutocomplete.svelte.d.ts +77 -0
  76. package/dist/createAutocomplete.svelte.js +100 -0
  77. package/dist/createCalendar.svelte.d.ts +192 -0
  78. package/dist/createCalendar.svelte.js +402 -0
  79. package/dist/createCheckbox.svelte.d.ts +45 -0
  80. package/dist/createCheckbox.svelte.js +26 -0
  81. package/dist/createColorInput.svelte.d.ts +67 -0
  82. package/dist/createColorInput.svelte.js +100 -0
  83. package/dist/createCombobox.svelte.d.ts +102 -0
  84. package/dist/createCombobox.svelte.js +171 -0
  85. package/dist/createCountryInput.svelte.d.ts +86 -0
  86. package/dist/createCountryInput.svelte.js +126 -0
  87. package/dist/createDateTimePicker.svelte.d.ts +83 -0
  88. package/dist/createDateTimePicker.svelte.js +202 -0
  89. package/dist/createDropdownList.svelte.d.ts +78 -0
  90. package/dist/createDropdownList.svelte.js +117 -0
  91. package/dist/createGauge.svelte.d.ts +56 -0
  92. package/dist/createGauge.svelte.js +49 -0
  93. package/dist/createListbox.svelte.d.ts +79 -0
  94. package/dist/createListbox.svelte.js +117 -0
  95. package/dist/createMaskedInput.svelte.d.ts +30 -0
  96. package/dist/createMaskedInput.svelte.js +62 -0
  97. package/dist/createNumberInput.svelte.d.ts +72 -0
  98. package/dist/createNumberInput.svelte.js +167 -0
  99. package/dist/createPasswordInput.svelte.d.ts +60 -0
  100. package/dist/createPasswordInput.svelte.js +72 -0
  101. package/dist/createPhoneInput.svelte.d.ts +46 -0
  102. package/dist/createPhoneInput.svelte.js +105 -0
  103. package/dist/createRadioGroup.svelte.d.ts +64 -0
  104. package/dist/createRadioGroup.svelte.js +73 -0
  105. package/dist/createRating.svelte.d.ts +70 -0
  106. package/dist/createRating.svelte.js +85 -0
  107. package/dist/createSlider.svelte.d.ts +71 -0
  108. package/dist/createSlider.svelte.js +123 -0
  109. package/dist/createSwitch.svelte.d.ts +43 -0
  110. package/dist/createSwitch.svelte.js +41 -0
  111. package/dist/createTabs.svelte.d.ts +78 -0
  112. package/dist/createTabs.svelte.js +92 -0
  113. package/dist/createTagsInput.svelte.d.ts +65 -0
  114. package/dist/createTagsInput.svelte.js +93 -0
  115. package/dist/createTimePicker.svelte.d.ts +106 -0
  116. package/dist/createTimePicker.svelte.js +248 -0
  117. package/dist/createToggle.svelte.d.ts +43 -0
  118. package/dist/createToggle.svelte.js +39 -0
  119. package/dist/createTree.svelte.d.ts +96 -0
  120. package/dist/createTree.svelte.js +194 -0
  121. package/dist/datetime/date-core.d.ts +88 -0
  122. package/dist/datetime/date-core.js +165 -0
  123. package/dist/datetime/date-format.d.ts +39 -0
  124. package/dist/datetime/date-format.js +371 -0
  125. package/dist/datetime/date-restrict.d.ts +23 -0
  126. package/dist/datetime/date-restrict.js +50 -0
  127. package/dist/datetime/date-selection.d.ts +25 -0
  128. package/dist/datetime/date-selection.js +94 -0
  129. package/dist/datetime/mask.d.ts +21 -0
  130. package/dist/datetime/mask.js +90 -0
  131. package/dist/editing.d.ts +1 -1
  132. package/dist/editing.js +7 -0
  133. package/dist/editor-contract.d.ts +48 -0
  134. package/dist/editor-contract.js +26 -0
  135. package/dist/editors/cell-editors.d.ts +2 -2
  136. package/dist/editors/cell-editors.js +3 -1
  137. package/dist/export-format.d.ts +178 -0
  138. package/dist/export-format.js +419 -0
  139. package/dist/hyperformula-adapter.d.ts +4 -0
  140. package/dist/hyperformula-adapter.js +15 -6
  141. package/dist/index.d.ts +60 -0
  142. package/dist/index.js +72 -0
  143. package/dist/list-option.d.ts +10 -0
  144. package/dist/list-option.js +7 -0
  145. package/dist/menus.js +18 -2
  146. package/dist/popover.d.ts +48 -0
  147. package/dist/popover.js +65 -0
  148. package/dist/row-resize.d.ts +4 -4
  149. package/dist/row-resize.js +8 -5
  150. package/dist/selection.d.ts +6 -0
  151. package/dist/selection.js +31 -5
  152. package/dist/server-data-source.d.ts +43 -0
  153. package/dist/server-data-source.js +100 -0
  154. package/dist/sparkline.js +8 -4
  155. package/dist/svgrid-wrapper.types.d.ts +26 -1
  156. package/package.json +6 -1
  157. package/src/GridFooter.svelte +34 -20
  158. package/src/SvAutoComplete.svelte +89 -0
  159. package/src/SvButton.svelte +97 -0
  160. package/src/SvCalendar.svelte +409 -0
  161. package/src/SvCalendar.test.ts +211 -0
  162. package/src/SvCheckBox.svelte +82 -0
  163. package/src/SvColorInput.svelte +160 -0
  164. package/src/SvComboBox.svelte +108 -0
  165. package/src/SvCountryInput.svelte +125 -0
  166. package/src/SvDateTimePicker.svelte +265 -0
  167. package/src/SvDateTimePicker.test.ts +136 -0
  168. package/src/SvDropDownList.svelte +120 -0
  169. package/src/SvForm.svelte +147 -0
  170. package/src/SvGauge.svelte +97 -0
  171. package/src/SvGrid.controller.svelte.ts +74 -8
  172. package/src/SvGrid.css +84 -31
  173. package/src/SvGrid.helpers.ts +41 -12
  174. package/src/SvGrid.svelte +84 -5
  175. package/src/SvGrid.types.ts +33 -0
  176. package/src/SvGridDropdown.svelte +16 -30
  177. package/src/SvListBox.svelte +89 -0
  178. package/src/SvMaskedInput.svelte +66 -0
  179. package/src/SvNumberInput.svelte +116 -0
  180. package/src/SvPasswordInput.svelte +100 -0
  181. package/src/SvPhoneInput.svelte +87 -0
  182. package/src/SvRadioGroup.svelte +85 -0
  183. package/src/SvRating.svelte +91 -0
  184. package/src/SvRepeatButton.svelte +89 -0
  185. package/src/SvSlider.svelte +155 -0
  186. package/src/SvSwitchButton.svelte +87 -0
  187. package/src/SvTabs.svelte +109 -0
  188. package/src/SvTagsInput.svelte +70 -0
  189. package/src/SvTimePicker.svelte +201 -0
  190. package/src/SvTimePicker.test.ts +98 -0
  191. package/src/SvToggleButton.svelte +57 -0
  192. package/src/SvTree.svelte +131 -0
  193. package/src/build-api.ts +115 -0
  194. package/src/cell-render.test.ts +38 -0
  195. package/src/cell-render.ts +43 -0
  196. package/src/clipboard.test.ts +18 -0
  197. package/src/clipboard.ts +24 -1
  198. package/src/collaboration.test.ts +30 -0
  199. package/src/collaboration.ts +6 -0
  200. package/src/core.ts +27 -3
  201. package/src/countries.ts +71 -0
  202. package/src/createAutocomplete.svelte.ts +104 -0
  203. package/src/createCalendar.svelte.ts +488 -0
  204. package/src/createCheckbox.svelte.ts +74 -0
  205. package/src/createColorInput.svelte.ts +115 -0
  206. package/src/createCombobox.svelte.ts +158 -0
  207. package/src/createCountryInput.svelte.ts +126 -0
  208. package/src/createDateTimePicker.svelte.ts +216 -0
  209. package/src/createDropdownList.svelte.ts +125 -0
  210. package/src/createGauge.svelte.ts +86 -0
  211. package/src/createListbox.svelte.ts +186 -0
  212. package/src/createMaskedInput.svelte.ts +81 -0
  213. package/src/createNumberInput.svelte.ts +193 -0
  214. package/src/createPasswordInput.svelte.ts +87 -0
  215. package/src/createPhoneInput.svelte.ts +119 -0
  216. package/src/createRadioGroup.svelte.ts +132 -0
  217. package/src/createRating.svelte.ts +145 -0
  218. package/src/createSlider.svelte.ts +160 -0
  219. package/src/createSwitch.svelte.ts +78 -0
  220. package/src/createTabs.svelte.ts +129 -0
  221. package/src/createTagsInput.svelte.ts +98 -0
  222. package/src/createTimePicker.svelte.ts +289 -0
  223. package/src/createToggle.svelte.ts +69 -0
  224. package/src/createTree.svelte.ts +216 -0
  225. package/src/datetime/date-core.test.ts +217 -0
  226. package/src/datetime/date-core.ts +204 -0
  227. package/src/datetime/date-format.test.ts +121 -0
  228. package/src/datetime/date-format.ts +317 -0
  229. package/src/datetime/date-restrict.ts +60 -0
  230. package/src/datetime/date-selection.test.ts +129 -0
  231. package/src/datetime/date-selection.ts +137 -0
  232. package/src/datetime/mask.test.ts +36 -0
  233. package/src/datetime/mask.ts +84 -0
  234. package/src/editing.test.ts +22 -0
  235. package/src/editing.ts +7 -1
  236. package/src/editor-contract.test.ts +32 -0
  237. package/src/editor-contract.ts +60 -0
  238. package/src/editors/cell-editors.ts +7 -1
  239. package/src/export-data-api.test.ts +126 -0
  240. package/src/export-format.test.ts +107 -0
  241. package/src/export-format.ts +598 -0
  242. package/src/hyperformula-adapter.test.ts +35 -1
  243. package/src/hyperformula-adapter.ts +18 -6
  244. package/src/index.ts +110 -0
  245. package/src/list-option.ts +15 -0
  246. package/src/menus.ts +21 -2
  247. package/src/popover.ts +79 -0
  248. package/src/row-resize.test.ts +25 -0
  249. package/src/row-resize.ts +8 -5
  250. package/src/selection.test.ts +36 -4
  251. package/src/selection.ts +30 -9
  252. package/src/server-data-source.test.ts +201 -0
  253. package/src/server-data-source.ts +148 -0
  254. package/src/sparkline.test.ts +9 -0
  255. package/src/sparkline.ts +9 -4
  256. package/src/svgrid-wrapper.types.ts +28 -1
  257. package/src/svgrid.behavior.test.ts +27 -0
  258. package/src/svgrid.new-features.wrapper.test.ts +27 -1
  259. package/src/ui-buttons.test.ts +105 -0
  260. package/src/ui-composite.test.ts +89 -0
  261. package/src/ui-inputs.test.ts +118 -0
  262. package/src/ui-range.test.ts +61 -0
  263. package/src/ui-selection.test.ts +119 -0
@@ -0,0 +1,18 @@
1
+ import { type SvEditorProps } from './editor-contract';
2
+ type Props = SvEditorProps & {
3
+ value?: number | null;
4
+ onChange?: (value: number | null) => void;
5
+ min?: number;
6
+ max?: number;
7
+ step?: number;
8
+ precision?: number;
9
+ /** Group thousands (1,234) on display. */
10
+ grouping?: boolean;
11
+ prefix?: string;
12
+ suffix?: string;
13
+ placeholder?: string;
14
+ spinButtons?: boolean;
15
+ };
16
+ declare const SvNumberInput: import("svelte").Component<Props, {}, "">;
17
+ type SvNumberInput = ReturnType<typeof SvNumberInput>;
18
+ export default SvNumberInput;
@@ -0,0 +1,100 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvPasswordInput - a password field with a reveal toggle and an optional
4
+ * strength meter. Parity: Smart `smart-password-input`. Emits the string value.
5
+ *
6
+ * The styled renderer over the headless `createPasswordInput` core: the reveal
7
+ * toggle + strength heuristic come from the core, spread here via prop-getters.
8
+ */
9
+ import { createPasswordInput } from './createPasswordInput.svelte'
10
+
11
+ type Props = {
12
+ value?: string
13
+ onChange?: (value: string) => void
14
+ placeholder?: string
15
+ disabled?: boolean
16
+ readonly?: boolean
17
+ /** Show the show/hide eye toggle. */
18
+ revealable?: boolean
19
+ /** Show a 4-level strength meter. */
20
+ showStrength?: boolean
21
+ name?: string
22
+ size?: 'sm' | 'md' | 'lg'
23
+ ariaLabel?: string
24
+ autocomplete?: string
25
+ }
26
+
27
+ let {
28
+ value = '',
29
+ onChange,
30
+ placeholder,
31
+ disabled = false,
32
+ readonly = false,
33
+ revealable = true,
34
+ showStrength = false,
35
+ name,
36
+ size = 'md',
37
+ ariaLabel,
38
+ autocomplete = 'current-password',
39
+ }: Props = $props()
40
+
41
+ const pw = createPasswordInput({
42
+ value: () => value,
43
+ onChange: (v) => onChange?.(v),
44
+ placeholder: () => placeholder,
45
+ disabled: () => disabled,
46
+ readonly: () => readonly,
47
+ ariaLabel: () => ariaLabel,
48
+ autocomplete: () => autocomplete,
49
+ })
50
+ </script>
51
+
52
+ <div class="sv-pw sv-pw--{size}" class:is-disabled={disabled}>
53
+ <div class="sv-pw__field">
54
+ <input class="sv-pw__input" {...pw.inputProps()} />
55
+ {#if revealable}
56
+ <button class="sv-pw__eye" {...pw.toggleProps()}>
57
+ {#if pw.revealed}
58
+ <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" /><path d="M1 1l22 22" /></svg>
59
+ {:else}
60
+ <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" /></svg>
61
+ {/if}
62
+ </button>
63
+ {/if}
64
+ </div>
65
+ {#if showStrength}
66
+ <div class="sv-pw__meter" aria-hidden="true">
67
+ {#each Array(4) as _, i (i)}
68
+ <span class="sv-pw__bar is-lvl{pw.strength}" class:on={i < pw.strength}></span>
69
+ {/each}
70
+ </div>
71
+ <span class="sv-pw__strength is-lvl{pw.strength}">{pw.strengthLabel}</span>
72
+ {/if}
73
+ {#if name}<input type="hidden" {name} value={value} />{/if}
74
+ </div>
75
+
76
+ <style>
77
+ .sv-pw { --_accent: var(--sg-accent, #2563eb); display: inline-flex; flex-direction: column; gap: 5px; width: 220px; }
78
+ .sv-pw.is-disabled { opacity: 0.6; }
79
+ .sv-pw__field {
80
+ display: flex; align-items: center;
81
+ background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
82
+ border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px);
83
+ }
84
+ .sv-pw__field:focus-within { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); }
85
+ .sv-pw__input { flex: 1; min-width: 0; border: 0; background: none; outline: none; color: inherit; font: inherit; padding: 0 10px; }
86
+ .sv-pw--sm .sv-pw__field { height: 28px; font-size: 12px; }
87
+ .sv-pw--md .sv-pw__field { height: 34px; font-size: 13px; }
88
+ .sv-pw--lg .sv-pw__field { height: 40px; font-size: 15px; }
89
+ .sv-pw__eye { display: grid; place-items: center; width: 32px; align-self: stretch; background: none; border: 0; color: var(--sg-muted, #64748b); cursor: pointer; }
90
+ .sv-pw__eye:hover { color: var(--_accent); }
91
+ .sv-pw__meter { display: flex; gap: 4px; }
92
+ .sv-pw__bar { flex: 1; height: 4px; border-radius: 2px; background: var(--sg-border, #e2e8f0); transition: background 0.15s; }
93
+ .sv-pw__bar.on.is-lvl1 { background: #dc2626; }
94
+ .sv-pw__bar.on.is-lvl2 { background: #f59e0b; }
95
+ .sv-pw__bar.on.is-lvl3 { background: #eab308; }
96
+ .sv-pw__bar.on.is-lvl4 { background: #16a34a; }
97
+ .sv-pw__strength { font-size: 11px; font-weight: 600; color: var(--sg-muted, #64748b); }
98
+ .sv-pw__strength.is-lvl1 { color: #dc2626; }
99
+ .sv-pw__strength.is-lvl4 { color: #16a34a; }
100
+ </style>
@@ -0,0 +1,18 @@
1
+ type Props = {
2
+ value?: string;
3
+ onChange?: (value: string) => void;
4
+ placeholder?: string;
5
+ disabled?: boolean;
6
+ readonly?: boolean;
7
+ /** Show the show/hide eye toggle. */
8
+ revealable?: boolean;
9
+ /** Show a 4-level strength meter. */
10
+ showStrength?: boolean;
11
+ name?: string;
12
+ size?: 'sm' | 'md' | 'lg';
13
+ ariaLabel?: string;
14
+ autocomplete?: string;
15
+ };
16
+ declare const SvPasswordInput: import("svelte").Component<Props, {}, "">;
17
+ type SvPasswordInput = ReturnType<typeof SvPasswordInput>;
18
+ export default SvPasswordInput;
@@ -0,0 +1,87 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvPhoneInput - a country dial-code selector + national number field. Parity:
4
+ * Smart `smart-phone-input` (simplified). Emits an E.164-ish string
5
+ * (`+<dial><digits>`). The country list is `countries.ts` (extend for full set).
6
+ *
7
+ * The styled renderer over the headless `createPhoneInput` core; country/number
8
+ * state + parsing live in the core, spread here via prop-getters.
9
+ */
10
+ import { COUNTRIES, flagEmoji } from './countries'
11
+ import { createPhoneInput } from './createPhoneInput.svelte'
12
+
13
+ type Props = {
14
+ value?: string
15
+ onChange?: (value: string, parts: { country: string; dial: string; national: string }) => void
16
+ /** Default country ISO code. */
17
+ country?: string
18
+ disabled?: boolean
19
+ readonly?: boolean
20
+ placeholder?: string
21
+ name?: string
22
+ size?: 'sm' | 'md' | 'lg'
23
+ ariaLabel?: string
24
+ }
25
+
26
+ let {
27
+ value = '',
28
+ onChange,
29
+ country = 'US',
30
+ disabled = false,
31
+ readonly = false,
32
+ placeholder = 'Phone number',
33
+ name,
34
+ size = 'md',
35
+ ariaLabel,
36
+ }: Props = $props()
37
+
38
+ const ph = createPhoneInput({
39
+ value: () => value,
40
+ onChange: (v, parts) => onChange?.(v, parts),
41
+ country: () => country,
42
+ disabled: () => disabled,
43
+ readonly: () => readonly,
44
+ placeholder: () => placeholder,
45
+ ariaLabel: () => ariaLabel,
46
+ })
47
+ </script>
48
+
49
+ <div class="sv-phone sv-phone--{size}" class:is-disabled={disabled}>
50
+ <div class="sv-phone__country">
51
+ <span class="sv-phone__flag" aria-hidden="true">{ph.flag}</span>
52
+ <span class="sv-phone__dial">{ph.dial}</span>
53
+ <select class="sv-phone__select" {...ph.selectProps()}>
54
+ {#each COUNTRIES as c (c.code)}
55
+ <option value={c.code}>{flagEmoji(c.code)} {c.name} ({c.dial})</option>
56
+ {/each}
57
+ </select>
58
+ <svg class="sv-phone__chev" viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
59
+ </div>
60
+ <input class="sv-phone__number" {...ph.inputProps()} />
61
+ {#if name}<input type="hidden" {name} value={ph.value} />{/if}
62
+ </div>
63
+
64
+ <style>
65
+ .sv-phone {
66
+ --_accent: var(--sg-accent, #2563eb);
67
+ display: inline-flex; align-items: stretch; width: 250px;
68
+ background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
69
+ border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px);
70
+ overflow: hidden;
71
+ }
72
+ .sv-phone:focus-within { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); }
73
+ .sv-phone.is-disabled { opacity: 0.6; }
74
+ .sv-phone__country {
75
+ position: relative; display: inline-flex; align-items: center; gap: 4px;
76
+ padding: 0 6px 0 10px; border-right: 1px solid var(--sg-border, #e2e8f0);
77
+ background: var(--sg-header-bg, #f8fafc); cursor: pointer;
78
+ }
79
+ .sv-phone__flag { font-size: 15px; }
80
+ .sv-phone__dial { font-size: 13px; font-weight: 600; }
81
+ .sv-phone__chev { color: var(--sg-muted, #64748b); }
82
+ .sv-phone__select { position: absolute; inset: 0; opacity: 0; cursor: pointer; font-size: 13px; }
83
+ .sv-phone__number { flex: 1; min-width: 0; border: 0; background: none; outline: none; color: inherit; font: inherit; padding: 0 10px; }
84
+ .sv-phone--sm { height: 28px; font-size: 12px; }
85
+ .sv-phone--md { height: 34px; font-size: 13px; }
86
+ .sv-phone--lg { height: 40px; font-size: 15px; }
87
+ </style>
@@ -0,0 +1,19 @@
1
+ type Props = {
2
+ value?: string;
3
+ onChange?: (value: string, parts: {
4
+ country: string;
5
+ dial: string;
6
+ national: string;
7
+ }) => void;
8
+ /** Default country ISO code. */
9
+ country?: string;
10
+ disabled?: boolean;
11
+ readonly?: boolean;
12
+ placeholder?: string;
13
+ name?: string;
14
+ size?: 'sm' | 'md' | 'lg';
15
+ ariaLabel?: string;
16
+ };
17
+ declare const SvPhoneInput: import("svelte").Component<Props, {}, "">;
18
+ type SvPhoneInput = ReturnType<typeof SvPhoneInput>;
19
+ export default SvPhoneInput;
@@ -0,0 +1,85 @@
1
+ <script lang="ts" module>
2
+ export type { RadioOption } from './createRadioGroup.svelte'
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ /**
7
+ * SvRadioGroup - an accessible radio group (WAI-ARIA radiogroup pattern) with
8
+ * roving tabindex + arrow-key navigation. Parity: Smart `smart-radio-button`
9
+ * (as a managed group). Controlled via `value` + `onChange`.
10
+ */
11
+ import { createRadioGroup, type RadioOption } from './createRadioGroup.svelte'
12
+
13
+ type Props = {
14
+ options: ReadonlyArray<RadioOption>
15
+ value?: string | number | null
16
+ onChange?: (value: string | number) => void
17
+ name?: string
18
+ disabled?: boolean
19
+ orientation?: 'vertical' | 'horizontal'
20
+ size?: 'sm' | 'md' | 'lg'
21
+ ariaLabel?: string
22
+ }
23
+
24
+ let {
25
+ options,
26
+ value = null,
27
+ onChange,
28
+ name,
29
+ disabled = false,
30
+ orientation = 'vertical',
31
+ size = 'md',
32
+ ariaLabel,
33
+ }: Props = $props()
34
+
35
+ // The styled radio group is just a renderer over the headless core.
36
+ const rg = createRadioGroup({
37
+ options: () => options,
38
+ value: () => value,
39
+ onChange: (v) => onChange?.(v),
40
+ disabled: () => disabled,
41
+ ariaLabel: () => ariaLabel,
42
+ })
43
+ </script>
44
+
45
+ <div
46
+ class="sv-radiogroup sv-radiogroup--{orientation} sv-radiogroup--{size}"
47
+ {...rg.groupProps()}
48
+ >
49
+ {#each options as opt (opt.value)}
50
+ <button
51
+ class="sv-radio"
52
+ class:is-checked={opt.value === value}
53
+ {...rg.radioProps(opt)}
54
+ >
55
+ <span class="sv-radio__dot"></span>
56
+ <span class="sv-radio__label">{opt.label}</span>
57
+ </button>
58
+ {/each}
59
+ {#if name}<input type="hidden" {name} value={value ?? ''} />{/if}
60
+ </div>
61
+
62
+ <style>
63
+ .sv-radiogroup { --_accent: var(--sg-accent, #2563eb); display: flex; gap: 10px; }
64
+ .sv-radiogroup--vertical { flex-direction: column; }
65
+ .sv-radiogroup--horizontal { flex-direction: row; flex-wrap: wrap; }
66
+ .sv-radio {
67
+ display: inline-flex; align-items: center; gap: 8px; background: none; border: 0; padding: 2px;
68
+ font: inherit; color: var(--sg-fg, #0f172a); cursor: pointer; user-select: none;
69
+ }
70
+ .sv-radiogroup--sm .sv-radio { font-size: 12px; }
71
+ .sv-radiogroup--md .sv-radio { font-size: 13px; }
72
+ .sv-radiogroup--lg .sv-radio { font-size: 15px; }
73
+ .sv-radio[disabled] { opacity: 0.5; cursor: not-allowed; }
74
+ .sv-radio__dot {
75
+ width: 17px; height: 17px; flex: none; border-radius: 50%;
76
+ border: 1.5px solid var(--sg-border, #cbd5e1); background: var(--sg-input-bg, #fff);
77
+ display: grid; place-items: center; transition: border-color 0.12s;
78
+ }
79
+ .sv-radio.is-checked .sv-radio__dot { border-color: var(--_accent); }
80
+ .sv-radio.is-checked .sv-radio__dot::after {
81
+ content: ''; width: 9px; height: 9px; border-radius: 50%; background: var(--_accent);
82
+ }
83
+ .sv-radio:focus-visible { outline: none; }
84
+ .sv-radio:focus-visible .sv-radio__dot { outline: 2px solid var(--sg-focus-ring, var(--_accent)); outline-offset: 2px; }
85
+ </style>
@@ -0,0 +1,20 @@
1
+ export type { RadioOption } from './createRadioGroup.svelte';
2
+ /**
3
+ * SvRadioGroup - an accessible radio group (WAI-ARIA radiogroup pattern) with
4
+ * roving tabindex + arrow-key navigation. Parity: Smart `smart-radio-button`
5
+ * (as a managed group). Controlled via `value` + `onChange`.
6
+ */
7
+ import { type RadioOption } from './createRadioGroup.svelte';
8
+ type Props = {
9
+ options: ReadonlyArray<RadioOption>;
10
+ value?: string | number | null;
11
+ onChange?: (value: string | number) => void;
12
+ name?: string;
13
+ disabled?: boolean;
14
+ orientation?: 'vertical' | 'horizontal';
15
+ size?: 'sm' | 'md' | 'lg';
16
+ ariaLabel?: string;
17
+ };
18
+ declare const SvRadioGroup: import("svelte").Component<Props, {}, "">;
19
+ type SvRadioGroup = ReturnType<typeof SvRadioGroup>;
20
+ export default SvRadioGroup;
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvRating - a star rating control (WAI-ARIA slider). Parity: Smart
4
+ * `smart-rating`. Hover preview, keyboard, optional half steps, readOnly.
5
+ * Uses the grid's `--sg-rating-*` tokens so it matches the in-grid editor.
6
+ */
7
+ import { createRating } from './createRating.svelte'
8
+
9
+ type Props = {
10
+ value?: number
11
+ onChange?: (value: number) => void
12
+ max?: number
13
+ /** Allow half-star precision. */
14
+ allowHalf?: boolean
15
+ /** Read-only: shown but not editable (the kit-standard name). */
16
+ readonly?: boolean
17
+ /** @deprecated use `readonly` - kept for back-compat. */
18
+ readOnly?: boolean
19
+ disabled?: boolean
20
+ size?: 'sm' | 'md' | 'lg'
21
+ name?: string
22
+ ariaLabel?: string
23
+ }
24
+
25
+ let {
26
+ value = 0,
27
+ onChange,
28
+ max = 5,
29
+ allowHalf = false,
30
+ readonly = false,
31
+ readOnly = false,
32
+ disabled = false,
33
+ size = 'md',
34
+ name,
35
+ ariaLabel,
36
+ }: Props = $props()
37
+
38
+ const ro = $derived(readonly || readOnly)
39
+
40
+ // The styled rating is just a renderer over the headless core.
41
+ const r = createRating({
42
+ value: () => value,
43
+ onChange: (v) => onChange?.(v),
44
+ max: () => max,
45
+ allowHalf: () => allowHalf,
46
+ readonly: () => ro,
47
+ disabled: () => disabled,
48
+ ariaLabel: () => ariaLabel,
49
+ })
50
+ </script>
51
+
52
+ <div
53
+ class="sv-rating sv-rating--{size}"
54
+ class:is-readonly={ro}
55
+ class:is-disabled={disabled}
56
+ {...r.rootProps()}
57
+ >
58
+ {#each Array(max) as _, i (i)}
59
+ <button
60
+ class="sv-rating__star is-{r.fillOf(i)}"
61
+ {...r.starProps(i)}
62
+ >
63
+ <svg viewBox="0 0 24 24" aria-hidden="true">
64
+ <defs>
65
+ <linearGradient id="half-{i}"><stop offset="50%" stop-color="var(--_on)" /><stop offset="50%" stop-color="var(--_off)" /></linearGradient>
66
+ </defs>
67
+ <path d="M12 2.5l2.9 6.1 6.6.9-4.8 4.6 1.2 6.6L12 18.6 6.1 21.7l1.2-6.6L2.5 9.5l6.6-.9z"
68
+ fill={r.fillOf(i) === 'full' ? 'var(--_on)' : r.fillOf(i) === 'half' ? `url(#half-${i})` : 'var(--_off)'} />
69
+ </svg>
70
+ </button>
71
+ {/each}
72
+ {#if name}<input type="hidden" {name} value={value} />{/if}
73
+ </div>
74
+
75
+ <style>
76
+ .sv-rating {
77
+ --_on: var(--sg-rating-on, #f59e0b);
78
+ --_off: var(--sg-rating-empty, #d1d5db);
79
+ --_sz: 22px;
80
+ display: inline-flex; gap: 2px; align-items: center;
81
+ }
82
+ .sv-rating--sm { --_sz: 16px; }
83
+ .sv-rating--lg { --_sz: 30px; }
84
+ .sv-rating.is-disabled { opacity: 0.5; }
85
+ .sv-rating__star {
86
+ width: var(--_sz); height: var(--_sz); padding: 0; border: 0; background: none; cursor: pointer; line-height: 0;
87
+ }
88
+ .sv-rating.is-readonly .sv-rating__star, .sv-rating.is-disabled .sv-rating__star { cursor: default; }
89
+ .sv-rating__star svg { width: 100%; height: 100%; }
90
+ .sv-rating:focus-visible { outline: 2px solid var(--sg-focus-ring, var(--sg-accent, #2563eb)); outline-offset: 2px; border-radius: 4px; }
91
+ </style>
@@ -0,0 +1,18 @@
1
+ type Props = {
2
+ value?: number;
3
+ onChange?: (value: number) => void;
4
+ max?: number;
5
+ /** Allow half-star precision. */
6
+ allowHalf?: boolean;
7
+ /** Read-only: shown but not editable (the kit-standard name). */
8
+ readonly?: boolean;
9
+ /** @deprecated use `readonly` - kept for back-compat. */
10
+ readOnly?: boolean;
11
+ disabled?: boolean;
12
+ size?: 'sm' | 'md' | 'lg';
13
+ name?: string;
14
+ ariaLabel?: string;
15
+ };
16
+ declare const SvRating: import("svelte").Component<Props, {}, "">;
17
+ type SvRating = ReturnType<typeof SvRating>;
18
+ export default SvRating;
@@ -0,0 +1,89 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvRepeatButton - fires `onclick` repeatedly while held down (after an
4
+ * initial delay, then at a steady interval). Parity: Smart `smart-repeat-button`.
5
+ * Used for spinners / steppers.
6
+ */
7
+ import type { Snippet } from 'svelte'
8
+
9
+ type Props = {
10
+ onclick?: () => void
11
+ /** Delay before repeats begin (ms). */
12
+ delay?: number
13
+ /** Interval between repeats (ms). */
14
+ interval?: number
15
+ disabled?: boolean
16
+ size?: 'sm' | 'md' | 'lg'
17
+ variant?: 'primary' | 'secondary' | 'outline' | 'ghost'
18
+ ariaLabel?: string
19
+ children?: Snippet
20
+ }
21
+
22
+ let {
23
+ onclick,
24
+ delay = 300,
25
+ interval = 60,
26
+ disabled = false,
27
+ size = 'md',
28
+ variant = 'secondary',
29
+ ariaLabel,
30
+ children,
31
+ }: Props = $props()
32
+
33
+ let delayTimer: ReturnType<typeof setTimeout> | null = null
34
+ let repeatTimer: ReturnType<typeof setInterval> | null = null
35
+
36
+ function stop() {
37
+ if (delayTimer) { clearTimeout(delayTimer); delayTimer = null }
38
+ if (repeatTimer) { clearInterval(repeatTimer); repeatTimer = null }
39
+ }
40
+
41
+ function start(e: PointerEvent) {
42
+ if (disabled || e.button !== 0) return
43
+ onclick?.() // fire once immediately
44
+ delayTimer = setTimeout(() => {
45
+ repeatTimer = setInterval(() => onclick?.(), Math.max(16, interval))
46
+ }, Math.max(0, delay))
47
+ }
48
+
49
+ function onKeydown(e: KeyboardEvent) {
50
+ if (disabled) return
51
+ if ((e.key === 'Enter' || e.key === ' ') && !e.repeat) { e.preventDefault(); onclick?.() }
52
+ }
53
+ </script>
54
+
55
+ <svelte:window onpointerup={stop} onpointercancel={stop} />
56
+
57
+ <button
58
+ type="button"
59
+ class="sv-btn sv-btn--{variant} sv-btn--{size} sv-repeat"
60
+ {disabled}
61
+ aria-label={ariaLabel}
62
+ onpointerdown={start}
63
+ onpointerleave={stop}
64
+ onkeydown={onKeydown}
65
+ >
66
+ {#if children}{@render children()}{/if}
67
+ </button>
68
+
69
+ <style>
70
+ /* Reuses the SvButton visual language (kept local so it works standalone). */
71
+ .sv-btn {
72
+ --_accent: var(--sg-accent, #2563eb);
73
+ --_border: var(--sg-border, #cbd5e1);
74
+ --_radius: var(--sg-radius, 8px);
75
+ display: inline-flex; align-items: center; justify-content: center; gap: 6px;
76
+ font: inherit; font-weight: 600; line-height: 1; border: 1px solid transparent;
77
+ border-radius: var(--_radius); cursor: pointer; user-select: none; touch-action: none;
78
+ }
79
+ .sv-btn--sm { padding: 5px 9px; font-size: 12px; }
80
+ .sv-btn--md { padding: 8px 12px; font-size: 13px; }
81
+ .sv-btn--lg { padding: 11px 16px; font-size: 15px; }
82
+ .sv-btn[disabled] { opacity: 0.55; cursor: not-allowed; }
83
+ .sv-btn--primary { background: var(--_accent); color: var(--sg-on-accent, #fff); }
84
+ .sv-btn--secondary { background: var(--sg-header-bg, #f1f5f9); color: var(--sg-fg, #0f172a); border-color: var(--_border); }
85
+ .sv-btn--outline { background: transparent; color: var(--_accent); border-color: var(--_accent); }
86
+ .sv-btn--ghost { background: transparent; color: var(--sg-fg, #0f172a); }
87
+ .sv-btn:focus-visible { outline: 2px solid var(--sg-focus-ring, var(--_accent)); outline-offset: 2px; }
88
+ .sv-btn:active { transform: translateY(0.5px); }
89
+ </style>
@@ -0,0 +1,21 @@
1
+ /**
2
+ * SvRepeatButton - fires `onclick` repeatedly while held down (after an
3
+ * initial delay, then at a steady interval). Parity: Smart `smart-repeat-button`.
4
+ * Used for spinners / steppers.
5
+ */
6
+ import type { Snippet } from 'svelte';
7
+ type Props = {
8
+ onclick?: () => void;
9
+ /** Delay before repeats begin (ms). */
10
+ delay?: number;
11
+ /** Interval between repeats (ms). */
12
+ interval?: number;
13
+ disabled?: boolean;
14
+ size?: 'sm' | 'md' | 'lg';
15
+ variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
16
+ ariaLabel?: string;
17
+ children?: Snippet;
18
+ };
19
+ declare const SvRepeatButton: import("svelte").Component<Props, {}, "">;
20
+ type SvRepeatButton = ReturnType<typeof SvRepeatButton>;
21
+ export default SvRepeatButton;