@svgrid/grid 1.2.33 → 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 (490) hide show
  1. package/README.md +6 -5
  2. package/dist/FlexRender.svelte +96 -96
  3. package/dist/GridFooter.svelte +178 -178
  4. package/dist/SvAccordion.svelte +109 -0
  5. package/dist/SvAccordion.svelte.d.ts +28 -0
  6. package/dist/SvAlert.svelte +92 -0
  7. package/dist/SvAlert.svelte.d.ts +27 -0
  8. package/dist/SvAutoComplete.svelte +47 -18
  9. package/dist/SvAutoComplete.svelte.d.ts +2 -5
  10. package/dist/SvAvatar.svelte +75 -0
  11. package/dist/SvAvatar.svelte.d.ts +14 -0
  12. package/dist/SvAvatarGroup.svelte +48 -0
  13. package/dist/SvAvatarGroup.svelte.d.ts +16 -0
  14. package/dist/SvBadge.svelte +54 -0
  15. package/dist/SvBadge.svelte.d.ts +23 -0
  16. package/dist/SvBreadcrumb.svelte +88 -0
  17. package/dist/SvBreadcrumb.svelte.d.ts +23 -0
  18. package/dist/SvButtonGroup.svelte +121 -0
  19. package/dist/SvButtonGroup.svelte.d.ts +16 -0
  20. package/dist/SvCalendar.svelte +72 -9
  21. package/dist/SvCalendar.svelte.d.ts +34 -1
  22. package/dist/SvCard.svelte +71 -0
  23. package/dist/SvCard.svelte.d.ts +28 -0
  24. package/dist/SvCarousel.svelte +134 -0
  25. package/dist/SvCarousel.svelte.d.ts +28 -0
  26. package/dist/SvCheckBox.svelte +36 -21
  27. package/dist/SvCheckBox.svelte.d.ts +2 -5
  28. package/dist/SvChip.svelte +88 -0
  29. package/dist/SvChip.svelte.d.ts +31 -0
  30. package/dist/SvCircularProgress.svelte +109 -0
  31. package/dist/SvCircularProgress.svelte.d.ts +31 -0
  32. package/dist/SvColorInput.svelte +54 -27
  33. package/dist/SvColorInput.svelte.d.ts +10 -6
  34. package/dist/SvComboBox.svelte +119 -33
  35. package/dist/SvComboBox.svelte.d.ts +18 -6
  36. package/dist/SvCommand.svelte +197 -0
  37. package/dist/SvCommand.svelte.d.ts +26 -0
  38. package/dist/SvContextMenu.svelte +96 -0
  39. package/dist/SvContextMenu.svelte.d.ts +25 -0
  40. package/dist/SvCountryInput.svelte +56 -21
  41. package/dist/SvCountryInput.svelte.d.ts +9 -5
  42. package/dist/SvDateRangeInput.svelte +256 -0
  43. package/dist/SvDateRangeInput.svelte.d.ts +37 -0
  44. package/dist/SvDateTimePicker.svelte +57 -20
  45. package/dist/SvDateTimePicker.svelte.d.ts +12 -4
  46. package/dist/SvDivider.svelte +61 -0
  47. package/dist/SvDivider.svelte.d.ts +22 -0
  48. package/dist/SvDrawer.svelte +226 -0
  49. package/dist/SvDrawer.svelte.d.ts +43 -0
  50. package/dist/SvDropDownList.svelte +114 -35
  51. package/dist/SvDropDownList.svelte.d.ts +7 -6
  52. package/dist/SvDurationInput.svelte +108 -0
  53. package/dist/SvDurationInput.svelte.d.ts +15 -0
  54. package/dist/SvEmptyState.svelte +59 -0
  55. package/dist/SvEmptyState.svelte.d.ts +25 -0
  56. package/dist/SvField.svelte +85 -0
  57. package/dist/SvField.svelte.d.ts +30 -0
  58. package/dist/SvFileUpload.svelte +169 -0
  59. package/dist/SvFileUpload.svelte.d.ts +24 -0
  60. package/dist/SvForm.svelte +7 -1
  61. package/dist/SvForm.svelte.d.ts +3 -0
  62. package/dist/SvGauge.svelte +7 -1
  63. package/dist/SvGauge.svelte.d.ts +11 -0
  64. package/dist/SvGrid.controller.svelte.d.ts +6 -0
  65. package/dist/SvGrid.controller.svelte.js +64 -9
  66. package/dist/SvGrid.css +2376 -2343
  67. package/dist/SvGrid.svelte +2764 -2651
  68. package/dist/SvGrid.types.d.ts +366 -0
  69. package/dist/SvGridBoard.svelte +2281 -0
  70. package/dist/SvGridBoard.svelte.d.ts +31 -0
  71. package/dist/SvGridDropdown.svelte +666 -665
  72. package/dist/SvGridSelect.svelte +255 -0
  73. package/dist/SvGridSelect.svelte.d.ts +32 -0
  74. package/dist/SvGroupCell.svelte +109 -0
  75. package/dist/SvGroupCell.svelte.d.ts +41 -0
  76. package/dist/SvListBox.svelte +123 -36
  77. package/dist/SvListBox.svelte.d.ts +12 -8
  78. package/dist/SvMaskedInput.svelte +53 -13
  79. package/dist/SvMaskedInput.svelte.d.ts +16 -6
  80. package/dist/SvMenu.svelte +101 -0
  81. package/dist/SvMenu.svelte.d.ts +26 -0
  82. package/dist/SvMenuList.svelte +143 -0
  83. package/dist/SvMenuList.svelte.d.ts +24 -0
  84. package/dist/SvModal.svelte +220 -0
  85. package/dist/SvModal.svelte.d.ts +31 -0
  86. package/dist/SvMultiSelect.svelte +277 -0
  87. package/dist/SvMultiSelect.svelte.d.ts +31 -0
  88. package/dist/SvNavPane.svelte +314 -0
  89. package/dist/SvNavPane.svelte.d.ts +59 -0
  90. package/dist/SvNumberInput.svelte +23 -9
  91. package/dist/SvNumberInput.svelte.d.ts +2 -0
  92. package/dist/SvOtpInput.svelte +157 -0
  93. package/dist/SvOtpInput.svelte.d.ts +16 -0
  94. package/dist/SvPagination.svelte +100 -0
  95. package/dist/SvPagination.svelte.d.ts +16 -0
  96. package/dist/SvPasswordInput.svelte +42 -12
  97. package/dist/SvPasswordInput.svelte.d.ts +13 -6
  98. package/dist/SvPhoneInput.svelte +43 -11
  99. package/dist/SvPhoneInput.svelte.d.ts +10 -11
  100. package/dist/SvPopover.svelte +127 -0
  101. package/dist/SvPopover.svelte.d.ts +35 -0
  102. package/dist/SvProgress.svelte +116 -0
  103. package/dist/SvProgress.svelte.d.ts +32 -0
  104. package/dist/SvRadioGroup.svelte +40 -22
  105. package/dist/SvRadioGroup.svelte.d.ts +2 -10
  106. package/dist/SvRating.svelte +51 -30
  107. package/dist/SvRating.svelte.d.ts +10 -7
  108. package/dist/SvRichText.svelte +192 -0
  109. package/dist/SvRichText.svelte.d.ts +16 -0
  110. package/dist/SvRowGroupPanel.svelte +147 -0
  111. package/dist/SvRowGroupPanel.svelte.d.ts +17 -0
  112. package/dist/SvScrollArea.svelte +50 -0
  113. package/dist/SvScrollArea.svelte.d.ts +22 -0
  114. package/dist/SvSkeleton.svelte +76 -0
  115. package/dist/SvSkeleton.svelte.d.ts +25 -0
  116. package/dist/SvSlider.svelte +41 -9
  117. package/dist/SvSlider.svelte.d.ts +4 -4
  118. package/dist/SvSparkline.svelte +77 -0
  119. package/dist/SvSparkline.svelte.d.ts +28 -0
  120. package/dist/SvSplitter.svelte +138 -0
  121. package/dist/SvSplitter.svelte.d.ts +32 -0
  122. package/dist/SvStat.svelte +86 -0
  123. package/dist/SvStat.svelte.d.ts +30 -0
  124. package/dist/SvStepper.svelte +91 -0
  125. package/dist/SvStepper.svelte.d.ts +24 -0
  126. package/dist/SvSwitchButton.svelte +39 -24
  127. package/dist/SvSwitchButton.svelte.d.ts +2 -5
  128. package/dist/SvTabs.svelte +147 -28
  129. package/dist/SvTabs.svelte.d.ts +16 -4
  130. package/dist/SvTagsInput.svelte +59 -22
  131. package/dist/SvTagsInput.svelte.d.ts +9 -4
  132. package/dist/SvTextArea.svelte +113 -0
  133. package/dist/SvTextArea.svelte.d.ts +18 -0
  134. package/dist/SvTextInput.svelte +115 -0
  135. package/dist/SvTextInput.svelte.d.ts +20 -0
  136. package/dist/SvTimePicker.svelte +19 -5
  137. package/dist/SvTimePicker.svelte.d.ts +12 -0
  138. package/dist/SvTimeline.svelte +75 -0
  139. package/dist/SvTimeline.svelte.d.ts +24 -0
  140. package/dist/SvToaster.svelte +124 -0
  141. package/dist/SvToaster.svelte.d.ts +10 -0
  142. package/dist/SvToggleButton.svelte +37 -12
  143. package/dist/SvToggleButton.svelte.d.ts +2 -4
  144. package/dist/SvTooltip.svelte +113 -0
  145. package/dist/SvTooltip.svelte.d.ts +22 -0
  146. package/dist/SvTour.svelte +151 -0
  147. package/dist/SvTour.svelte.d.ts +25 -0
  148. package/dist/SvTree.svelte +286 -44
  149. package/dist/SvTree.svelte.d.ts +26 -9
  150. package/dist/SvTreeSelect.svelte +222 -0
  151. package/dist/SvTreeSelect.svelte.d.ts +24 -0
  152. package/dist/a11y/dismissable.d.ts +32 -0
  153. package/dist/a11y/dismissable.js +54 -0
  154. package/dist/a11y/focus-trap.d.ts +39 -0
  155. package/dist/a11y/focus-trap.js +142 -0
  156. package/dist/a11y/live-region.d.ts +8 -0
  157. package/dist/a11y/live-region.js +60 -0
  158. package/dist/a11y/scroll-lock.d.ts +4 -0
  159. package/dist/a11y/scroll-lock.js +41 -0
  160. package/dist/a11y.d.ts +3 -1
  161. package/dist/a11y.js +1 -1
  162. package/dist/avatar.d.ts +10 -0
  163. package/dist/avatar.js +22 -0
  164. package/dist/builtin-editors.d.ts +5 -0
  165. package/dist/builtin-editors.js +55 -0
  166. package/dist/cdn/svgrid.js +16022 -8235
  167. package/dist/cdn/svgrid.svelte-external.js +14543 -6765
  168. package/dist/columns.js +3 -2
  169. package/dist/core.d.ts +7 -1
  170. package/dist/countries.d.ts +12 -0
  171. package/dist/countries.js +24 -0
  172. package/dist/createAccordion.svelte.d.ts +71 -0
  173. package/dist/createAccordion.svelte.js +99 -0
  174. package/dist/createAutocomplete.svelte.d.ts +13 -4
  175. package/dist/createAutocomplete.svelte.js +11 -1
  176. package/dist/createButtonGroup.svelte.d.ts +62 -0
  177. package/dist/createButtonGroup.svelte.js +154 -0
  178. package/dist/createCalendar.svelte.d.ts +5 -0
  179. package/dist/createCalendar.svelte.js +2 -0
  180. package/dist/createCheckbox.svelte.d.ts +9 -17
  181. package/dist/createCheckbox.svelte.js +28 -1
  182. package/dist/createColorInput.svelte.d.ts +12 -22
  183. package/dist/createColorInput.svelte.js +13 -0
  184. package/dist/createCombobox.svelte.d.ts +16 -5
  185. package/dist/createCombobox.svelte.js +13 -2
  186. package/dist/createCountryInput.svelte.d.ts +14 -3
  187. package/dist/createCountryInput.svelte.js +12 -2
  188. package/dist/createDateTimePicker.svelte.d.ts +17 -2
  189. package/dist/createDateTimePicker.svelte.js +12 -2
  190. package/dist/createDropdownList.svelte.d.ts +14 -5
  191. package/dist/createDropdownList.svelte.js +50 -1
  192. package/dist/createFileUpload.svelte.d.ts +68 -0
  193. package/dist/createFileUpload.svelte.js +122 -0
  194. package/dist/createListbox.svelte.d.ts +10 -1
  195. package/dist/createListbox.svelte.js +48 -1
  196. package/dist/createMaskedInput.svelte.d.ts +11 -2
  197. package/dist/createMaskedInput.svelte.js +11 -1
  198. package/dist/createNumberInput.svelte.d.ts +1 -0
  199. package/dist/createNumberInput.svelte.js +1 -0
  200. package/dist/createPasswordInput.svelte.d.ts +19 -21
  201. package/dist/createPasswordInput.svelte.js +16 -4
  202. package/dist/createPhoneInput.svelte.d.ts +26 -7
  203. package/dist/createPhoneInput.svelte.js +24 -3
  204. package/dist/createPopoverSelect.svelte.d.ts +86 -0
  205. package/dist/createPopoverSelect.svelte.js +196 -0
  206. package/dist/createRadioGroup.svelte.d.ts +9 -0
  207. package/dist/createRadioGroup.svelte.js +11 -1
  208. package/dist/createRating.svelte.d.ts +11 -0
  209. package/dist/createRating.svelte.js +12 -1
  210. package/dist/createSlider.svelte.d.ts +2 -0
  211. package/dist/createSlider.svelte.js +16 -5
  212. package/dist/createSplitter.svelte.d.ts +67 -0
  213. package/dist/createSplitter.svelte.js +99 -0
  214. package/dist/createSwitch.svelte.d.ts +9 -16
  215. package/dist/createSwitch.svelte.js +28 -1
  216. package/dist/createTabs.svelte.d.ts +7 -0
  217. package/dist/createTabs.svelte.js +17 -2
  218. package/dist/createTagsInput.svelte.d.ts +13 -1
  219. package/dist/createTagsInput.svelte.js +12 -3
  220. package/dist/createToggle.svelte.d.ts +9 -0
  221. package/dist/createToggle.svelte.js +12 -1
  222. package/dist/createTree.svelte.d.ts +19 -0
  223. package/dist/createTree.svelte.js +108 -15
  224. package/dist/debounce.d.ts +11 -0
  225. package/dist/debounce.js +30 -0
  226. package/dist/duration.d.ts +15 -0
  227. package/dist/duration.js +51 -0
  228. package/dist/editor-contract.d.ts +62 -7
  229. package/dist/editor-contract.js +45 -5
  230. package/dist/editor-registry.d.ts +67 -0
  231. package/dist/editor-registry.js +38 -0
  232. package/dist/editors/cell-editors.d.ts +1 -1
  233. package/dist/editors/cell-editors.js +5 -0
  234. package/dist/fuzzy.d.ts +3 -0
  235. package/dist/fuzzy.js +41 -0
  236. package/dist/grid-select.d.ts +9 -0
  237. package/dist/grid-select.js +8 -0
  238. package/dist/index.d.ts +79 -6
  239. package/dist/index.js +78 -4
  240. package/dist/keyboard-handlers.js +19 -0
  241. package/dist/list-option.d.ts +36 -0
  242. package/dist/list-option.js +68 -0
  243. package/dist/otp.d.ts +16 -0
  244. package/dist/otp.js +26 -0
  245. package/dist/paginate.d.ts +20 -0
  246. package/dist/paginate.js +40 -0
  247. package/dist/popover.d.ts +15 -1
  248. package/dist/popover.js +29 -3
  249. package/dist/recurrence.d.ts +36 -0
  250. package/dist/recurrence.js +90 -0
  251. package/dist/server-data-source.d.ts +89 -0
  252. package/dist/server-data-source.js +4 -0
  253. package/dist/server-group-model.d.ts +98 -0
  254. package/dist/server-group-model.js +263 -0
  255. package/dist/toast-store.svelte.d.ts +41 -0
  256. package/dist/toast-store.svelte.js +113 -0
  257. package/dist/tree-select.d.ts +19 -0
  258. package/dist/tree-select.js +40 -0
  259. package/dist/ui-app.types.d.ts +80 -0
  260. package/dist/ui-app.types.js +7 -0
  261. package/dist/validators.d.ts +43 -0
  262. package/dist/validators.js +53 -0
  263. package/dist/virtual.d.ts +35 -0
  264. package/dist/virtual.js +34 -0
  265. package/package.json +85 -85
  266. package/src/FlexRender.svelte +96 -96
  267. package/src/GridFooter.svelte +178 -178
  268. package/src/SvAccordion.svelte +109 -0
  269. package/src/SvAccordion.test.ts +66 -0
  270. package/src/SvAlert.svelte +92 -0
  271. package/src/SvAutoComplete.svelte +47 -18
  272. package/src/SvAvatar.svelte +75 -0
  273. package/src/SvAvatarGroup.svelte +48 -0
  274. package/src/SvBadge.svelte +54 -0
  275. package/src/SvBreadcrumb.svelte +88 -0
  276. package/src/SvButtonGroup.svelte +121 -0
  277. package/src/SvButtonGroup.test.ts +72 -0
  278. package/src/SvCalendar.svelte +72 -9
  279. package/src/SvCard.svelte +71 -0
  280. package/src/SvCarousel.svelte +134 -0
  281. package/src/SvCheckBox.svelte +36 -21
  282. package/src/SvChip.svelte +88 -0
  283. package/src/SvCircularProgress.svelte +109 -0
  284. package/src/SvColorInput.svelte +54 -27
  285. package/src/SvComboBox.svelte +119 -33
  286. package/src/SvCommand.svelte +197 -0
  287. package/src/SvContextMenu.svelte +96 -0
  288. package/src/SvCountryInput.svelte +56 -21
  289. package/src/SvDateRangeInput.svelte +256 -0
  290. package/src/SvDateRangeInput.test.ts +80 -0
  291. package/src/SvDateTimePicker.svelte +57 -20
  292. package/src/SvDivider.svelte +61 -0
  293. package/src/SvDrawer.svelte +226 -0
  294. package/src/SvDrawer.test.ts +125 -0
  295. package/src/SvDropDownList.svelte +114 -35
  296. package/src/SvDurationInput.svelte +108 -0
  297. package/src/SvEmptyState.svelte +59 -0
  298. package/src/SvField.svelte +85 -0
  299. package/src/SvFileUpload.svelte +169 -0
  300. package/src/SvFileUpload.test.ts +59 -0
  301. package/src/SvForm.svelte +7 -1
  302. package/src/SvGauge.svelte +7 -1
  303. package/src/SvGrid.controller.svelte.ts +2553 -2494
  304. package/src/SvGrid.css +2376 -2343
  305. package/src/SvGrid.svelte +2764 -2651
  306. package/src/SvGrid.types.ts +944 -570
  307. package/src/SvGridBoard.svelte +2281 -0
  308. package/src/SvGridDropdown.svelte +666 -665
  309. package/src/SvGridSelect.svelte +255 -0
  310. package/src/SvGridSelect.test.ts +100 -0
  311. package/src/SvGroupCell.svelte +109 -0
  312. package/src/SvListBox.svelte +123 -36
  313. package/src/SvMaskedInput.svelte +53 -13
  314. package/src/SvMenu.svelte +101 -0
  315. package/src/SvMenu.test.ts +73 -0
  316. package/src/SvMenuList.svelte +143 -0
  317. package/src/SvModal.svelte +220 -0
  318. package/src/SvMultiSelect.svelte +277 -0
  319. package/src/SvMultiSelect.test.ts +167 -0
  320. package/src/SvNavPane.svelte +314 -0
  321. package/src/SvNavPane.test.ts +70 -0
  322. package/src/SvNumberInput.svelte +23 -9
  323. package/src/SvOtpInput.svelte +157 -0
  324. package/src/SvPagination.svelte +100 -0
  325. package/src/SvPasswordInput.svelte +42 -12
  326. package/src/SvPhoneInput.svelte +43 -11
  327. package/src/SvPopover.svelte +127 -0
  328. package/src/SvProgress.svelte +116 -0
  329. package/src/SvRadioGroup.svelte +40 -22
  330. package/src/SvRating.svelte +51 -30
  331. package/src/SvRichText.svelte +192 -0
  332. package/src/SvRowGroupPanel.svelte +147 -0
  333. package/src/SvScrollArea.svelte +50 -0
  334. package/src/SvSkeleton.svelte +76 -0
  335. package/src/SvSlider.svelte +41 -9
  336. package/src/SvSparkline.svelte +77 -0
  337. package/src/SvSplitter.svelte +138 -0
  338. package/src/SvSplitter.test.ts +55 -0
  339. package/src/SvStat.svelte +86 -0
  340. package/src/SvStepper.svelte +91 -0
  341. package/src/SvSwitchButton.svelte +39 -24
  342. package/src/SvTabs.svelte +147 -28
  343. package/src/SvTagsInput.svelte +59 -22
  344. package/src/SvTextArea.svelte +113 -0
  345. package/src/SvTextInput.svelte +115 -0
  346. package/src/SvTimePicker.svelte +19 -5
  347. package/src/SvTimeline.svelte +75 -0
  348. package/src/SvToaster.svelte +124 -0
  349. package/src/SvToaster.test.ts +63 -0
  350. package/src/SvToggleButton.svelte +37 -12
  351. package/src/SvTooltip.svelte +113 -0
  352. package/src/SvTour.svelte +151 -0
  353. package/src/SvTree.svelte +286 -44
  354. package/src/SvTreeSelect.svelte +222 -0
  355. package/src/SvTreeSelect.test.ts +87 -0
  356. package/src/a11y/dismissable.test.ts +95 -0
  357. package/src/a11y/dismissable.ts +94 -0
  358. package/src/a11y/focus-trap.test.ts +110 -0
  359. package/src/a11y/focus-trap.ts +134 -0
  360. package/src/a11y/live-region.test.ts +40 -0
  361. package/src/a11y/live-region.ts +65 -0
  362. package/src/a11y/scroll-lock.test.ts +38 -0
  363. package/src/a11y/scroll-lock.ts +41 -0
  364. package/src/a11y.contract.test.ts +49 -49
  365. package/src/a11y.test.ts +59 -59
  366. package/src/a11y.ts +61 -59
  367. package/src/avatar.test.ts +32 -0
  368. package/src/avatar.ts +21 -0
  369. package/src/board.test.ts +927 -0
  370. package/src/build-api.ts +798 -798
  371. package/src/builtin-editors.grid.test.ts +85 -0
  372. package/src/builtin-editors.test.ts +58 -0
  373. package/src/builtin-editors.ts +56 -0
  374. package/src/cell-formatting.ts +169 -169
  375. package/src/cell-render.ts +469 -469
  376. package/src/collaboration.test.ts +104 -104
  377. package/src/collaboration.ts +167 -167
  378. package/src/columns.ts +3 -2
  379. package/src/core.performance.test.ts +30 -30
  380. package/src/core.ts +1111 -1101
  381. package/src/countries.ts +25 -0
  382. package/src/createAccordion.svelte.ts +126 -0
  383. package/src/createAutocomplete.svelte.ts +18 -1
  384. package/src/createButtonGroup.svelte.ts +166 -0
  385. package/src/createCalendar.svelte.ts +6 -0
  386. package/src/createCheckbox.svelte.ts +23 -1
  387. package/src/createColorInput.svelte.ts +20 -0
  388. package/src/createCombobox.svelte.ts +22 -2
  389. package/src/createCountryInput.svelte.ts +21 -2
  390. package/src/createDateTimePicker.svelte.ts +23 -2
  391. package/src/createDropdownList.svelte.ts +31 -2
  392. package/src/createFileUpload.svelte.ts +144 -0
  393. package/src/createGrid.svelte.ts +42 -42
  394. package/src/createGrid.test.ts +10 -10
  395. package/src/createGridState.svelte.ts +17 -17
  396. package/src/createListbox.svelte.ts +35 -3
  397. package/src/createMaskedInput.svelte.ts +18 -1
  398. package/src/createNumberInput.svelte.ts +2 -0
  399. package/src/createPasswordInput.svelte.ts +31 -5
  400. package/src/createPhoneInput.svelte.ts +38 -4
  401. package/src/createPopoverSelect.svelte.ts +208 -0
  402. package/src/createRadioGroup.svelte.ts +23 -1
  403. package/src/createRating.svelte.ts +26 -1
  404. package/src/createSlider.svelte.ts +14 -3
  405. package/src/createSplitter.svelte.ts +119 -0
  406. package/src/createSwitch.svelte.ts +26 -3
  407. package/src/createTabs.svelte.ts +20 -3
  408. package/src/createTagsInput.svelte.ts +24 -3
  409. package/src/createToggle.svelte.ts +25 -2
  410. package/src/createTree.svelte.ts +104 -14
  411. package/src/debounce.test.ts +50 -0
  412. package/src/debounce.ts +41 -0
  413. package/src/duration.test.ts +41 -0
  414. package/src/duration.ts +51 -0
  415. package/src/editing.test.ts +859 -859
  416. package/src/editing.ts +675 -675
  417. package/src/editor-contract.ts +87 -8
  418. package/src/editor-registry.grid.test.ts +98 -0
  419. package/src/editor-registry.test.ts +86 -0
  420. package/src/editor-registry.ts +106 -0
  421. package/src/editors/cell-editors.ts +10 -1
  422. package/src/export-data-api.test.ts +126 -126
  423. package/src/export-format.test.ts +107 -107
  424. package/src/export-format.ts +598 -598
  425. package/src/flex-render.ts +3 -3
  426. package/src/fuzzy.test.ts +40 -0
  427. package/src/fuzzy.ts +39 -0
  428. package/src/grid-select.test.ts +28 -0
  429. package/src/grid-select.ts +20 -0
  430. package/src/index.ts +463 -318
  431. package/src/keyboard-handlers.ts +20 -0
  432. package/src/keyboard.test.ts +59 -59
  433. package/src/keyboard.ts +97 -97
  434. package/src/list-option.ts +74 -0
  435. package/src/list-power.test.ts +71 -0
  436. package/src/menus.ts +582 -582
  437. package/src/merge-objects.ts +48 -48
  438. package/src/otp.test.ts +28 -0
  439. package/src/otp.ts +28 -0
  440. package/src/overlays.test.ts +85 -0
  441. package/src/paginate.test.ts +41 -0
  442. package/src/paginate.ts +61 -0
  443. package/src/phone-valid.test.ts +26 -0
  444. package/src/popover.ts +31 -3
  445. package/src/progress.test.ts +55 -0
  446. package/src/recurrence.test.ts +91 -0
  447. package/src/recurrence.ts +111 -0
  448. package/src/render-component.ts +28 -28
  449. package/src/selection.test.ts +754 -754
  450. package/src/selection.ts +600 -600
  451. package/src/server-data-source.test.ts +289 -289
  452. package/src/server-data-source.ts +413 -311
  453. package/src/server-group-model.test.ts +294 -0
  454. package/src/server-group-model.ts +370 -0
  455. package/src/sparkline.test.ts +68 -68
  456. package/src/sparkline.ts +169 -169
  457. package/src/spreadsheet.test.ts +489 -489
  458. package/src/spreadsheet.ts +304 -304
  459. package/src/static-functions.ts +11 -11
  460. package/src/subscribe.ts +38 -38
  461. package/src/svgrid-wrapper.types.ts +439 -439
  462. package/src/svgrid.behavior.test.ts +706 -706
  463. package/src/svgrid.features.test.ts +157 -157
  464. package/src/svgrid.new-features.wrapper.test.ts +251 -251
  465. package/src/svgrid.responsive.test.ts +72 -0
  466. package/src/svgrid.wrapper.test.ts +40 -40
  467. package/src/toast-store.svelte.ts +148 -0
  468. package/src/toast-store.test.ts +86 -0
  469. package/src/tree-edit.test.ts +49 -0
  470. package/src/tree-filter.test.ts +56 -0
  471. package/src/tree-select.test.ts +48 -0
  472. package/src/tree-select.ts +62 -0
  473. package/src/ui-app.test.ts +130 -0
  474. package/src/ui-app.types.ts +88 -0
  475. package/src/ui-display.test.ts +79 -0
  476. package/src/ui-inputs.test.ts +1 -1
  477. package/src/ui-status.test.ts +141 -0
  478. package/src/ui-tier1.test.ts +142 -0
  479. package/src/ui-tier2.test.ts +124 -0
  480. package/src/ui-tier3.test.ts +139 -0
  481. package/src/validators.test.ts +58 -0
  482. package/src/validators.ts +105 -0
  483. package/src/virtual.test.ts +72 -0
  484. package/src/virtual.ts +67 -0
  485. package/src/virtualization/column-virtualizer.test.ts +27 -27
  486. package/src/virtualization/column-virtualizer.ts +30 -30
  487. package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
  488. package/src/virtualization/types.ts +30 -30
  489. package/src/virtualization/virtualizer.test.ts +47 -47
  490. package/src/virtualization/virtualizer.ts +296 -296
@@ -0,0 +1,124 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvToaster - renders the shared toast queue (see `toast-store`). Mount ONCE
4
+ * near the app root; call `toast()` from anywhere to push notifications. The
5
+ * container is an `aria-live` region as a visual backstop, though each toast
6
+ * is also announced through the shared live region by the store.
7
+ *
8
+ * ```svelte
9
+ * <SvToaster position="bottom-right" />
10
+ * ```
11
+ */
12
+ import { portalToBody } from './popover'
13
+ import { toastStore, dismissToast, pauseToast, resumeToast, type Toast } from './toast-store.svelte'
14
+
15
+ type Position =
16
+ | 'top-left' | 'top-center' | 'top-right'
17
+ | 'bottom-left' | 'bottom-center' | 'bottom-right'
18
+
19
+ type Props = {
20
+ /** Corner/edge the stack anchors to. Default 'bottom-right'. */
21
+ position?: Position
22
+ /** Max toasts shown at once (older ones stay queued in the store). */
23
+ max?: number
24
+ }
25
+
26
+ let { position = 'bottom-right', max = 5 }: Props = $props()
27
+
28
+ const visible = $derived(toastStore.toasts.slice(-max))
29
+ const icon = (v: Toast['variant']) =>
30
+ v === 'success' ? '✓' : v === 'error' ? '✕' : v === 'warning' ? '⚠' : 'ℹ'
31
+
32
+ // Swipe-to-dismiss: drag a toast sideways past ~60px to dismiss it.
33
+ let drag = $state<{ id: number; startX: number; dx: number } | null>(null)
34
+ function onDown(e: PointerEvent, id: number) {
35
+ drag = { id, startX: e.clientX, dx: 0 }
36
+ ;(e.currentTarget as HTMLElement).setPointerCapture?.(e.pointerId)
37
+ pauseToast(id)
38
+ }
39
+ function onMove(e: PointerEvent) {
40
+ if (drag) drag = { ...drag, dx: e.clientX - drag.startX }
41
+ }
42
+ function onUp(id: number) {
43
+ if (!drag || drag.id !== id) return
44
+ const dx = drag.dx
45
+ drag = null
46
+ if (Math.abs(dx) > 60) dismissToast(id)
47
+ else resumeToast(id)
48
+ }
49
+ const dragDx = (id: number) => (drag?.id === id ? drag.dx : 0)
50
+ </script>
51
+
52
+ <div class="sv-toaster sv-toaster--{position}" use:portalToBody role="region" aria-label="Notifications">
53
+ {#each visible as t (t.id)}
54
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
55
+ <div
56
+ class="sv-toast sv-toast--{t.variant}"
57
+ class:is-dragging={drag?.id === t.id}
58
+ role={t.variant === 'error' || t.variant === 'warning' ? 'alert' : 'status'}
59
+ style:transform={dragDx(t.id) ? `translateX(${dragDx(t.id)}px)` : undefined}
60
+ style:opacity={dragDx(t.id) ? 1 - Math.min(Math.abs(dragDx(t.id)) / 160, 0.7) : undefined}
61
+ onmouseenter={() => pauseToast(t.id)}
62
+ onmouseleave={() => resumeToast(t.id)}
63
+ onfocusin={() => pauseToast(t.id)}
64
+ onfocusout={() => resumeToast(t.id)}
65
+ onpointerdown={(e) => onDown(e, t.id)}
66
+ onpointermove={onMove}
67
+ onpointerup={() => onUp(t.id)}
68
+ onpointercancel={() => onUp(t.id)}
69
+ >
70
+ <span class="sv-toast__icon" aria-hidden="true">{icon(t.variant)}</span>
71
+ <div class="sv-toast__content">
72
+ {#if t.title}<div class="sv-toast__title">{t.title}</div>{/if}
73
+ <div class="sv-toast__msg">{t.message}</div>
74
+ </div>
75
+ {#if t.dismissible}
76
+ <button type="button" class="sv-toast__x" aria-label="Dismiss" onclick={() => dismissToast(t.id)}>&times;</button>
77
+ {/if}
78
+ </div>
79
+ {/each}
80
+ </div>
81
+
82
+ <style>
83
+ :global(.sv-toaster) {
84
+ position: fixed; z-index: 2147483001; display: flex; flex-direction: column; gap: 8px;
85
+ padding: 16px; max-width: min(92vw, 380px); pointer-events: none;
86
+ }
87
+ :global(.sv-toaster--top-left) { top: 0; left: 0; }
88
+ :global(.sv-toaster--top-center) { top: 0; left: 50%; transform: translateX(-50%); align-items: center; }
89
+ :global(.sv-toaster--top-right) { top: 0; right: 0; }
90
+ :global(.sv-toaster--bottom-left) { bottom: 0; left: 0; flex-direction: column-reverse; }
91
+ :global(.sv-toaster--bottom-center) { bottom: 0; left: 50%; transform: translateX(-50%); align-items: center; flex-direction: column-reverse; }
92
+ :global(.sv-toaster--bottom-right) { bottom: 0; right: 0; flex-direction: column-reverse; }
93
+
94
+ :global(.sv-toast) {
95
+ pointer-events: auto;
96
+ display: flex; align-items: flex-start; gap: 10px; width: 100%; box-sizing: border-box;
97
+ padding: 11px 12px; border-radius: 10px; font-size: 13px; line-height: 1.45;
98
+ background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
99
+ border: 1px solid var(--sg-border, #e2e8f0);
100
+ border-inline-start: 3px solid var(--_accent, var(--sg-accent, #2563eb));
101
+ box-shadow: 0 12px 32px -12px rgba(15, 23, 42, 0.4);
102
+ animation: sv-toast-in 0.18s cubic-bezier(0.16, 1, 0.3, 1) both;
103
+ transition: transform 0.2s ease, opacity 0.2s ease;
104
+ touch-action: pan-y; /* let vertical scroll through; capture horizontal swipe */
105
+ }
106
+ :global(.sv-toast.is-dragging) { transition: none; cursor: grabbing; user-select: none; }
107
+ @keyframes sv-toast-in { from { opacity: 0; transform: translateY(6px) scale(0.98) } to { opacity: 1 } }
108
+ @media (prefers-reduced-motion: reduce) { :global(.sv-toast) { animation: none } }
109
+
110
+ :global(.sv-toast--success) { --_accent: var(--sg-success, #16a34a); }
111
+ :global(.sv-toast--error) { --_accent: var(--sg-danger, #dc2626); }
112
+ :global(.sv-toast--warning) { --_accent: var(--sg-warning, #f59e0b); }
113
+ :global(.sv-toast--info) { --_accent: var(--sg-accent, #2563eb); }
114
+
115
+ :global(.sv-toast__icon) { flex: none; width: 18px; height: 18px; display: grid; place-items: center; color: var(--_accent); font-weight: 700; }
116
+ :global(.sv-toast__content) { flex: 1; min-width: 0; }
117
+ :global(.sv-toast__title) { font-weight: 650; margin-bottom: 1px; }
118
+ :global(.sv-toast__msg) { color: var(--sg-fg, #0f172a); overflow-wrap: anywhere; }
119
+ :global(.sv-toast__x) {
120
+ flex: none; width: 22px; height: 22px; display: grid; place-items: center; margin: -2px -2px 0 0;
121
+ background: none; border: 0; color: var(--sg-muted, #64748b); cursor: pointer; border-radius: 5px; font-size: 17px; line-height: 1;
122
+ }
123
+ :global(.sv-toast__x:hover) { background: var(--sg-row-hover-bg, #f1f5f9); color: var(--sg-fg, #0f172a); }
124
+ </style>
@@ -0,0 +1,10 @@
1
+ type Position = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
2
+ type Props = {
3
+ /** Corner/edge the stack anchors to. Default 'bottom-right'. */
4
+ position?: Position;
5
+ /** Max toasts shown at once (older ones stay queued in the store). */
6
+ max?: number;
7
+ };
8
+ declare const SvToaster: import("svelte").Component<Props, {}, "">;
9
+ type SvToaster = ReturnType<typeof SvToaster>;
10
+ export default SvToaster;
@@ -4,18 +4,34 @@
4
4
  * Parity: Smart `smart-toggle-button`. Controlled via `pressed` + `onChange`.
5
5
  */
6
6
  import type { Snippet } from 'svelte'
7
+ import SvField from './SvField.svelte'
8
+ import { nextEditorId, type SvEditorProps } from './editor-contract'
7
9
  import { createToggle } from './createToggle.svelte'
8
10
 
9
- type Props = {
11
+ type Props = SvEditorProps & {
10
12
  pressed?: boolean
11
13
  onChange?: (pressed: boolean) => void
12
- disabled?: boolean
13
- size?: 'sm' | 'md' | 'lg'
14
- ariaLabel?: string
15
14
  children?: Snippet
16
15
  }
17
16
 
18
- let { pressed = false, onChange, disabled = false, size = 'md', ariaLabel, children }: Props = $props()
17
+ let {
18
+ pressed = false,
19
+ onChange,
20
+ disabled = false,
21
+ size = 'md',
22
+ ariaLabel,
23
+ invalid = false,
24
+ required = false,
25
+ error,
26
+ label,
27
+ hint,
28
+ dir,
29
+ id,
30
+ children,
31
+ }: Props = $props()
32
+
33
+ const autoId = nextEditorId('sv-toggle')
34
+ const uid = $derived(id ?? autoId)
19
35
 
20
36
  // The styled toggle is just a renderer over the headless core.
21
37
  const t = createToggle({
@@ -23,16 +39,24 @@
23
39
  onChange: (v) => onChange?.(v),
24
40
  disabled: () => disabled,
25
41
  ariaLabel: () => ariaLabel,
42
+ id: () => uid,
43
+ invalid: () => invalid,
44
+ required: () => required,
45
+ error: () => error,
46
+ hint: () => hint,
26
47
  })
27
48
  </script>
28
49
 
29
- <button
30
- class="sv-toggle sv-toggle--{size}"
31
- class:is-pressed={pressed}
32
- {...t.buttonProps()}
33
- >
34
- {#if children}{@render children()}{/if}
35
- </button>
50
+ <SvField id={uid} {label} {hint} {error} {required} {dir}>
51
+ <button
52
+ class="sv-toggle sv-toggle--{size}"
53
+ class:is-pressed={pressed}
54
+ class:is-invalid={invalid}
55
+ {...t.buttonProps()}
56
+ >
57
+ {#if children}{@render children()}{/if}
58
+ </button>
59
+ </SvField>
36
60
 
37
61
  <style>
38
62
  .sv-toggle {
@@ -53,5 +77,6 @@
53
77
  background: var(--_accent); color: var(--sg-on-accent, #fff); border-color: var(--_accent);
54
78
  }
55
79
  .sv-toggle[disabled] { opacity: 0.55; cursor: not-allowed; }
80
+ .sv-toggle.is-invalid { border-color: var(--sg-danger, #dc2626); }
56
81
  .sv-toggle:focus-visible { outline: 2px solid var(--sg-focus-ring, var(--_accent)); outline-offset: 2px; }
57
82
  </style>
@@ -3,12 +3,10 @@
3
3
  * Parity: Smart `smart-toggle-button`. Controlled via `pressed` + `onChange`.
4
4
  */
5
5
  import type { Snippet } from 'svelte';
6
- type Props = {
6
+ import { type SvEditorProps } from './editor-contract';
7
+ type Props = SvEditorProps & {
7
8
  pressed?: boolean;
8
9
  onChange?: (pressed: boolean) => void;
9
- disabled?: boolean;
10
- size?: 'sm' | 'md' | 'lg';
11
- ariaLabel?: string;
12
10
  children?: Snippet;
13
11
  };
14
12
  declare const SvToggleButton: import("svelte").Component<Props, {}, "">;
@@ -0,0 +1,113 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvTooltip - a small hover/focus tooltip anchored to its child, portalled to
4
+ * <body> so it is never clipped. Shows after a short delay, hides on leave /
5
+ * blur / Escape, and is wired via `aria-describedby` (role="tooltip"). Respects
6
+ * keyboard users (opens on focus).
7
+ *
8
+ * ```svelte
9
+ * <SvTooltip text="Delete row"><button aria-label="Delete">🗑</button></SvTooltip>
10
+ * ```
11
+ */
12
+ import type { Snippet } from 'svelte'
13
+ import { portalToBody, popIn } from './popover'
14
+ import { nextEditorId } from './editor-contract'
15
+
16
+ type Props = {
17
+ text: string
18
+ placement?: 'top' | 'bottom'
19
+ /** Show delay in ms. Default 300. */
20
+ delay?: number
21
+ disabled?: boolean
22
+ children?: Snippet
23
+ }
24
+
25
+ let { text, placement = 'top', delay = 300, disabled = false, children }: Props = $props()
26
+
27
+ let anchorEl = $state<HTMLSpanElement | null>(null)
28
+ let tipEl = $state<HTMLDivElement | null>(null)
29
+ let open = $state(false)
30
+ let pos = $state({ top: 0, left: 0, arrowX: 12 })
31
+ const tid = nextEditorId('sv-tip')
32
+ let showTimer: ReturnType<typeof setTimeout> | undefined
33
+
34
+ function place() {
35
+ if (!anchorEl) return
36
+ const r = anchorEl.getBoundingClientRect()
37
+ const tipH = tipEl?.offsetHeight ?? 30
38
+ const tipW = tipEl?.offsetWidth ?? 0
39
+ const top = placement === 'top' ? r.top - tipH - 8 : r.bottom + 8
40
+ let left = r.left + r.width / 2 - tipW / 2
41
+ left = Math.max(4, Math.min(left, window.innerWidth - tipW - 4))
42
+ // Keep the arrow under the anchor's center even when the tip is clamped.
43
+ const arrowX = Math.max(10, Math.min(tipW - 10, r.left + r.width / 2 - left))
44
+ pos = { top, left, arrowX }
45
+ }
46
+
47
+ function show() {
48
+ if (disabled || !text) return
49
+ clearTimeout(showTimer)
50
+ showTimer = setTimeout(() => { open = true; queueMicrotask(place) }, delay)
51
+ }
52
+ function hide() { clearTimeout(showTimer); open = false }
53
+
54
+ $effect(() => {
55
+ if (!open) return
56
+ place()
57
+ const rp = () => place()
58
+ window.addEventListener('scroll', rp, true)
59
+ window.addEventListener('resize', rp)
60
+ const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') hide() }
61
+ document.addEventListener('keydown', onKey)
62
+ return () => {
63
+ window.removeEventListener('scroll', rp, true)
64
+ window.removeEventListener('resize', rp)
65
+ document.removeEventListener('keydown', onKey)
66
+ }
67
+ })
68
+ </script>
69
+
70
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
71
+ <span
72
+ bind:this={anchorEl}
73
+ class="sv-tip__anchor"
74
+ aria-describedby={open ? tid : undefined}
75
+ onpointerenter={show}
76
+ onpointerleave={hide}
77
+ onfocusin={show}
78
+ onfocusout={hide}
79
+ >
80
+ {@render children?.()}
81
+ </span>
82
+
83
+ {#if open}
84
+ <div
85
+ bind:this={tipEl}
86
+ id={tid}
87
+ class="sv-tip"
88
+ role="tooltip"
89
+ use:portalToBody
90
+ use:popIn={{ up: placement === 'top', duration: 110, scale: 0.9 }}
91
+ class:sv-tip--bottom={placement === 'bottom'}
92
+ style:position="fixed"
93
+ style:top={`${pos.top}px`}
94
+ style:left={`${pos.left}px`}
95
+ style:--tip-arrow-x={`${pos.arrowX}px`}
96
+ >{text}<span class="sv-tip__arrow" aria-hidden="true"></span></div>
97
+ {/if}
98
+
99
+ <style>
100
+ .sv-tip__anchor { display: inline-flex; }
101
+ :global(.sv-tip) {
102
+ z-index: 2147483647; pointer-events: none; position: relative;
103
+ max-width: 240px; padding: 5px 9px; font-size: 12px; line-height: 1.4; font-weight: 500;
104
+ background: var(--sg-fg, #0f172a); color: var(--sg-bg, #fff);
105
+ border-radius: 6px; box-shadow: 0 6px 20px -6px rgba(15, 23, 42, 0.5); white-space: normal;
106
+ }
107
+ :global(.sv-tip__arrow) {
108
+ position: absolute; inset-inline-start: var(--tip-arrow-x, 12px); width: 8px; height: 8px;
109
+ background: var(--sg-fg, #0f172a); transform: translateX(-50%) rotate(45deg);
110
+ }
111
+ :global(.sv-tip:not(.sv-tip--bottom) .sv-tip__arrow) { bottom: -3px; }
112
+ :global(.sv-tip--bottom .sv-tip__arrow) { top: -3px; }
113
+ </style>
@@ -0,0 +1,22 @@
1
+ /**
2
+ * SvTooltip - a small hover/focus tooltip anchored to its child, portalled to
3
+ * <body> so it is never clipped. Shows after a short delay, hides on leave /
4
+ * blur / Escape, and is wired via `aria-describedby` (role="tooltip"). Respects
5
+ * keyboard users (opens on focus).
6
+ *
7
+ * ```svelte
8
+ * <SvTooltip text="Delete row"><button aria-label="Delete">🗑</button></SvTooltip>
9
+ * ```
10
+ */
11
+ import type { Snippet } from 'svelte';
12
+ type Props = {
13
+ text: string;
14
+ placement?: 'top' | 'bottom';
15
+ /** Show delay in ms. Default 300. */
16
+ delay?: number;
17
+ disabled?: boolean;
18
+ children?: Snippet;
19
+ };
20
+ declare const SvTooltip: import("svelte").Component<Props, {}, "">;
21
+ type SvTooltip = ReturnType<typeof SvTooltip>;
22
+ export default SvTooltip;
@@ -0,0 +1,151 @@
1
+ <script lang="ts" module>
2
+ export type { TourStep } from './ui-app.types'
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ /**
7
+ * SvTour - a guided product tour / onboarding: it spotlights each step's target
8
+ * element (a dimmed backdrop with a cut-out), anchors a popover with the step's
9
+ * title/content near it, and steps Back / Next / Done. Arrow keys navigate,
10
+ * Escape skips. Portalled to <body>. Controlled via `open`.
11
+ *
12
+ * ```svelte
13
+ * <SvTour bind:open steps={[
14
+ * { target: '#new-btn', title: 'Create', content: 'Start here.' },
15
+ * { target: '.grid', title: 'Your data', content: 'It shows up here.' },
16
+ * ]} />
17
+ * ```
18
+ */
19
+ import type { TourStep } from './ui-app.types'
20
+ import { portalToBody } from './popover'
21
+
22
+ type Props = {
23
+ steps: ReadonlyArray<TourStep>
24
+ open?: boolean
25
+ onFinish?: () => void
26
+ onSkip?: () => void
27
+ onStep?: (index: number) => void
28
+ }
29
+
30
+ let { steps, open = $bindable(false), onFinish, onSkip, onStep }: Props = $props()
31
+
32
+ let index = $state(0)
33
+ let rect = $state<DOMRect | null>(null)
34
+ const step = $derived(steps[index])
35
+
36
+ function targetEl(): HTMLElement | null {
37
+ const t = step?.target
38
+ if (!t) return null
39
+ return typeof t === 'string' ? document.querySelector<HTMLElement>(t) : t
40
+ }
41
+ function measure() {
42
+ const el = targetEl()
43
+ el?.scrollIntoView({ block: 'center', behavior: 'smooth' })
44
+ rect = el ? el.getBoundingClientRect() : null
45
+ }
46
+ function goto(i: number) {
47
+ index = Math.max(0, Math.min(i, steps.length - 1))
48
+ onStep?.(index)
49
+ queueMicrotask(measure)
50
+ }
51
+ function next() { if (index >= steps.length - 1) finish(); else goto(index + 1) }
52
+ function back() { goto(index - 1) }
53
+ function finish() { open = false; onFinish?.() }
54
+ function skip() { open = false; onSkip?.() }
55
+
56
+ $effect(() => {
57
+ if (!open) return
58
+ index = 0
59
+ queueMicrotask(measure)
60
+ const reflow = () => measure()
61
+ window.addEventListener('resize', reflow)
62
+ window.addEventListener('scroll', reflow, true)
63
+ const onKey = (e: KeyboardEvent) => {
64
+ if (e.key === 'Escape') { e.preventDefault(); skip() }
65
+ else if (e.key === 'ArrowRight') { e.preventDefault(); next() }
66
+ else if (e.key === 'ArrowLeft') { e.preventDefault(); back() }
67
+ }
68
+ window.addEventListener('keydown', onKey)
69
+ return () => {
70
+ window.removeEventListener('resize', reflow)
71
+ window.removeEventListener('scroll', reflow, true)
72
+ window.removeEventListener('keydown', onKey)
73
+ }
74
+ })
75
+
76
+ const POP_W = 300
77
+ const pop = $derived.by(() => {
78
+ if (typeof window === 'undefined' || !rect) {
79
+ return { top: '50%', left: '50%', transform: 'translate(-50%, -50%)', place: 'center' as const }
80
+ }
81
+ const left = Math.max(12, Math.min(rect.left, window.innerWidth - POP_W - 12))
82
+ const below = window.innerHeight - rect.bottom
83
+ if (below > 190) return { top: `${rect.bottom + 10}px`, left: `${left}px`, transform: 'none', place: 'bottom' as const }
84
+ return { top: `${rect.top - 10}px`, left: `${left}px`, transform: 'translateY(-100%)', place: 'top' as const }
85
+ })
86
+ </script>
87
+
88
+ {#if open && step}
89
+ <div class="sv-tour" use:portalToBody>
90
+ {#if rect}
91
+ <div
92
+ class="sv-tour__spot"
93
+ style:top={`${rect.top - 6}px`}
94
+ style:left={`${rect.left - 6}px`}
95
+ style:width={`${rect.width + 12}px`}
96
+ style:height={`${rect.height + 12}px`}
97
+ ></div>
98
+ {:else}
99
+ <div class="sv-tour__backdrop"></div>
100
+ {/if}
101
+
102
+ <div
103
+ class="sv-tour__pop sv-tour__pop--{pop.place}"
104
+ style:top={pop.top}
105
+ style:left={pop.left}
106
+ style:transform={pop.transform}
107
+ role="dialog"
108
+ aria-modal="true"
109
+ aria-label={step.title ?? 'Tour step'}
110
+ >
111
+ {#if step.title}<div class="sv-tour__title">{step.title}</div>{/if}
112
+ <div class="sv-tour__body">{step.content}</div>
113
+ <div class="sv-tour__foot">
114
+ <span class="sv-tour__count">{index + 1} / {steps.length}</span>
115
+ <div class="sv-tour__btns">
116
+ <button type="button" class="sv-tour__skip" onclick={skip}>Skip</button>
117
+ {#if index > 0}<button type="button" class="sv-tour__back" onclick={back}>Back</button>{/if}
118
+ <button type="button" class="sv-tour__next" onclick={next}>{index === steps.length - 1 ? 'Done' : 'Next'}</button>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ {/if}
124
+
125
+ <style>
126
+ :global(.sv-tour) { position: fixed; inset: 0; z-index: 2147483000; }
127
+ :global(.sv-tour__backdrop) { position: fixed; inset: 0; background: rgba(15, 23, 42, 0.55); }
128
+ :global(.sv-tour__spot) {
129
+ position: fixed; border-radius: 8px; pointer-events: none;
130
+ box-shadow: 0 0 0 9999px rgba(15, 23, 42, 0.55); transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
131
+ }
132
+ :global(.sv-tour__pop) {
133
+ position: fixed; z-index: 1; width: 300px; max-width: calc(100vw - 24px);
134
+ background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
135
+ border: 1px solid var(--sg-border, #e2e8f0); border-radius: 12px; padding: 14px 16px;
136
+ box-shadow: 0 20px 48px -16px rgba(15, 23, 42, 0.5);
137
+ animation: sv-tour-in 0.16s cubic-bezier(0.16, 1, 0.3, 1) both;
138
+ }
139
+ @keyframes sv-tour-in { from { opacity: 0; transform: translateY(4px) } }
140
+ :global(.sv-tour__pop--top) { animation: none; }
141
+ :global(.sv-tour__title) { font-size: 14.5px; font-weight: 650; margin-bottom: 4px; }
142
+ :global(.sv-tour__body) { font-size: 13px; line-height: 1.55; color: var(--sg-fg, #334155); }
143
+ :global(.sv-tour__foot) { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 14px; }
144
+ :global(.sv-tour__count) { font-size: 12px; color: var(--sg-muted, #94a3b8); font-variant-numeric: tabular-nums; }
145
+ :global(.sv-tour__btns) { display: flex; gap: 6px; }
146
+ :global(.sv-tour__skip), :global(.sv-tour__back), :global(.sv-tour__next) {
147
+ font: inherit; font-size: 12.5px; padding: 5px 12px; border-radius: 7px; cursor: pointer; border: 1px solid var(--sg-border, #cbd5e1); background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
148
+ }
149
+ :global(.sv-tour__skip) { border-color: transparent; background: none; color: var(--sg-muted, #64748b); }
150
+ :global(.sv-tour__next) { background: var(--sg-accent, #2563eb); border-color: var(--sg-accent, #2563eb); color: var(--sg-on-accent, #fff); }
151
+ </style>
@@ -0,0 +1,25 @@
1
+ export type { TourStep } from './ui-app.types';
2
+ /**
3
+ * SvTour - a guided product tour / onboarding: it spotlights each step's target
4
+ * element (a dimmed backdrop with a cut-out), anchors a popover with the step's
5
+ * title/content near it, and steps Back / Next / Done. Arrow keys navigate,
6
+ * Escape skips. Portalled to <body>. Controlled via `open`.
7
+ *
8
+ * ```svelte
9
+ * <SvTour bind:open steps={[
10
+ * { target: '#new-btn', title: 'Create', content: 'Start here.' },
11
+ * { target: '.grid', title: 'Your data', content: 'It shows up here.' },
12
+ * ]} />
13
+ * ```
14
+ */
15
+ import type { TourStep } from './ui-app.types';
16
+ type Props = {
17
+ steps: ReadonlyArray<TourStep>;
18
+ open?: boolean;
19
+ onFinish?: () => void;
20
+ onSkip?: () => void;
21
+ onStep?: (index: number) => void;
22
+ };
23
+ declare const SvTour: import("svelte").Component<Props, {}, "open">;
24
+ type SvTour = ReturnType<typeof SvTour>;
25
+ export default SvTour;