@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
@@ -3,7 +3,11 @@ export interface Props {
3
3
  /** Toaster instance that manages the toast queue. */
4
4
  toaster?: Toaster;
5
5
  /** Screen corner where toasts appear. */
6
- position?: 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';
6
+ position?: 'top-start' | 'top-center' | 'top-end' | 'bottom-start' | 'bottom-center' | 'bottom-end';
7
+ /** CSS length inset from the window or anchor region. */
8
+ inset?: string;
9
+ /** Optional content region used for toast placement. */
10
+ anchor?: HTMLElement | null;
7
11
  /** CSS class to apply to the viewport container. */
8
12
  class?: string;
9
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ToastViewport.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/ToastViewport.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,KAAK;IACpB,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,cAAc,GAAG,YAAY,CAAC;IACnE,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmCD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"ToastViewport.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/ToastViewport.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,KAAK;IACpB,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yCAAyC;IACzC,QAAQ,CAAC,EACL,WAAW,GACX,YAAY,GACZ,SAAS,GACT,cAAc,GACd,eAAe,GACf,YAAY,CAAC;IACjB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8JD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -0,0 +1,426 @@
1
+ <script lang="ts">
2
+ /**
3
+ * WorkingStrip — "something is working" status.
4
+ *
5
+ * - `variant="strip"`: a thin bar (place it above a phone bottom bar); with
6
+ * `onopen` the whole strip is a button that reopens the surface doing the
7
+ * work (e.g. an assistant sheet);
8
+ * - `variant="floating"`: the same content as a pill the host floats over
9
+ * the page (desktop and tablet), with the goal above the current step;
10
+ * - `variant="inline"`: a compact line at the top of a pane.
11
+ *
12
+ * Phases (see `WorkingStatus`): a spinner while `working`; `paused`;
13
+ * `waiting` (the person is needed, with a prominent Review button); `done`
14
+ * (success colors), `failed` (error colors) and `cancelled`, each with an
15
+ * icon and text, never color alone; nothing while `idle`.
16
+ *
17
+ * Accessibility: two live regions stay mounted. Step changes are announced
18
+ * politely, at most once per `announceIntervalMs`; `waiting` and `failed`
19
+ * are announced assertively. The strip never takes focus by itself. Escape
20
+ * inside it pauses the work when `onpause` is given. Every control is at
21
+ * least 44px (strip and floating).
22
+ */
23
+ import { onDestroy, untrack } from 'svelte';
24
+ import { M } from '../../i18n/strings.ui.js';
25
+ import { useI18n } from '../../i18n/use-i18n.js';
26
+ import {
27
+ WORKING_ASSERTIVE_PHASES,
28
+ type WorkingPhase,
29
+ type WorkingStatus,
30
+ } from './working-status.js';
31
+
32
+ export interface Props {
33
+ /** What is happening. */
34
+ status: WorkingStatus;
35
+ /** `strip` (above a bottom bar), `floating` (a pill), or `inline`. */
36
+ variant?: 'strip' | 'floating' | 'inline';
37
+ /** Show a Stop button while the work runs, is paused, or waits. */
38
+ canStop?: boolean;
39
+ /** Stop the work. */
40
+ onstop?: () => void;
41
+ /** Pause the work (shows Pause while working; Escape pauses too). */
42
+ onpause?: () => void;
43
+ /** Continue paused work (shows Continue while paused). */
44
+ onresume?: () => void;
45
+ /** Open what the work is waiting on (shows Review while waiting). */
46
+ onreview?: () => void;
47
+ /** Reopen the surface doing the work (strip and floating). */
48
+ onopen?: () => void;
49
+ /** Hide a finished status (shows Close once done, failed or cancelled). */
50
+ ondismiss?: () => void;
51
+ /** Accessible hint for `onopen` (default "Open"). */
52
+ openLabel?: string;
53
+ /** Stop button text (default "Stop"). */
54
+ stopLabel?: string;
55
+ /** Pause button text (default "Pause"). */
56
+ pauseLabel?: string;
57
+ /** Continue button text (default "Continue"). */
58
+ resumeLabel?: string;
59
+ /** Review button text (default "Review"). */
60
+ reviewLabel?: string;
61
+ /** Minimum time between two polite step announcements. Default 2000ms. */
62
+ announceIntervalMs?: number;
63
+ }
64
+
65
+ let {
66
+ status,
67
+ variant = 'strip',
68
+ canStop = false,
69
+ onstop,
70
+ onpause,
71
+ onresume,
72
+ onreview,
73
+ onopen,
74
+ ondismiss,
75
+ openLabel,
76
+ stopLabel,
77
+ pauseLabel,
78
+ resumeLabel,
79
+ reviewLabel,
80
+ announceIntervalMs = 2000,
81
+ }: Props = $props();
82
+
83
+ const { t } = useI18n();
84
+
85
+ const DEFAULT_LABEL = {
86
+ working: M['ui.working_strip.working'],
87
+ paused: M['ui.working_strip.paused'],
88
+ waiting: M['ui.working_strip.waiting'],
89
+ done: M['ui.working_strip.done'],
90
+ failed: M['ui.working_strip.failed'],
91
+ cancelled: M['ui.working_strip.cancelled'],
92
+ } satisfies Record<Exclude<WorkingPhase, 'idle'>, unknown>;
93
+
94
+ const phase = $derived(status.phase);
95
+ const visible = $derived(phase !== 'idle');
96
+ const label = $derived(
97
+ phase === 'idle' ? '' : (status.label ?? t(DEFAULT_LABEL[phase])),
98
+ );
99
+ const goal = $derived(status.goal?.trim() || null);
100
+ const assertive = $derived(WORKING_ASSERTIVE_PHASES.includes(phase));
101
+ const terminal = $derived(
102
+ phase === 'done' || phase === 'failed' || phase === 'cancelled',
103
+ );
104
+ const running = $derived(
105
+ phase === 'working' || phase === 'paused' || phase === 'waiting',
106
+ );
107
+ const accessibleSummary = $derived(goal ? `${goal}. ${label}` : label);
108
+
109
+ // Polite announcements, throttled so a fast run does not chatter.
110
+ let politeText = $state('');
111
+ let lastAnnouncedAt = 0;
112
+ let announceTimer: ReturnType<typeof setTimeout> | null = null;
113
+
114
+ function announce(text: string) {
115
+ if (announceTimer) clearTimeout(announceTimer);
116
+ announceTimer = null;
117
+ const wait = Math.max(0, lastAnnouncedAt + announceIntervalMs - Date.now());
118
+ if (wait === 0 || text === '') {
119
+ politeText = text;
120
+ lastAnnouncedAt = text ? Date.now() : lastAnnouncedAt;
121
+ return;
122
+ }
123
+ announceTimer = setTimeout(() => {
124
+ announceTimer = null;
125
+ politeText = text;
126
+ lastAnnouncedAt = Date.now();
127
+ }, wait);
128
+ }
129
+
130
+ $effect(() => {
131
+ const text = visible && !assertive ? label : '';
132
+ untrack(() => announce(text));
133
+ });
134
+
135
+ onDestroy(() => {
136
+ if (announceTimer) clearTimeout(announceTimer);
137
+ });
138
+
139
+ function handleKeydown(event: KeyboardEvent) {
140
+ if (event.key === 'Escape' && phase === 'working' && onpause) {
141
+ event.stopPropagation();
142
+ onpause();
143
+ }
144
+ }
145
+ </script>
146
+
147
+ <div class="working-strip__live" aria-live="polite" aria-atomic="true">
148
+ {politeText}
149
+ </div>
150
+ <div class="working-strip__live" aria-live="assertive" aria-atomic="true">
151
+ {visible && assertive ? accessibleSummary : ''}
152
+ </div>
153
+
154
+ {#if visible}
155
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
156
+ <div
157
+ class="working-strip working-strip--{variant}"
158
+ data-phase={phase}
159
+ data-testid="working-strip"
160
+ onkeydown={handleKeydown}
161
+ >
162
+ {#snippet content()}
163
+ <span class="working-strip__icon" aria-hidden="true">
164
+ {#if phase === 'working'}
165
+ <span class="working-strip__spinner"></span>
166
+ {:else if phase === 'paused'}
167
+ <span class="working-strip__glyph">&#10074;&#10074;</span>
168
+ {:else if phase === 'waiting'}
169
+ <span class="working-strip__glyph">!</span>
170
+ {:else if phase === 'done'}
171
+ <span class="working-strip__glyph">&#10003;</span>
172
+ {:else if phase === 'failed'}
173
+ <span class="working-strip__glyph">&#10005;</span>
174
+ {:else if phase === 'cancelled'}
175
+ <span class="working-strip__glyph">&#9632;</span>
176
+ {/if}
177
+ </span>
178
+ <span class="working-strip__text" aria-hidden="true">
179
+ {#if goal && variant === 'floating'}
180
+ <span class="working-strip__goal">{goal}</span>
181
+ {/if}
182
+ <span class="working-strip__label">{label}</span>
183
+ </span>
184
+ {/snippet}
185
+
186
+ {#if variant !== 'inline' && onopen}
187
+ <button
188
+ type="button"
189
+ class="working-strip__main"
190
+ aria-label={`${accessibleSummary}. ${openLabel ?? t(M['ui.working_strip.open'])}`}
191
+ onclick={onopen}
192
+ >
193
+ {@render content()}
194
+ </button>
195
+ {:else}
196
+ <div class="working-strip__main">
197
+ <span class="working-strip__sr">{accessibleSummary}</span>
198
+ {@render content()}
199
+ </div>
200
+ {/if}
201
+
202
+ <div class="working-strip__actions">
203
+ {#if phase === 'waiting' && onreview}
204
+ <button
205
+ type="button"
206
+ class="working-strip__button working-strip__button--primary"
207
+ onclick={onreview}
208
+ >
209
+ {reviewLabel ?? t(M['ui.working_strip.review'])}
210
+ </button>
211
+ {/if}
212
+ {#if phase === 'working' && onpause}
213
+ <button type="button" class="working-strip__button" onclick={onpause}>
214
+ {pauseLabel ?? t(M['ui.working_strip.pause'])}
215
+ </button>
216
+ {/if}
217
+ {#if phase === 'paused' && onresume}
218
+ <button
219
+ type="button"
220
+ class="working-strip__button working-strip__button--primary"
221
+ onclick={onresume}
222
+ >
223
+ {resumeLabel ?? t(M['ui.working_strip.resume'])}
224
+ </button>
225
+ {/if}
226
+ {#if canStop && running}
227
+ <button type="button" class="working-strip__button" onclick={onstop}>
228
+ {stopLabel ?? t(M['ui.working_strip.stop'])}
229
+ </button>
230
+ {/if}
231
+ {#if terminal && ondismiss}
232
+ <button
233
+ type="button"
234
+ class="working-strip__button working-strip__button--icon"
235
+ aria-label={t(M['ui.working_strip.dismiss'])}
236
+ onclick={ondismiss}
237
+ >
238
+ <span aria-hidden="true">&#10005;</span>
239
+ </button>
240
+ {/if}
241
+ </div>
242
+ </div>
243
+ {/if}
244
+
245
+ <style>
246
+ .working-strip__live,
247
+ .working-strip__sr {
248
+ position: absolute;
249
+ inline-size: 1px;
250
+ block-size: 1px;
251
+ overflow: hidden;
252
+ clip-path: inset(50%);
253
+ white-space: nowrap;
254
+ }
255
+
256
+ .working-strip {
257
+ display: flex;
258
+ align-items: center;
259
+ gap: var(--smrt-spacing-2);
260
+ min-inline-size: 0;
261
+ background: var(--smrt-color-surface-container-high);
262
+ color: var(--smrt-color-on-surface);
263
+ font: var(--smrt-typography-body-medium-font);
264
+ }
265
+
266
+ .working-strip--strip {
267
+ box-sizing: border-box;
268
+ min-block-size: 2.75rem;
269
+ padding-inline-end: var(--smrt-spacing-2);
270
+ border-block-start: 1px solid var(--smrt-color-outline-variant);
271
+ box-shadow: var(--smrt-elevation-2);
272
+ }
273
+
274
+ .working-strip--floating {
275
+ box-sizing: border-box;
276
+ min-block-size: 3.5rem;
277
+ max-inline-size: min(34rem, calc(100vw - 2rem));
278
+ padding-block: var(--smrt-spacing-1);
279
+ padding-inline-end: var(--smrt-spacing-2);
280
+ border: 1px solid var(--smrt-color-outline-variant);
281
+ border-radius: var(--smrt-radius-xl, 1.25rem);
282
+ box-shadow: var(--smrt-elevation-3);
283
+ }
284
+
285
+ .working-strip--inline {
286
+ padding: var(--smrt-spacing-2) var(--smrt-spacing-3);
287
+ border-block-end: 1px solid var(--smrt-color-outline-variant);
288
+ }
289
+
290
+ .working-strip[data-phase='waiting'] {
291
+ background: var(--smrt-color-tertiary-container, var(--smrt-color-primary-container));
292
+ color: var(--smrt-color-on-tertiary-container, var(--smrt-color-on-primary-container));
293
+ }
294
+
295
+ .working-strip[data-phase='done'] {
296
+ background: var(--smrt-color-success-container, var(--smrt-color-primary-container));
297
+ color: var(--smrt-color-on-success-container, var(--smrt-color-on-primary-container));
298
+ }
299
+
300
+ .working-strip[data-phase='failed'] {
301
+ background: var(--smrt-color-error-container);
302
+ color: var(--smrt-color-on-error-container);
303
+ }
304
+
305
+ .working-strip__main {
306
+ display: flex;
307
+ flex: 1;
308
+ align-items: center;
309
+ gap: var(--smrt-spacing-2);
310
+ min-inline-size: 0;
311
+ min-block-size: 2.75rem;
312
+ padding: 0 var(--smrt-spacing-4);
313
+ border: 0;
314
+ border-radius: inherit;
315
+ background: transparent;
316
+ color: inherit;
317
+ font: inherit;
318
+ text-align: start;
319
+ }
320
+
321
+ button.working-strip__main {
322
+ cursor: pointer;
323
+ }
324
+
325
+ .working-strip--inline .working-strip__main {
326
+ min-block-size: 0;
327
+ padding: 0;
328
+ }
329
+
330
+ .working-strip__main:focus-visible,
331
+ .working-strip__button:focus-visible {
332
+ outline: 2px solid currentColor;
333
+ outline-offset: -2px;
334
+ }
335
+
336
+ .working-strip__icon {
337
+ display: inline-grid;
338
+ flex: none;
339
+ place-items: center;
340
+ inline-size: 1.25rem;
341
+ }
342
+
343
+ .working-strip__glyph {
344
+ font-weight: 700;
345
+ line-height: 1;
346
+ }
347
+
348
+ .working-strip__text {
349
+ display: flex;
350
+ flex-direction: column;
351
+ min-inline-size: 0;
352
+ }
353
+
354
+ .working-strip__goal {
355
+ overflow: hidden;
356
+ font: var(--smrt-typography-label-medium-font);
357
+ opacity: 0.8;
358
+ text-overflow: ellipsis;
359
+ white-space: nowrap;
360
+ }
361
+
362
+ .working-strip__label {
363
+ overflow: hidden;
364
+ text-overflow: ellipsis;
365
+ white-space: nowrap;
366
+ }
367
+
368
+ .working-strip__spinner {
369
+ display: block;
370
+ inline-size: 1rem;
371
+ block-size: 1rem;
372
+ border: 2px solid
373
+ color-mix(in srgb, currentColor 25%, transparent);
374
+ border-block-start-color: currentColor;
375
+ border-radius: var(--smrt-radius-full);
376
+ animation: working-strip-spin 0.8s linear infinite;
377
+ }
378
+
379
+ .working-strip__actions {
380
+ display: flex;
381
+ flex: none;
382
+ align-items: center;
383
+ gap: var(--smrt-spacing-1);
384
+ }
385
+
386
+ .working-strip__button {
387
+ flex: none;
388
+ min-inline-size: 2.75rem;
389
+ min-block-size: 2.75rem;
390
+ padding: 0 var(--smrt-spacing-4);
391
+ border: 1px solid var(--smrt-color-outline-variant);
392
+ border-radius: var(--smrt-radius-full);
393
+ background: var(--smrt-color-surface);
394
+ color: var(--smrt-color-on-surface);
395
+ font: var(--smrt-typography-label-large-font);
396
+ cursor: pointer;
397
+ }
398
+
399
+ .working-strip__button--primary {
400
+ border-color: transparent;
401
+ background: var(--smrt-color-primary);
402
+ color: var(--smrt-color-on-primary);
403
+ }
404
+
405
+ .working-strip__button--icon {
406
+ padding: 0;
407
+ }
408
+
409
+ .working-strip--inline .working-strip__button {
410
+ min-block-size: 2rem;
411
+ }
412
+
413
+ @keyframes working-strip-spin {
414
+ to {
415
+ transform: rotate(360deg);
416
+ }
417
+ }
418
+
419
+ @media (prefers-reduced-motion: reduce) {
420
+ .working-strip__spinner {
421
+ animation: none;
422
+ border-block-start-color: color-mix(in srgb, currentColor 25%, transparent);
423
+ border-inline-start-color: currentColor;
424
+ }
425
+ }
426
+ </style>
@@ -0,0 +1,37 @@
1
+ import { type WorkingStatus } from './working-status.js';
2
+ export interface Props {
3
+ /** What is happening. */
4
+ status: WorkingStatus;
5
+ /** `strip` (above a bottom bar), `floating` (a pill), or `inline`. */
6
+ variant?: 'strip' | 'floating' | 'inline';
7
+ /** Show a Stop button while the work runs, is paused, or waits. */
8
+ canStop?: boolean;
9
+ /** Stop the work. */
10
+ onstop?: () => void;
11
+ /** Pause the work (shows Pause while working; Escape pauses too). */
12
+ onpause?: () => void;
13
+ /** Continue paused work (shows Continue while paused). */
14
+ onresume?: () => void;
15
+ /** Open what the work is waiting on (shows Review while waiting). */
16
+ onreview?: () => void;
17
+ /** Reopen the surface doing the work (strip and floating). */
18
+ onopen?: () => void;
19
+ /** Hide a finished status (shows Close once done, failed or cancelled). */
20
+ ondismiss?: () => void;
21
+ /** Accessible hint for `onopen` (default "Open"). */
22
+ openLabel?: string;
23
+ /** Stop button text (default "Stop"). */
24
+ stopLabel?: string;
25
+ /** Pause button text (default "Pause"). */
26
+ pauseLabel?: string;
27
+ /** Continue button text (default "Continue"). */
28
+ resumeLabel?: string;
29
+ /** Review button text (default "Review"). */
30
+ reviewLabel?: string;
31
+ /** Minimum time between two polite step announcements. Default 2000ms. */
32
+ announceIntervalMs?: number;
33
+ }
34
+ declare const WorkingStrip: import("svelte").Component<Props, {}, "">;
35
+ type WorkingStrip = ReturnType<typeof WorkingStrip>;
36
+ export default WorkingStrip;
37
+ //# sourceMappingURL=WorkingStrip.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkingStrip.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/WorkingStrip.svelte.ts"],"names":[],"mappings":"AA2BA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,KAAK;IACpB,yBAAyB;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC1C,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA0KD,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -1,18 +1,10 @@
1
- /**
2
- * Golden test for ConfirmDialog (Sweep S11, #1416).
3
- *
4
- * ConfirmDialog renders a backdrop `<div role="dialog" aria-modal="true">` only
5
- * while `open` is true, with a title, message, and cancel/confirm buttons. It
6
- * exposes `onconfirm`/`oncancel` callbacks; Escape (handled at the document
7
- * level) and backdrop clicks both route to `oncancel`. On open it manages focus:
8
- * focus moves to the confirm button, Tab is trapped within the dialog, and focus
9
- * is restored to the opener on close (#1586).
10
- */
11
- import { render, screen, waitFor } from '@testing-library/svelte';
1
+ /** Native confirmation rendering, actions, focus and instance identity. */
2
+ import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';
12
3
  import userEvent from '@testing-library/user-event';
13
4
  import { describe, expect, it, vi } from 'vitest';
14
5
  import { expectNoA11yViolations } from '../../../test-support/a11y';
15
6
  import ConfirmDialog from '../ConfirmDialog.svelte';
7
+ import RichMessage from './confirm-message.fixture.svelte';
16
8
  const baseProps = {
17
9
  open: true,
18
10
  title: 'Delete item',
@@ -27,6 +19,38 @@ describe('ConfirmDialog', () => {
27
19
  expect(dialog).toHaveAccessibleName('Delete item');
28
20
  expect(screen.getByText('This action cannot be undone.')).toBeInTheDocument();
29
21
  });
22
+ it('uses native dialog and unique instance description ids', () => {
23
+ render(ConfirmDialog, { props: baseProps });
24
+ render(ConfirmDialog, {
25
+ props: { ...baseProps, title: 'Second', message: 'Other' },
26
+ });
27
+ const dialogs = screen.getAllByRole('dialog');
28
+ expect(dialogs.every((dialog) => dialog instanceof HTMLDialogElement)).toBe(true);
29
+ for (const attribute of ['aria-labelledby', 'aria-describedby']) {
30
+ const ids = dialogs.map((dialog) => dialog.getAttribute(attribute));
31
+ expect(new Set(ids).size).toBe(2);
32
+ for (let index = 0; index < dialogs.length; index++) {
33
+ expect(dialogs[index].contains(document.getElementById(ids[index]))).toBe(true);
34
+ }
35
+ }
36
+ });
37
+ it('handles native cancel without closing outside controlled state', async () => {
38
+ const oncancel = vi.fn();
39
+ render(ConfirmDialog, { props: { ...baseProps, oncancel } });
40
+ const dialog = screen.getByRole('dialog');
41
+ const event = new Event('cancel', { cancelable: true });
42
+ await fireEvent(dialog, event);
43
+ expect(event.defaultPrevented).toBe(true);
44
+ expect(oncancel).toHaveBeenCalledTimes(1);
45
+ expect(dialog).toHaveAttribute('open');
46
+ });
47
+ it('renders a snippet message as accessible rich content', () => {
48
+ render(RichMessage);
49
+ const dialog = screen.getByRole('dialog', { name: 'Rich confirmation' });
50
+ expect(dialog.querySelector('strong')).toHaveTextContent('Record name');
51
+ expect(screen.getAllByRole('listitem')).toHaveLength(2);
52
+ expect(dialog).toHaveAccessibleDescription('Remove Record name? Notes Attachments');
53
+ });
30
54
  it('renders nothing when closed', () => {
31
55
  render(ConfirmDialog, { props: { ...baseProps, open: false } });
32
56
  expect(screen.queryByRole('dialog')).toBeNull();
@@ -104,17 +128,11 @@ describe('ConfirmDialog', () => {
104
128
  expect(opener).toHaveFocus();
105
129
  opener.remove();
106
130
  });
107
- it('cancels via Escape even when focus is outside the dialog', async () => {
131
+ it('does not consume Escape from outside its dialog', async () => {
108
132
  const oncancel = vi.fn();
109
- const outside = document.createElement('input');
110
- document.body.appendChild(outside);
111
133
  render(ConfirmDialog, { props: { ...baseProps, oncancel } });
112
- // Move focus out of the dialog, then press Escape: the document-level
113
- // handler still fires because the dialog is open.
114
- outside.focus();
115
- await userEvent.keyboard('{Escape}');
116
- expect(oncancel).toHaveBeenCalledTimes(1);
117
- outside.remove();
134
+ await fireEvent.keyDown(window, { key: 'Escape' });
135
+ expect(oncancel).not.toHaveBeenCalled();
118
136
  });
119
137
  it('focuses the dialog container when all controls are disabled (loading)', async () => {
120
138
  // Both buttons are disabled while loading, so there is no focusable
@@ -0,0 +1,101 @@
1
+ /**
2
+ * PhoneSheet: a non-modal phone surface (full-screen page or bottom sheet)
3
+ * that stays mounted while closed, closes on its button / Escape / swipe
4
+ * down, and manages focus.
5
+ */
6
+ import { render, screen } from '@testing-library/svelte';
7
+ import userEvent from '@testing-library/user-event';
8
+ import { createRawSnippet, flushSync, tick } from 'svelte';
9
+ import { describe, expect, it, vi } from 'vitest';
10
+ import { expectNoA11yViolations } from '../../../test-support/a11y';
11
+ import PhoneSheet from '../PhoneSheet.svelte';
12
+ const body = createRawSnippet(() => ({
13
+ render: () => '<p>Sheet body</p>',
14
+ }));
15
+ describe('PhoneSheet', () => {
16
+ it('renders a labelled dialog with a named close button when open', async () => {
17
+ const { container } = render(PhoneSheet, {
18
+ props: {
19
+ open: true,
20
+ title: 'Notifications',
21
+ onclose: () => { },
22
+ children: body,
23
+ },
24
+ });
25
+ const dialog = screen.getByRole('dialog', { name: 'Notifications' });
26
+ expect(dialog).toHaveAttribute('aria-hidden', 'false');
27
+ expect(screen.getByRole('button', { name: 'Close Notifications' })).toBeInTheDocument();
28
+ expect(screen.getByText('Sheet body')).toBeInTheDocument();
29
+ await expectNoA11yViolations(container);
30
+ });
31
+ it('stays mounted but hidden and inert while closed', () => {
32
+ render(PhoneSheet, {
33
+ props: {
34
+ open: false,
35
+ title: 'Assistant',
36
+ onclose: () => { },
37
+ children: body,
38
+ },
39
+ });
40
+ const sheet = screen.getByTestId('phone-sheet');
41
+ expect(sheet).toHaveAttribute('aria-hidden', 'true');
42
+ // jsdom has no `inert` IDL attribute, so Svelte sets it as a property.
43
+ expect(sheet.hasAttribute('inert') ||
44
+ sheet.inert).toBe(true);
45
+ expect(sheet.classList.contains('open')).toBe(false);
46
+ });
47
+ it('closes on the close button and on Escape', async () => {
48
+ const onclose = vi.fn();
49
+ render(PhoneSheet, {
50
+ props: {
51
+ open: true,
52
+ title: 'Assistant',
53
+ onclose,
54
+ closeLabel: 'Close the assistant',
55
+ children: body,
56
+ },
57
+ });
58
+ await userEvent.click(screen.getByRole('button', { name: 'Close the assistant' }));
59
+ expect(onclose).toHaveBeenCalledTimes(1);
60
+ screen.getByRole('dialog').dispatchEvent(new KeyboardEvent('keydown', {
61
+ key: 'Escape',
62
+ bubbles: true,
63
+ cancelable: true,
64
+ }));
65
+ expect(onclose).toHaveBeenCalledTimes(2);
66
+ });
67
+ it('moves focus in on open and back to the opener on close', async () => {
68
+ const opener = document.createElement('button');
69
+ document.body.appendChild(opener);
70
+ opener.focus();
71
+ const { rerender } = render(PhoneSheet, {
72
+ props: {
73
+ open: false,
74
+ title: 'Assistant',
75
+ onclose: () => { },
76
+ children: body,
77
+ },
78
+ });
79
+ await rerender({ open: true });
80
+ await tick();
81
+ await tick();
82
+ expect(document.activeElement).toBe(screen.getByTestId('phone-sheet'));
83
+ await rerender({ open: false });
84
+ flushSync();
85
+ expect(document.activeElement).toBe(opener);
86
+ opener.remove();
87
+ });
88
+ it('draws a grabber only for the sheet variant', () => {
89
+ const { container } = render(PhoneSheet, {
90
+ props: {
91
+ open: true,
92
+ title: 'Assistant',
93
+ variant: 'sheet',
94
+ onclose: () => { },
95
+ children: body,
96
+ },
97
+ });
98
+ expect(container.querySelector('.phone-sheet__grabber')).not.toBeNull();
99
+ expect(container.querySelector('.phone-sheet--sheet')).not.toBeNull();
100
+ });
101
+ });