@happyvertical/smrt-ui 0.51.39 → 0.53.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 (392) hide show
  1. package/AGENTS.md +25 -3
  2. package/README.md +558 -8
  3. package/dist/actions/__tests__/swipe-dismiss.test.js +69 -0
  4. package/dist/actions/swipe-dismiss.d.ts +42 -0
  5. package/dist/actions/swipe-dismiss.d.ts.map +1 -0
  6. package/dist/actions/swipe-dismiss.js +69 -0
  7. package/dist/components/calendar/Calendar.svelte +5 -0
  8. package/dist/components/calendar/Calendar.svelte.d.ts.map +1 -1
  9. package/dist/components/calendar/CalendarView.svelte +1250 -0
  10. package/dist/components/calendar/CalendarView.svelte.d.ts +66 -0
  11. package/dist/components/calendar/CalendarView.svelte.d.ts.map +1 -0
  12. package/dist/components/calendar/DayView.svelte +5 -0
  13. package/dist/components/calendar/DayView.svelte.d.ts.map +1 -1
  14. package/dist/components/calendar/__tests__/CalendarView.test.js +226 -0
  15. package/dist/components/calendar/__tests__/calendar-model.test.js +138 -0
  16. package/dist/components/calendar/calendar-model.d.ts +178 -0
  17. package/dist/components/calendar/calendar-model.d.ts.map +1 -0
  18. package/dist/components/calendar/calendar-model.js +362 -0
  19. package/dist/components/calendar/index.d.ts +12 -1
  20. package/dist/components/calendar/index.d.ts.map +1 -1
  21. package/dist/components/calendar/index.js +11 -1
  22. package/dist/components/data/CollectionList.svelte +23 -5
  23. package/dist/components/data/CollectionList.svelte.d.ts +8 -2
  24. package/dist/components/data/CollectionList.svelte.d.ts.map +1 -1
  25. package/dist/components/data/DataTable.svelte +178 -55
  26. package/dist/components/data/DataTable.svelte.d.ts.map +1 -1
  27. package/dist/components/data/DataTableController.d.ts +4 -0
  28. package/dist/components/data/DataTableController.d.ts.map +1 -1
  29. package/dist/components/data/DataTableController.js +11 -4
  30. package/dist/components/data/DataTableResponsive.d.ts +4 -0
  31. package/dist/components/data/DataTableResponsive.d.ts.map +1 -0
  32. package/dist/components/data/DataTableResponsive.js +22 -0
  33. package/dist/components/data/ListSortSelect.svelte +121 -0
  34. package/dist/components/data/ListSortSelect.svelte.d.ts +22 -0
  35. package/dist/components/data/ListSortSelect.svelte.d.ts.map +1 -0
  36. package/dist/components/data/SortableHeader.svelte +169 -0
  37. package/dist/components/data/SortableHeader.svelte.d.ts +30 -0
  38. package/dist/components/data/SortableHeader.svelte.d.ts.map +1 -0
  39. package/dist/components/data/__tests__/CollectionList.test.js +37 -0
  40. package/dist/components/data/__tests__/DataTable.test.js +76 -0
  41. package/dist/components/data/__tests__/DataTableController.test.js +35 -0
  42. package/dist/components/data/__tests__/DataTableResponsive.test.js +80 -0
  43. package/dist/components/data/__tests__/SortableHeader.test.js +101 -0
  44. package/dist/components/data/__tests__/link-step-surface.test.js +172 -0
  45. package/dist/components/data/__tests__/list-sort-state.svelte.test.js +71 -0
  46. package/dist/components/data/__tests__/list-sort.test.js +91 -0
  47. package/dist/components/data/__tests__/responsive-table.fixture.svelte +29 -0
  48. package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts +7 -0
  49. package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts.map +1 -0
  50. package/dist/components/data/__tests__/surface-navigation.test.js +121 -0
  51. package/dist/components/data/data-surface.d.ts +1 -0
  52. package/dist/components/data/data-surface.d.ts.map +1 -1
  53. package/dist/components/data/data-surface.js +1 -0
  54. package/dist/components/data/index.d.ts +6 -0
  55. package/dist/components/data/index.d.ts.map +1 -1
  56. package/dist/components/data/index.js +6 -0
  57. package/dist/components/data/link-surface.d.ts +79 -0
  58. package/dist/components/data/link-surface.d.ts.map +1 -0
  59. package/dist/components/data/link-surface.js +155 -0
  60. package/dist/components/data/list-sort-state.svelte.d.ts +39 -0
  61. package/dist/components/data/list-sort-state.svelte.d.ts.map +1 -0
  62. package/dist/components/data/list-sort-state.svelte.js +47 -0
  63. package/dist/components/data/list-sort.d.ts +94 -0
  64. package/dist/components/data/list-sort.d.ts.map +1 -0
  65. package/dist/components/data/list-sort.js +182 -0
  66. package/dist/components/data/step-surface.d.ts +73 -0
  67. package/dist/components/data/step-surface.d.ts.map +1 -0
  68. package/dist/components/data/step-surface.js +177 -0
  69. package/dist/components/data/surface-navigation.d.ts +49 -0
  70. package/dist/components/data/surface-navigation.d.ts.map +1 -0
  71. package/dist/components/data/surface-navigation.js +100 -0
  72. package/dist/components/data/types.d.ts +27 -0
  73. package/dist/components/data/types.d.ts.map +1 -1
  74. package/dist/components/display/DateDisplay.svelte +76 -14
  75. package/dist/components/display/DateDisplay.svelte.d.ts +2 -0
  76. package/dist/components/display/DateDisplay.svelte.d.ts.map +1 -1
  77. package/dist/components/display/Icon.svelte +3 -16
  78. package/dist/components/display/Icon.svelte.d.ts +0 -9
  79. package/dist/components/display/Icon.svelte.d.ts.map +1 -1
  80. package/dist/components/display/StatusBadge.svelte +29 -2
  81. package/dist/components/display/StatusBadge.svelte.d.ts +4 -2
  82. package/dist/components/display/StatusBadge.svelte.d.ts.map +1 -1
  83. package/dist/components/display/__tests__/DateDisplay.test.js +82 -1
  84. package/dist/components/display/__tests__/Icon.test.js +132 -2
  85. package/dist/components/display/__tests__/StatusBadge.test.js +78 -0
  86. package/dist/components/display/icons.svelte.d.ts +11 -0
  87. package/dist/components/display/icons.svelte.d.ts.map +1 -0
  88. package/dist/components/display/icons.svelte.js +60 -0
  89. package/dist/components/display/index.d.ts +3 -1
  90. package/dist/components/display/index.d.ts.map +1 -1
  91. package/dist/components/display/index.js +1 -0
  92. package/dist/components/display/types.d.ts +2 -0
  93. package/dist/components/display/types.d.ts.map +1 -1
  94. package/dist/components/feedback/ConfirmDialog.svelte +59 -48
  95. package/dist/components/feedback/ConfirmDialog.svelte.d.ts +14 -2
  96. package/dist/components/feedback/ConfirmDialog.svelte.d.ts.map +1 -1
  97. package/dist/components/feedback/PhoneSheet.svelte +224 -0
  98. package/dist/components/feedback/PhoneSheet.svelte.d.ts +35 -0
  99. package/dist/components/feedback/PhoneSheet.svelte.d.ts.map +1 -0
  100. package/dist/components/feedback/ToastViewport.svelte +156 -8
  101. package/dist/components/feedback/ToastViewport.svelte.d.ts +5 -1
  102. package/dist/components/feedback/ToastViewport.svelte.d.ts.map +1 -1
  103. package/dist/components/feedback/WorkingStrip.svelte +426 -0
  104. package/dist/components/feedback/WorkingStrip.svelte.d.ts +37 -0
  105. package/dist/components/feedback/WorkingStrip.svelte.d.ts.map +1 -0
  106. package/dist/components/feedback/__tests__/ConfirmDialog.test.js +38 -20
  107. package/dist/components/feedback/__tests__/PhoneSheet.test.js +101 -0
  108. package/dist/components/feedback/__tests__/WorkingStrip.test.js +172 -0
  109. package/dist/components/feedback/__tests__/confirm-message.fixture.svelte +9 -0
  110. package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts +19 -0
  111. package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts.map +1 -0
  112. package/dist/components/feedback/__tests__/toast.test.js +142 -1
  113. package/dist/components/feedback/index.d.ts +5 -1
  114. package/dist/components/feedback/index.d.ts.map +1 -1
  115. package/dist/components/feedback/index.js +5 -0
  116. package/dist/components/feedback/toast.d.ts +13 -1
  117. package/dist/components/feedback/toast.d.ts.map +1 -1
  118. package/dist/components/feedback/toast.js +51 -10
  119. package/dist/components/feedback/working-status.d.ts +34 -0
  120. package/dist/components/feedback/working-status.d.ts.map +1 -0
  121. package/dist/components/feedback/working-status.js +5 -0
  122. package/dist/components/forms/CameraCapture.svelte +619 -0
  123. package/dist/components/forms/CameraCapture.svelte.d.ts +42 -0
  124. package/dist/components/forms/CameraCapture.svelte.d.ts.map +1 -0
  125. package/dist/components/forms/Checkbox.svelte +34 -3
  126. package/dist/components/forms/Checkbox.svelte.d.ts +2 -0
  127. package/dist/components/forms/Checkbox.svelte.d.ts.map +1 -1
  128. package/dist/components/forms/Combobox.svelte +108 -12
  129. package/dist/components/forms/Combobox.svelte.d.ts +6 -0
  130. package/dist/components/forms/Combobox.svelte.d.ts.map +1 -1
  131. package/dist/components/forms/DictationButton.svelte +128 -0
  132. package/dist/components/forms/DictationButton.svelte.d.ts +19 -0
  133. package/dist/components/forms/DictationButton.svelte.d.ts.map +1 -0
  134. package/dist/components/forms/DictationStatus.svelte +164 -0
  135. package/dist/components/forms/DictationStatus.svelte.d.ts +11 -0
  136. package/dist/components/forms/DictationStatus.svelte.d.ts.map +1 -0
  137. package/dist/components/forms/Fieldset.svelte +5 -1
  138. package/dist/components/forms/Fieldset.svelte.d.ts +2 -0
  139. package/dist/components/forms/Fieldset.svelte.d.ts.map +1 -1
  140. package/dist/components/forms/Form.svelte +5 -0
  141. package/dist/components/forms/Form.svelte.d.ts +1 -0
  142. package/dist/components/forms/Form.svelte.d.ts.map +1 -1
  143. package/dist/components/forms/FormActionBar.svelte +84 -0
  144. package/dist/components/forms/FormActionBar.svelte.d.ts +23 -0
  145. package/dist/components/forms/FormActionBar.svelte.d.ts.map +1 -0
  146. package/dist/components/forms/Input.svelte +17 -1
  147. package/dist/components/forms/Input.svelte.d.ts +2 -0
  148. package/dist/components/forms/Input.svelte.d.ts.map +1 -1
  149. package/dist/components/forms/Listbox.svelte +39 -1
  150. package/dist/components/forms/Listbox.svelte.d.ts.map +1 -1
  151. package/dist/components/forms/MultiSelect.svelte +41 -1
  152. package/dist/components/forms/MultiSelect.svelte.d.ts.map +1 -1
  153. package/dist/components/forms/Radio.svelte +16 -4
  154. package/dist/components/forms/RadioGroup.svelte +7 -1
  155. package/dist/components/forms/RadioGroup.svelte.d.ts +2 -0
  156. package/dist/components/forms/RadioGroup.svelte.d.ts.map +1 -1
  157. package/dist/components/forms/SearchInput.svelte +207 -0
  158. package/dist/components/forms/SearchInput.svelte.d.ts +22 -0
  159. package/dist/components/forms/SearchInput.svelte.d.ts.map +1 -0
  160. package/dist/components/forms/SegmentedControl.svelte +152 -11
  161. package/dist/components/forms/SegmentedControl.svelte.d.ts +4 -0
  162. package/dist/components/forms/SegmentedControl.svelte.d.ts.map +1 -1
  163. package/dist/components/forms/Select.svelte +17 -1
  164. package/dist/components/forms/Select.svelte.d.ts +2 -0
  165. package/dist/components/forms/Select.svelte.d.ts.map +1 -1
  166. package/dist/components/forms/SignaturePad.svelte +436 -0
  167. package/dist/components/forms/SignaturePad.svelte.d.ts +32 -0
  168. package/dist/components/forms/SignaturePad.svelte.d.ts.map +1 -0
  169. package/dist/components/forms/StagedControlReview.svelte +21 -12
  170. package/dist/components/forms/StagedControlReview.svelte.d.ts.map +1 -1
  171. package/dist/components/forms/Switch.svelte +18 -5
  172. package/dist/components/forms/Switch.svelte.d.ts +2 -0
  173. package/dist/components/forms/Switch.svelte.d.ts.map +1 -1
  174. package/dist/components/forms/TagsInput.svelte +8 -1
  175. package/dist/components/forms/Textarea.svelte +16 -1
  176. package/dist/components/forms/Textarea.svelte.d.ts +2 -0
  177. package/dist/components/forms/Textarea.svelte.d.ts.map +1 -1
  178. package/dist/components/forms/__tests__/CameraCapture.test.js +504 -0
  179. package/dist/components/forms/__tests__/Combobox.test.js +354 -0
  180. package/dist/components/forms/__tests__/ControlHitArea.test.js +73 -0
  181. package/dist/components/forms/__tests__/DictationButton.test.js +176 -0
  182. package/dist/components/forms/__tests__/Fieldset.test.js +37 -0
  183. package/dist/components/forms/__tests__/Form.test.js +46 -0
  184. package/dist/components/forms/__tests__/FormActionBar.test.js +22 -0
  185. package/dist/components/forms/__tests__/Listbox.test.js +303 -0
  186. package/dist/components/forms/__tests__/MultiSelect.test.js +281 -0
  187. package/dist/components/forms/__tests__/SearchInput.test.js +92 -0
  188. package/dist/components/forms/__tests__/SignaturePad.test.js +338 -0
  189. package/dist/components/forms/__tests__/StagedControlReview.test.js +37 -3
  190. package/dist/components/forms/__tests__/camera-capture-session.test.js +207 -0
  191. package/dist/components/forms/__tests__/capture-form-retry.test.js +166 -0
  192. package/dist/components/forms/__tests__/capture-form.fixture.svelte +38 -0
  193. package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts +10 -0
  194. package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts.map +1 -0
  195. package/dist/components/forms/__tests__/capture-test-env.d.ts +70 -0
  196. package/dist/components/forms/__tests__/capture-test-env.d.ts.map +1 -0
  197. package/dist/components/forms/__tests__/capture-test-env.js +122 -0
  198. package/dist/components/forms/__tests__/capture-touch.fixture.svelte +15 -0
  199. package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts +8 -0
  200. package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts.map +1 -0
  201. package/dist/components/forms/__tests__/combobox-form.fixture.svelte +29 -0
  202. package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts +14 -0
  203. package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts.map +1 -0
  204. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte +19 -0
  205. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts +11 -0
  206. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts.map +1 -0
  207. package/dist/components/forms/__tests__/composite-registration.fixture.svelte +29 -0
  208. package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts +8 -0
  209. package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts.map +1 -0
  210. package/dist/components/forms/__tests__/control-interaction.test.js +19 -1
  211. package/dist/components/forms/__tests__/control-proposals.test.js +63 -0
  212. package/dist/components/forms/__tests__/dictation-recording.test.js +582 -0
  213. package/dist/components/forms/__tests__/dictation.test.js +486 -0
  214. package/dist/components/forms/__tests__/form-attachment.fixture.svelte +28 -0
  215. package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts +11 -0
  216. package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts.map +1 -0
  217. package/dist/components/forms/__tests__/form-retry-form.fixture.svelte +31 -0
  218. package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts +13 -0
  219. package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts.map +1 -0
  220. package/dist/components/forms/__tests__/form-retry-form.test.js +107 -0
  221. package/dist/components/forms/__tests__/hidden-controls-form-retry.test.js +69 -0
  222. package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte +29 -0
  223. package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts +9 -0
  224. package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts.map +1 -0
  225. package/dist/components/forms/__tests__/listbox-form.fixture.svelte +27 -0
  226. package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts +13 -0
  227. package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts.map +1 -0
  228. package/dist/components/forms/__tests__/long-press.test.js +175 -0
  229. package/dist/components/forms/__tests__/multiselect-form.fixture.svelte +27 -0
  230. package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts +13 -0
  231. package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts.map +1 -0
  232. package/dist/components/forms/__tests__/native-file-field.test.js +177 -0
  233. package/dist/components/forms/__tests__/place-picker.fixture.svelte +33 -0
  234. package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts +12 -0
  235. package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts.map +1 -0
  236. package/dist/components/forms/__tests__/segmented-posting.fixture.svelte +28 -0
  237. package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts +12 -0
  238. package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts.map +1 -0
  239. package/dist/components/forms/__tests__/segmented-posting.test.js +92 -0
  240. package/dist/components/forms/__tests__/signature-pad-logic.test.js +54 -0
  241. package/dist/components/forms/__tests__/touch-density.fixture.svelte +34 -0
  242. package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts +8 -0
  243. package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts.map +1 -0
  244. package/dist/components/forms/__tests__/touch-density.test.js +66 -0
  245. package/dist/components/forms/audio-capture.d.ts +69 -0
  246. package/dist/components/forms/audio-capture.d.ts.map +1 -0
  247. package/dist/components/forms/audio-capture.js +193 -0
  248. package/dist/components/forms/camera-capture-session.d.ts +81 -0
  249. package/dist/components/forms/camera-capture-session.d.ts.map +1 -0
  250. package/dist/components/forms/camera-capture-session.js +130 -0
  251. package/dist/components/forms/control-interaction.d.ts +6 -0
  252. package/dist/components/forms/control-interaction.d.ts.map +1 -1
  253. package/dist/components/forms/control-interaction.js +12 -1
  254. package/dist/components/forms/control-proposals.d.ts +55 -0
  255. package/dist/components/forms/control-proposals.d.ts.map +1 -0
  256. package/dist/components/forms/control-proposals.js +188 -0
  257. package/dist/components/forms/dictation-transcribe.d.ts +36 -0
  258. package/dist/components/forms/dictation-transcribe.d.ts.map +1 -0
  259. package/dist/components/forms/dictation-transcribe.js +65 -0
  260. package/dist/components/forms/dictation.svelte.d.ts +200 -0
  261. package/dist/components/forms/dictation.svelte.d.ts.map +1 -0
  262. package/dist/components/forms/dictation.svelte.js +686 -0
  263. package/dist/components/forms/form-retry/__tests__/boundaries.test.js +23 -0
  264. package/dist/components/forms/form-retry/__tests__/content-digest.test.js +70 -0
  265. package/dist/components/forms/form-retry/__tests__/controller.test.js +802 -0
  266. package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts +82 -0
  267. package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts.map +1 -0
  268. package/dist/components/forms/form-retry/__tests__/fake-kit.js +180 -0
  269. package/dist/components/forms/form-retry/__tests__/form-draft.test.js +169 -0
  270. package/dist/components/forms/form-retry/__tests__/ssr.test.js +37 -0
  271. package/dist/components/forms/form-retry/__tests__/storage.d.ts +26 -0
  272. package/dist/components/forms/form-retry/__tests__/storage.d.ts.map +1 -0
  273. package/dist/components/forms/form-retry/__tests__/storage.js +63 -0
  274. package/dist/components/forms/form-retry/__tests__/submission-key.test.js +236 -0
  275. package/dist/components/forms/form-retry/__tests__/submitted-draft.test.js +334 -0
  276. package/dist/components/forms/form-retry/content-digest.d.ts +54 -0
  277. package/dist/components/forms/form-retry/content-digest.d.ts.map +1 -0
  278. package/dist/components/forms/form-retry/content-digest.js +169 -0
  279. package/dist/components/forms/form-retry/controller.d.ts +214 -0
  280. package/dist/components/forms/form-retry/controller.d.ts.map +1 -0
  281. package/dist/components/forms/form-retry/controller.js +404 -0
  282. package/dist/components/forms/form-retry/form-draft.d.ts +68 -0
  283. package/dist/components/forms/form-retry/form-draft.d.ts.map +1 -0
  284. package/dist/components/forms/form-retry/form-draft.js +161 -0
  285. package/dist/components/forms/form-retry/index.d.ts +19 -0
  286. package/dist/components/forms/form-retry/index.d.ts.map +1 -0
  287. package/dist/components/forms/form-retry/index.js +16 -0
  288. package/dist/components/forms/form-retry/submission-key.d.ts +244 -0
  289. package/dist/components/forms/form-retry/submission-key.d.ts.map +1 -0
  290. package/dist/components/forms/form-retry/submission-key.js +342 -0
  291. package/dist/components/forms/form-retry/submitted-draft.d.ts +112 -0
  292. package/dist/components/forms/form-retry/submitted-draft.d.ts.map +1 -0
  293. package/dist/components/forms/form-retry/submitted-draft.js +270 -0
  294. package/dist/components/forms/form-retry/types.d.ts +84 -0
  295. package/dist/components/forms/form-retry/types.d.ts.map +1 -0
  296. package/dist/components/forms/form-retry/types.js +13 -0
  297. package/dist/components/forms/index.d.ts +21 -2
  298. package/dist/components/forms/index.d.ts.map +1 -1
  299. package/dist/components/forms/index.js +22 -1
  300. package/dist/components/forms/insert-text.d.ts +12 -0
  301. package/dist/components/forms/insert-text.d.ts.map +1 -0
  302. package/dist/components/forms/insert-text.js +38 -0
  303. package/dist/components/forms/long-press.d.ts +88 -0
  304. package/dist/components/forms/long-press.d.ts.map +1 -0
  305. package/dist/components/forms/long-press.js +213 -0
  306. package/dist/components/forms/native-file-field.d.ts +94 -0
  307. package/dist/components/forms/native-file-field.d.ts.map +1 -0
  308. package/dist/components/forms/native-file-field.js +147 -0
  309. package/dist/components/forms/ready-beep.d.ts +24 -0
  310. package/dist/components/forms/ready-beep.d.ts.map +1 -0
  311. package/dist/components/forms/ready-beep.js +82 -0
  312. package/dist/components/forms/signature-pad-logic.d.ts +50 -0
  313. package/dist/components/forms/signature-pad-logic.d.ts.map +1 -0
  314. package/dist/components/forms/signature-pad-logic.js +48 -0
  315. package/dist/components/forms/types.d.ts +41 -0
  316. package/dist/components/forms/types.d.ts.map +1 -1
  317. package/dist/components/layout/PageHeader.svelte +151 -17
  318. package/dist/components/layout/PageHeader.svelte.d.ts +47 -7
  319. package/dist/components/layout/PageHeader.svelte.d.ts.map +1 -1
  320. package/dist/components/layout/__tests__/PageHeader.test.js +87 -1
  321. package/dist/components/layout/index.d.ts +1 -0
  322. package/dist/components/layout/index.d.ts.map +1 -1
  323. package/dist/components/layout/index.js +1 -0
  324. package/dist/components/layout/page-header-context.d.ts +25 -0
  325. package/dist/components/layout/page-header-context.d.ts.map +1 -0
  326. package/dist/components/layout/page-header-context.js +16 -0
  327. package/dist/components/nav/FilterChips.svelte +8 -1
  328. package/dist/components/nav/FilterChips.svelte.d.ts +2 -0
  329. package/dist/components/nav/FilterChips.svelte.d.ts.map +1 -1
  330. package/dist/components/nav/Tabs.svelte +241 -0
  331. package/dist/components/nav/Tabs.svelte.d.ts +15 -0
  332. package/dist/components/nav/Tabs.svelte.d.ts.map +1 -1
  333. package/dist/components/nav/__tests__/LinkTabs.test.js +117 -0
  334. package/dist/components/nav/index.d.ts +1 -0
  335. package/dist/components/nav/index.d.ts.map +1 -1
  336. package/dist/components/nav/index.js +1 -0
  337. package/dist/components/nav/tabs-overflow.d.ts +12 -0
  338. package/dist/components/nav/tabs-overflow.d.ts.map +1 -0
  339. package/dist/components/nav/tabs-overflow.js +17 -0
  340. package/dist/components/nav/types.d.ts +8 -0
  341. package/dist/components/nav/types.d.ts.map +1 -1
  342. package/dist/components/ui/Button.svelte +16 -2
  343. package/dist/components/ui/Button.svelte.d.ts +2 -0
  344. package/dist/components/ui/Button.svelte.d.ts.map +1 -1
  345. package/dist/components/ui/Card.svelte +14 -5
  346. package/dist/components/ui/Dropdown.svelte +55 -1
  347. package/dist/components/ui/Dropdown.svelte.d.ts +8 -0
  348. package/dist/components/ui/Dropdown.svelte.d.ts.map +1 -1
  349. package/dist/components/ui/IconToggle.svelte +139 -0
  350. package/dist/components/ui/IconToggle.svelte.d.ts +32 -0
  351. package/dist/components/ui/IconToggle.svelte.d.ts.map +1 -0
  352. package/dist/components/ui/IconToggleGroup.svelte +56 -0
  353. package/dist/components/ui/IconToggleGroup.svelte.d.ts +21 -0
  354. package/dist/components/ui/IconToggleGroup.svelte.d.ts.map +1 -0
  355. package/dist/components/ui/Pagination.svelte +1 -1
  356. package/dist/components/ui/Popover.svelte +17 -1
  357. package/dist/components/ui/Popover.svelte.d.ts +8 -0
  358. package/dist/components/ui/Popover.svelte.d.ts.map +1 -1
  359. package/dist/components/ui/__tests__/IconToggle.test.js +59 -0
  360. package/dist/components/ui/__tests__/IconToggleGroup.test.js +30 -0
  361. package/dist/components/ui/__tests__/Popover.test.js +44 -0
  362. package/dist/components/ui/__tests__/dropdown-popover-icon.test.js +125 -0
  363. package/dist/components/ui/__tests__/phone-touch-targets.test.js +39 -0
  364. package/dist/components/ui/index.d.ts +2 -0
  365. package/dist/components/ui/index.d.ts.map +1 -1
  366. package/dist/components/ui/index.js +2 -0
  367. package/dist/i18n/strings.ui.d.ts +65 -0
  368. package/dist/i18n/strings.ui.d.ts.map +1 -1
  369. package/dist/i18n/strings.ui.js +72 -0
  370. package/dist/styles/tokens.css +2 -0
  371. package/dist/svelte/__tests__/playground.test.js +3 -1
  372. package/dist/svelte/playground/CalendarPreview.svelte +140 -0
  373. package/dist/svelte/playground/CalendarPreview.svelte.d.ts +4 -0
  374. package/dist/svelte/playground/CalendarPreview.svelte.d.ts.map +1 -0
  375. package/dist/svelte/playground/CapturePreview.svelte +56 -0
  376. package/dist/svelte/playground/CapturePreview.svelte.d.ts +4 -0
  377. package/dist/svelte/playground/CapturePreview.svelte.d.ts.map +1 -0
  378. package/dist/svelte/playground.d.ts.map +1 -1
  379. package/dist/svelte/playground.js +20 -0
  380. package/dist/themes/ThemeProvider.svelte +9 -0
  381. package/dist/themes/ThemeProvider.svelte.d.ts +2 -0
  382. package/dist/themes/ThemeProvider.svelte.d.ts.map +1 -1
  383. package/dist/themes/css-generator.d.ts.map +1 -1
  384. package/dist/themes/css-generator.js +3 -0
  385. package/dist/themes/styles/glass.css +4 -0
  386. package/dist/themes/styles/happyvertical.css +4 -0
  387. package/dist/themes/styles/material.css +4 -0
  388. package/dist/themes/styles/smrt.css +4 -0
  389. package/dist/themes/styles/studio.css +4 -0
  390. package/dist/types-generic.d.ts +2 -0
  391. package/dist/types-generic.d.ts.map +1 -1
  392. package/package.json +9 -3
@@ -0,0 +1,73 @@
1
+ /**
2
+ * A multi-step flow (a wizard, a setup checklist) as a mounted data surface,
3
+ * so an agent can see where a person is and move the flow forward.
4
+ *
5
+ * The published state lists the steps (`state.steps`: id, label, status) and
6
+ * the current one. Three controls move between them:
7
+ *
8
+ * - `next` — advance from the current step. A step whose forward button only
9
+ * checks input and shows the next step runs the page's `next` handler, the
10
+ * same function the button calls. A step whose forward button SAVES or
11
+ * CREATES something (`nextWrites`) is never pressed by an agent: `next`
12
+ * reveals and highlights that button instead, and publishes
13
+ * `awaitingPerson: true` until the page moves on. People apply writes.
14
+ * - `back` — return to the previous step (never a write).
15
+ * - `go-to` — jump to a step the page marks `available` (payload
16
+ * `{ target }`: a step id or label).
17
+ *
18
+ * A handler that returns `false` (validation failed) refuses the command, so
19
+ * the agent sees the step did not change and can read the form's errors.
20
+ */
21
+ import type { DataSurfaceDescriptor, DataSurfaceJsonValue, DataSurfaceRegistry, DataSurfaceSubject } from '@happyvertical/smrt-types';
22
+ export interface StepSurfaceStep {
23
+ id: string;
24
+ /** Plain label a person sees in the progress row. */
25
+ label: string;
26
+ description?: string;
27
+ /** The step's work is done. */
28
+ complete?: boolean;
29
+ /** `go-to` may jump here (default: complete steps and the current one). */
30
+ available?: boolean;
31
+ }
32
+ type StepHandler = () => boolean | undefined | Promise<boolean | undefined>;
33
+ export interface StepSurfaceOptions {
34
+ registry: DataSurfaceRegistry;
35
+ surfaceId: string;
36
+ subject?: DataSurfaceSubject;
37
+ label: string;
38
+ description: string;
39
+ steps: readonly StepSurfaceStep[];
40
+ /** Id of the step on screen. */
41
+ current: string;
42
+ /**
43
+ * The forward action of the current step, when it does not write — the
44
+ * same function its Continue button calls. Return `false` to refuse.
45
+ */
46
+ next?: StepHandler;
47
+ /**
48
+ * The current step's forward button saves or creates something. An agent's
49
+ * `next` then only reveals the button (see {@link StepSurfaceOptions.showNext}).
50
+ */
51
+ nextWrites?: boolean;
52
+ /** Reveal and highlight the current step's forward button for the person. */
53
+ showNext?: () => void;
54
+ /** Return to the previous step. Return `false` to refuse. */
55
+ back?: StepHandler;
56
+ /** Jump to a step. Return `false` to refuse. */
57
+ goTo?: (stepId: string) => boolean | undefined | Promise<boolean | undefined>;
58
+ /** Extra JSON state published alongside the steps. */
59
+ state?: Record<string, DataSurfaceJsonValue>;
60
+ }
61
+ export type StepSurfaceUpdate = Partial<Pick<StepSurfaceOptions, 'steps' | 'current' | 'next' | 'nextWrites' | 'showNext' | 'back' | 'goTo' | 'state'>>;
62
+ export interface StepSurfaceHandle {
63
+ update(next: StepSurfaceUpdate): void;
64
+ destroy(): void;
65
+ }
66
+ /** Resolve a `go-to` payload to a step id (id, exact label, unique prefix). */
67
+ export declare function resolveStepTarget(payload: DataSurfaceJsonValue | undefined, steps: readonly StepSurfaceStep[]): string | null;
68
+ /** The descriptor {@link registerStepSurface} mounts. */
69
+ export declare function stepSurfaceDescriptor(options: Pick<StepSurfaceOptions, 'surfaceId' | 'subject' | 'label' | 'description'>): DataSurfaceDescriptor;
70
+ /** Mount a multi-step flow on a data-surface registry. */
71
+ export declare function registerStepSurface(options: StepSurfaceOptions): StepSurfaceHandle;
72
+ export {};
73
+ //# sourceMappingURL=step-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-surface.d.ts","sourceRoot":"","sources":["../../../src/components/data/step-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAEnB,MAAM,2BAA2B,CAAC;AAGnC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,KAAK,WAAW,GAAG,MAAM,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;AAE5E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAClC,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,gDAAgD;IAChD,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IAC9E,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CAC9C;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CACrC,IAAI,CACF,kBAAkB,EAChB,OAAO,GACP,SAAS,GACT,MAAM,GACN,YAAY,GACZ,UAAU,GACV,MAAM,GACN,MAAM,GACN,OAAO,CACV,CACF,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,OAAO,IAAI,IAAI,CAAC;CACjB;AAUD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,KAAK,EAAE,SAAS,eAAe,EAAE,GAChC,MAAM,GAAG,IAAI,CAaf;AAED,yDAAyD;AACzD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,IAAI,CACX,kBAAkB,EAClB,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAClD,GACA,qBAAqB,CA2CvB;AAED,0DAA0D;AAC1D,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,kBAAkB,GAC1B,iBAAiB,CA6FnB"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * A multi-step flow (a wizard, a setup checklist) as a mounted data surface,
3
+ * so an agent can see where a person is and move the flow forward.
4
+ *
5
+ * The published state lists the steps (`state.steps`: id, label, status) and
6
+ * the current one. Three controls move between them:
7
+ *
8
+ * - `next` — advance from the current step. A step whose forward button only
9
+ * checks input and shows the next step runs the page's `next` handler, the
10
+ * same function the button calls. A step whose forward button SAVES or
11
+ * CREATES something (`nextWrites`) is never pressed by an agent: `next`
12
+ * reveals and highlights that button instead, and publishes
13
+ * `awaitingPerson: true` until the page moves on. People apply writes.
14
+ * - `back` — return to the previous step (never a write).
15
+ * - `go-to` — jump to a step the page marks `available` (payload
16
+ * `{ target }`: a step id or label).
17
+ *
18
+ * A handler that returns `false` (validation failed) refuses the command, so
19
+ * the agent sees the step did not change and can read the form's errors.
20
+ */
21
+ import { linkTargetFromPayload } from './link-surface.js';
22
+ function normalize(value) {
23
+ return value.trim().toLowerCase().replace(/\s+/g, ' ');
24
+ }
25
+ function stepAvailable(step, current) {
26
+ return step.available ?? (step.complete === true || step.id === current);
27
+ }
28
+ /** Resolve a `go-to` payload to a step id (id, exact label, unique prefix). */
29
+ export function resolveStepTarget(payload, steps) {
30
+ const target = linkTargetFromPayload(payload);
31
+ if (!target)
32
+ return null;
33
+ const wanted = normalize(target);
34
+ const byId = steps.find((step) => normalize(step.id) === wanted);
35
+ if (byId)
36
+ return byId.id;
37
+ const byLabel = steps.filter((step) => normalize(step.label) === wanted);
38
+ if (byLabel.length === 1)
39
+ return byLabel[0].id;
40
+ if (byLabel.length > 1)
41
+ return null;
42
+ const byPrefix = steps.filter((step) => normalize(step.label).startsWith(wanted));
43
+ return byPrefix.length === 1 ? byPrefix[0].id : null;
44
+ }
45
+ /** The descriptor {@link registerStepSurface} mounts. */
46
+ export function stepSurfaceDescriptor(options) {
47
+ const columns = [
48
+ { id: 'id', label: 'ID', capabilities: ['read'], role: 'row-key' },
49
+ { id: 'label', label: 'Step', capabilities: ['read'] },
50
+ { id: 'status', label: 'Status', capabilities: ['read'], role: 'status' },
51
+ { id: 'description', label: 'About', capabilities: ['read'] },
52
+ ];
53
+ return {
54
+ version: 1,
55
+ identity: {
56
+ kind: 'custom',
57
+ surfaceId: options.surfaceId,
58
+ ...(options.subject ? { subject: options.subject } : {}),
59
+ },
60
+ schemaVersion: 1,
61
+ label: options.label,
62
+ description: options.description,
63
+ rowKey: 'id',
64
+ columns,
65
+ query: {
66
+ modes: ['rows'],
67
+ projectableColumnIds: columns.map((column) => column.id),
68
+ filterableColumnIds: [],
69
+ sortableColumnIds: [],
70
+ },
71
+ controls: [
72
+ {
73
+ id: 'next',
74
+ label: 'Next step',
75
+ description: 'Continue from the current step. When the step saves or creates something (state.nextWrites), this only shows the person the button to press.',
76
+ },
77
+ { id: 'back', label: 'Previous step' },
78
+ {
79
+ id: 'go-to',
80
+ label: 'Go to step',
81
+ description: 'Jump to an available step. Payload: { target } — a step id or label.',
82
+ },
83
+ ],
84
+ actions: [],
85
+ limits: { maxQueryRows: 50, maxQueryBytes: 100_000, maxSelectionSize: 1 },
86
+ };
87
+ }
88
+ /** Mount a multi-step flow on a data-surface registry. */
89
+ export function registerStepSurface(options) {
90
+ let current = { ...options };
91
+ let awaitingPerson = false;
92
+ let revision = 1;
93
+ const publishedState = () => {
94
+ const index = current.steps.findIndex((step) => step.id === current.current);
95
+ return {
96
+ ...(current.state ?? {}),
97
+ current: current.current,
98
+ currentLabel: current.steps[index]?.label ?? null,
99
+ stepNumber: index + 1,
100
+ stepCount: current.steps.length,
101
+ nextWrites: current.nextWrites === true,
102
+ awaitingPerson,
103
+ steps: current.steps.map((step) => ({
104
+ id: step.id,
105
+ label: step.label,
106
+ ...(step.description ? { description: step.description } : {}),
107
+ status: step.id === current.current
108
+ ? 'current'
109
+ : step.complete
110
+ ? 'complete'
111
+ : stepAvailable(step, current.current)
112
+ ? 'available'
113
+ : 'upcoming',
114
+ })),
115
+ };
116
+ };
117
+ let signature = JSON.stringify(publishedState());
118
+ const publish = () => {
119
+ const next = JSON.stringify(publishedState());
120
+ if (next !== signature) {
121
+ signature = next;
122
+ revision += 1;
123
+ }
124
+ };
125
+ const run = async (handler) => {
126
+ if (!handler)
127
+ return { ok: false };
128
+ const result = await handler();
129
+ return result === false ? { ok: false } : undefined;
130
+ };
131
+ const dispose = options.registry.register({
132
+ descriptor: stepSurfaceDescriptor(options),
133
+ getSnapshot: () => ({ revision, state: publishedState(), selection: null }),
134
+ execute: async (command) => {
135
+ switch (command.controlId) {
136
+ case 'next': {
137
+ if (current.nextWrites) {
138
+ if (!current.showNext)
139
+ return { ok: false };
140
+ current.showNext();
141
+ awaitingPerson = true;
142
+ publish();
143
+ return undefined;
144
+ }
145
+ return run(current.next);
146
+ }
147
+ case 'back':
148
+ return run(current.back);
149
+ case 'go-to': {
150
+ const stepId = resolveStepTarget(command.payload, current.steps);
151
+ const step = current.steps.find((item) => item.id === stepId);
152
+ if (!step || !current.goTo)
153
+ return { ok: false };
154
+ if (!stepAvailable(step, current.current))
155
+ return { ok: false };
156
+ const goTo = current.goTo;
157
+ return run(() => goTo(step.id));
158
+ }
159
+ default:
160
+ return { ok: false };
161
+ }
162
+ },
163
+ });
164
+ return {
165
+ update(next) {
166
+ const moved = next.current !== undefined && next.current !== current.current;
167
+ current = { ...current, ...next };
168
+ // The person pressed the button (or the flow moved another way).
169
+ if (moved || next.nextWrites === false)
170
+ awaitingPerson = false;
171
+ publish();
172
+ },
173
+ destroy() {
174
+ dispose();
175
+ },
176
+ };
177
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * "Has the page settled after that command?"
3
+ *
4
+ * A visible command on a navigation surface (a link list, a tab row) starts a
5
+ * page change and returns at once: awaiting it inside the command would make
6
+ * the registry report `not_found` whenever the new page unmounts the surface
7
+ * that ran it. The navigation's promise is tracked here instead, keyed by the
8
+ * registry the command ran on, so whoever drives the page next — an in-page
9
+ * assistant about to show the model the page's tools, a test — can wait for
10
+ * it to finish and for the new page's surfaces to register:
11
+ *
12
+ * ```ts
13
+ * await registry.execute(openEventsCommand);
14
+ * await whenSurfaceNavigationSettled(registry); // new page mounted and quiet
15
+ * ```
16
+ *
17
+ * `registerLinkSurface` tracks its own `navigate` result. A bespoke surface
18
+ * whose command navigates calls {@link trackSurfaceNavigation} itself.
19
+ */
20
+ import type { DataSurfaceRegistry } from '@happyvertical/smrt-types';
21
+ /**
22
+ * Record a navigation a command on `registry` started. Returns the same
23
+ * promise. A rejection is swallowed for waiting purposes (a failed navigation
24
+ * is still a finished one); the caller keeps its own handling.
25
+ */
26
+ export declare function trackSurfaceNavigation<T>(registry: DataSurfaceRegistry, navigation: T | Promise<T>): T | Promise<T>;
27
+ /** Whether a tracked navigation on `registry` is still running. */
28
+ export declare function hasPendingSurfaceNavigation(registry: DataSurfaceRegistry): boolean;
29
+ export interface SurfaceNavigationSettleOptions {
30
+ /**
31
+ * How long the registry must go without a surface registering or
32
+ * unregistering before the page counts as settled. Default 120 ms.
33
+ */
34
+ quietMs?: number;
35
+ /** Give up waiting after this long. Default 5000 ms. */
36
+ timeoutMs?: number;
37
+ /** Extra sources whose changes also reset the quiet timer (e.g. page tools). */
38
+ alsoWatch?: ReadonlyArray<{
39
+ subscribe?: (listener: (event: unknown) => void) => () => void;
40
+ } | null | undefined>;
41
+ signal?: AbortSignal;
42
+ }
43
+ /**
44
+ * Resolve once every navigation tracked on `registry` has finished AND the
45
+ * registry (plus `alsoWatch` sources) has been quiet for `quietMs`, or after
46
+ * `timeoutMs`, whichever comes first. Never rejects.
47
+ */
48
+ export declare function whenSurfaceNavigationSettled(registry: DataSurfaceRegistry, options?: SurfaceNavigationSettleOptions): Promise<void>;
49
+ //# sourceMappingURL=surface-navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-navigation.d.ts","sourceRoot":"","sources":["../../../src/components/data/surface-navigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAIrE;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,QAAQ,EAAE,mBAAmB,EAC7B,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACzB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBhB;AAED,mEAAmE;AACnE,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAET;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,aAAa,CACrB;QAAE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;KAAE,GAClE,IAAI,GACJ,SAAS,CACZ,CAAC;IACF,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,GAAE,8BAAmC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAiDf"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * "Has the page settled after that command?"
3
+ *
4
+ * A visible command on a navigation surface (a link list, a tab row) starts a
5
+ * page change and returns at once: awaiting it inside the command would make
6
+ * the registry report `not_found` whenever the new page unmounts the surface
7
+ * that ran it. The navigation's promise is tracked here instead, keyed by the
8
+ * registry the command ran on, so whoever drives the page next — an in-page
9
+ * assistant about to show the model the page's tools, a test — can wait for
10
+ * it to finish and for the new page's surfaces to register:
11
+ *
12
+ * ```ts
13
+ * await registry.execute(openEventsCommand);
14
+ * await whenSurfaceNavigationSettled(registry); // new page mounted and quiet
15
+ * ```
16
+ *
17
+ * `registerLinkSurface` tracks its own `navigate` result. A bespoke surface
18
+ * whose command navigates calls {@link trackSurfaceNavigation} itself.
19
+ */
20
+ const pending = new WeakMap();
21
+ /**
22
+ * Record a navigation a command on `registry` started. Returns the same
23
+ * promise. A rejection is swallowed for waiting purposes (a failed navigation
24
+ * is still a finished one); the caller keeps its own handling.
25
+ */
26
+ export function trackSurfaceNavigation(registry, navigation) {
27
+ if (!navigation || typeof navigation.then !== 'function') {
28
+ return navigation;
29
+ }
30
+ const promise = Promise.resolve(navigation);
31
+ let set = pending.get(registry);
32
+ if (!set) {
33
+ set = new Set();
34
+ pending.set(registry, set);
35
+ }
36
+ const entry = promise.then(() => undefined, () => undefined);
37
+ set.add(entry);
38
+ void entry.then(() => set?.delete(entry));
39
+ return promise;
40
+ }
41
+ /** Whether a tracked navigation on `registry` is still running. */
42
+ export function hasPendingSurfaceNavigation(registry) {
43
+ return (pending.get(registry)?.size ?? 0) > 0;
44
+ }
45
+ /**
46
+ * Resolve once every navigation tracked on `registry` has finished AND the
47
+ * registry (plus `alsoWatch` sources) has been quiet for `quietMs`, or after
48
+ * `timeoutMs`, whichever comes first. Never rejects.
49
+ */
50
+ export async function whenSurfaceNavigationSettled(registry, options = {}) {
51
+ const quietMs = Math.max(0, options.quietMs ?? 120);
52
+ const timeoutMs = Math.max(0, options.timeoutMs ?? 5_000);
53
+ const started = Date.now();
54
+ const remaining = () => Math.max(0, timeoutMs - (Date.now() - started));
55
+ const timeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
56
+ // 1. Tracked navigations (a navigation may start another, so loop).
57
+ for (;;) {
58
+ const set = pending.get(registry);
59
+ if (!set || set.size === 0 || options.signal?.aborted)
60
+ break;
61
+ const left = remaining();
62
+ if (left === 0)
63
+ return;
64
+ await Promise.race([Promise.all([...set]), timeout(left)]);
65
+ }
66
+ if (options.signal?.aborted || remaining() === 0)
67
+ return;
68
+ // 2. Quiet period: new page components register their surfaces and tools.
69
+ await new Promise((resolve) => {
70
+ let quietTimer = null;
71
+ const unsubscribers = [];
72
+ const finish = () => {
73
+ if (quietTimer)
74
+ clearTimeout(quietTimer);
75
+ clearTimeout(hardTimer);
76
+ for (const unsubscribe of unsubscribers)
77
+ unsubscribe();
78
+ options.signal?.removeEventListener('abort', finish);
79
+ resolve();
80
+ };
81
+ const restart = () => {
82
+ if (quietTimer)
83
+ clearTimeout(quietTimer);
84
+ quietTimer = setTimeout(finish, quietMs);
85
+ };
86
+ const hardTimer = setTimeout(finish, remaining());
87
+ options.signal?.addEventListener('abort', finish, { once: true });
88
+ unsubscribers.push(registry.subscribe((event) => {
89
+ if (event.type === 'registered' || event.type === 'unregistered') {
90
+ restart();
91
+ }
92
+ }));
93
+ for (const source of options.alsoWatch ?? []) {
94
+ const unsubscribe = source?.subscribe?.(() => restart());
95
+ if (unsubscribe)
96
+ unsubscribers.push(unsubscribe);
97
+ }
98
+ restart();
99
+ });
100
+ }
@@ -95,6 +95,12 @@ export interface DataTableColumn<T> {
95
95
  headerSortMode?: 'automatic' | 'manual';
96
96
  /** Whether column is sortable */
97
97
  sortable?: boolean;
98
+ /**
99
+ * Direction applied on the first activation of this column's header
100
+ * (default `asc`). Use `desc` for dates and counts so one click shows the
101
+ * newest / largest first.
102
+ */
103
+ sortFirstDirection?: SortDirection;
98
104
  /** Column width (CSS value) */
99
105
  width?: string;
100
106
  /** Minimum width (CSS value) */
@@ -139,6 +145,14 @@ export interface SortState {
139
145
  * DataTable props
140
146
  */
141
147
  export interface DataTableProps<T> {
148
+ /** Sort-control target density; omit to inherit ThemeProvider. */
149
+ density?: 'comfortable' | 'touch';
150
+ /** Opt-in container-width column collapse; default keeps horizontal scrolling. */
151
+ responsiveMode?: 'scroll' | 'hide-columns';
152
+ /** Container-width threshold in pixels for narrow mode (default 800). */
153
+ responsiveBreakpoint?: number;
154
+ /** Target width per retained column in narrow mode (default 160 pixels). */
155
+ responsiveColumnMinWidth?: number;
142
156
  /** Data rows */
143
157
  data: T[];
144
158
  /** Column definitions */
@@ -169,6 +183,12 @@ export interface DataTableProps<T> {
169
183
  sort?: SortState;
170
184
  /** Sort change callback */
171
185
  onSortChange?: (sort: SortState) => void;
186
+ /**
187
+ * Whether a third activation of a sorted header clears the sort
188
+ * (asc → desc → none; the default). `false` toggles asc ⇄ desc so the list
189
+ * always keeps one defined order.
190
+ */
191
+ sortClearable?: boolean;
172
192
  /** Parent owns sorting and supplies already-sorted rows. */
173
193
  manualSorting?: boolean;
174
194
  /** Optional client-side row filter. */
@@ -251,6 +271,13 @@ export interface DataTableProps<T> {
251
271
  hoverable?: boolean;
252
272
  /** Enable sticky header */
253
273
  stickyHeader?: boolean;
274
+ /**
275
+ * How the table looks on phones (48rem and under): `scroll` keeps the table
276
+ * (scrolling sideways when it is wider than the screen), `cards` makes each
277
+ * row its own block of stacked cells and hides the column heads, so give the
278
+ * page another way to sort (a `ListSortSelect`).
279
+ */
280
+ phoneLayout?: 'scroll' | 'cards';
254
281
  /** Table caption for accessibility */
255
282
  caption?: string;
256
283
  /** Dense mode (reduced padding) */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/data/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/data/types.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,8 @@ export interface Props {
17
17
  showTime?: boolean;
18
18
  /** Locale for formatting (defaults to en-CA) */
19
19
  locale?: string;
20
+ /** IANA zone for timestamps and relative calendar-day boundaries. */
21
+ timeZone?: string;
20
22
  /** Optional CSS class */
21
23
  class?: string;
22
24
  }
@@ -27,15 +29,22 @@ const {
27
29
  fallback = 'N/A',
28
30
  showTime = false,
29
31
  locale = 'en-CA',
32
+ timeZone,
30
33
  class: className = '',
31
34
  }: Props = $props();
32
35
 
33
- // Parse the date
36
+ const isCalendarDate = $derived(
37
+ typeof date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(date),
38
+ );
39
+
40
+ // Bare dates denote a calendar day, never a browser-local instant.
34
41
  const parsedDate = $derived.by(() => {
35
42
  if (date === null || date === undefined) return null;
36
- if (date instanceof Date) return date;
43
+ if (date instanceof Date) return Number.isNaN(date.getTime()) ? null : date;
37
44
  const d = new Date(date);
38
- return Number.isNaN(d.getTime()) ? null : d;
45
+ if (Number.isNaN(d.getTime())) return null;
46
+ if (isCalendarDate && d.toISOString().slice(0, 10) !== date) return null;
47
+ return d;
39
48
  });
40
49
 
41
50
  // Format options for Intl.DateTimeFormat
@@ -45,8 +54,52 @@ const dateOptions: Record<string, Intl.DateTimeFormatOptions> = {
45
54
  long: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' },
46
55
  };
47
56
 
48
- // Format relative time
57
+ // Convert zone-local Gregorian dates to ordinals so DST does not alter day counts.
58
+ function calendarDay(d: Date, zone?: string): number {
59
+ const parts = new Intl.DateTimeFormat('en-US', {
60
+ timeZone: zone,
61
+ year: 'numeric',
62
+ month: 'numeric',
63
+ day: 'numeric',
64
+ }).formatToParts(d);
65
+ const part = (type: string) =>
66
+ Number(parts.find((entry) => entry.type === type)?.value);
67
+ const midnight = new Date(0);
68
+ midnight.setUTCFullYear(part('year'), part('month') - 1, part('day'));
69
+ return midnight.getTime() / 86400000;
70
+ }
71
+
72
+ function formatCalendarRelative(d: Date): string {
73
+ const now = new Date();
74
+ const days =
75
+ calendarDay(now, timeZone) -
76
+ (isCalendarDate ? d.getTime() / 86400000 : calendarDay(d, timeZone));
77
+ if (days === 0) {
78
+ if (isCalendarDate || d > now) return 'today';
79
+ const minutes = Math.floor((now.getTime() - d.getTime()) / 60000);
80
+ if (minutes === 0) return 'just now';
81
+ return minutes < 60
82
+ ? `${minutes}m ago`
83
+ : `${Math.floor(minutes / 60)}h ago`;
84
+ }
85
+ if (days === 1) return 'yesterday';
86
+ if (days === -1) return 'tomorrow';
87
+ const count = Math.abs(days);
88
+ const [amount, unit] =
89
+ count < 7
90
+ ? [count, 'days']
91
+ : count < 30
92
+ ? [Math.floor(count / 7), 'weeks']
93
+ : count < 365
94
+ ? [Math.floor(count / 30), 'months']
95
+ : [Math.floor(count / 365), 'years'];
96
+ return days < 0 ? `in ${amount} ${unit}` : `${amount} ${unit} ago`;
97
+ }
98
+
99
+ // Preserve duration-based relative defaults for instant inputs without a zone.
49
100
  function formatRelative(d: Date): string {
101
+ if (timeZone !== undefined || isCalendarDate)
102
+ return formatCalendarRelative(d);
50
103
  const now = new Date();
51
104
  const diffMs = now.getTime() - d.getTime();
52
105
  const diffSec = Math.floor(diffMs / 1000);
@@ -83,21 +136,30 @@ function formatRelative(d: Date): string {
83
136
  const formatted = $derived.by(() => {
84
137
  if (!parsedDate) return fallback;
85
138
 
86
- if (format === 'relative') {
87
- return formatRelative(parsedDate);
88
- }
139
+ try {
140
+ if (format === 'relative') return formatRelative(parsedDate);
89
141
 
90
- const options = { ...dateOptions[format] };
91
- if (showTime) {
92
- options.hour = 'numeric';
93
- options.minute = '2-digit';
142
+ const options = {
143
+ ...dateOptions[format],
144
+ timeZone: isCalendarDate ? 'UTC' : timeZone,
145
+ };
146
+ if (showTime && !isCalendarDate) {
147
+ options.hour = 'numeric';
148
+ options.minute = '2-digit';
149
+ }
150
+ return new Intl.DateTimeFormat(locale, options).format(parsedDate);
151
+ } catch (error) {
152
+ if (error instanceof RangeError) return fallback;
153
+ throw error;
94
154
  }
95
-
96
- return new Intl.DateTimeFormat(locale, options).format(parsedDate);
97
155
  });
98
156
 
99
157
  // ISO string for datetime attribute
100
- const isoString = $derived(parsedDate?.toISOString() ?? '');
158
+ const isoString = $derived(
159
+ isCalendarDate && parsedDate
160
+ ? String(date)
161
+ : (parsedDate?.toISOString() ?? ''),
162
+ );
101
163
  </script>
102
164
 
103
165
  {#if parsedDate}
@@ -15,6 +15,8 @@ export interface Props {
15
15
  showTime?: boolean;
16
16
  /** Locale for formatting (defaults to en-CA) */
17
17
  locale?: string;
18
+ /** IANA zone for timestamps and relative calendar-day boundaries. */
19
+ timeZone?: string;
18
20
  /** Optional CSS class */
19
21
  class?: string;
20
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DateDisplay.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/display/DateDisplay.svelte.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,sCAAsC;AACtC,MAAM,WAAW,KAAK;IACpB,uDAAuD;IACvD,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD,qBAAqB;IACrB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiGD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"DateDisplay.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/display/DateDisplay.svelte.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,sCAAsC;AACtC,MAAM,WAAW,KAAK;IACpB,uDAAuD;IACvD,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD,qBAAqB;IACrB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6JD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}