@fusion.dev/helix-headless 0.145.0 → 0.147.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 (343) hide show
  1. package/custom-elements.json +12286 -4281
  2. package/dist/accordion/item/accordion-item.d.ts +51 -18
  3. package/dist/accordion/item/accordion-item.js +45 -13
  4. package/dist/accordion/root/accordion-root.d.ts +16 -7
  5. package/dist/accordion/root/accordion-root.js +3 -3
  6. package/dist/announcement/root/announcement-root.d.ts +16 -6
  7. package/dist/announcement/root/announcement-root.js +37 -7
  8. package/dist/app-header/root/app-header-root.d.ts +7 -2
  9. package/dist/app-header/root/app-header-root.js +9 -1
  10. package/dist/app-header/sectioning.d.ts +3 -1
  11. package/dist/app-header/sectioning.js +3 -2
  12. package/dist/area-chart/root/area-chart-root.d.ts +18 -1
  13. package/dist/area-chart/root/area-chart-root.js +11 -3
  14. package/dist/avatar/group/avatar-group.d.ts +20 -14
  15. package/dist/avatar/group/avatar-group.js +17 -19
  16. package/dist/avatar/root/avatar-root.d.ts +31 -1
  17. package/dist/avatar/root/avatar-root.js +11 -1
  18. package/dist/badge/root/badge-root.d.ts +60 -7
  19. package/dist/badge/root/badge-root.js +89 -6
  20. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  21. package/dist/bar-chart/root/bar-chart-root.js +48 -20
  22. package/dist/bar-chart/stack.d.ts +25 -0
  23. package/dist/bar-chart/stack.js +27 -0
  24. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
  25. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
  26. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
  27. package/dist/breadcrumbs/root/breadcrumbs-root.js +51 -4
  28. package/dist/button/root/button-root.d.ts +50 -38
  29. package/dist/button/root/button-root.js +42 -53
  30. package/dist/button/submitter.d.ts +27 -0
  31. package/dist/button/submitter.js +25 -0
  32. package/dist/button-group/root/button-group-root.d.ts +2 -1
  33. package/dist/button-group/root/button-group-root.js +5 -1
  34. package/dist/canvas/node/canvas-node.d.ts +4 -3
  35. package/dist/canvas/node/canvas-node.js +3 -2
  36. package/dist/canvas/root/canvas-root.js +2 -2
  37. package/dist/card/root/card-root.d.ts +36 -4
  38. package/dist/card/root/card-root.js +29 -10
  39. package/dist/carousel/root/carousel-root.d.ts +43 -4
  40. package/dist/carousel/root/carousel-root.js +40 -12
  41. package/dist/carousel/stops.d.ts +20 -0
  42. package/dist/carousel/stops.js +30 -0
  43. package/dist/chat/message/chat-message.js +5 -4
  44. package/dist/chat/naming.d.ts +5 -1
  45. package/dist/chat/naming.js +4 -2
  46. package/dist/chat/root/chat-root.d.ts +40 -4
  47. package/dist/chat/root/chat-root.js +32 -6
  48. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  49. package/dist/checkbox/root/checkbox-root.js +18 -7
  50. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  51. package/dist/checkbox-group/root/checkbox-group-root.js +14 -11
  52. package/dist/checkbox-group/select-all.d.ts +21 -0
  53. package/dist/checkbox-group/select-all.js +7 -0
  54. package/dist/code-block/highlight.d.ts +15 -0
  55. package/dist/code-block/highlight.js +4 -0
  56. package/dist/code-block/root/code-block-root.d.ts +79 -10
  57. package/dist/code-block/root/code-block-root.js +74 -5
  58. package/dist/color-input/root/color-input-root.d.ts +14 -0
  59. package/dist/color-input/root/color-input-root.js +17 -7
  60. package/dist/color-picker/channels.js +1 -2
  61. package/dist/color-picker/root/color-picker-root.d.ts +53 -16
  62. package/dist/color-picker/root/color-picker-root.js +155 -46
  63. package/dist/color-picker/wheel.d.ts +17 -0
  64. package/dist/color-picker/wheel.js +6 -0
  65. package/dist/combobox/root/combobox-root.d.ts +56 -0
  66. package/dist/combobox/root/combobox-root.js +92 -15
  67. package/dist/command/root/command-root.d.ts +19 -2
  68. package/dist/command/root/command-root.js +24 -23
  69. package/dist/copy-button/root/copy-button-root.d.ts +21 -1
  70. package/dist/copy-button/root/copy-button-root.js +16 -4
  71. package/dist/data-table/index.d.ts +1 -1
  72. package/dist/data-table/index.js +1 -1
  73. package/dist/data-table/keys.d.ts +6 -0
  74. package/dist/data-table/keys.js +14 -0
  75. package/dist/data-table/root/data-table-root.d.ts +27 -18
  76. package/dist/data-table/root/data-table-root.js +31 -57
  77. package/dist/data-table/tree.d.ts +16 -1
  78. package/dist/data-table/tree.js +2 -3
  79. package/dist/date-input/root/date-input-root.d.ts +11 -2
  80. package/dist/date-input/root/date-input-root.js +26 -12
  81. package/dist/date-picker/root/date-picker-root.d.ts +14 -9
  82. package/dist/date-picker/root/date-picker-root.js +33 -22
  83. package/dist/description-list/item/description-list-item.d.ts +18 -4
  84. package/dist/description-list/item/description-list-item.js +8 -4
  85. package/dist/dialog/description.js +15 -1
  86. package/dist/dialog/root/dialog-root.d.ts +8 -2
  87. package/dist/dialog/root/dialog-root.js +16 -1
  88. package/dist/divider/root/divider-root.d.ts +3 -0
  89. package/dist/divider/root/divider-root.js +2 -1
  90. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  91. package/dist/donut-chart/root/donut-chart-root.js +55 -1
  92. package/dist/donut-chart/slice-label.d.ts +35 -0
  93. package/dist/donut-chart/slice-label.js +11 -0
  94. package/dist/drawer/reveal.d.ts +8 -0
  95. package/dist/drawer/reveal.js +1 -0
  96. package/dist/drawer/root/drawer-root.d.ts +63 -2
  97. package/dist/drawer/root/drawer-root.js +75 -4
  98. package/dist/drilldown/item/drilldown-item.d.ts +21 -1
  99. package/dist/drilldown/item/drilldown-item.js +40 -5
  100. package/dist/drilldown/root/drilldown-root.d.ts +21 -3
  101. package/dist/drilldown/root/drilldown-root.js +22 -3
  102. package/dist/element-events.generated.js +35 -6
  103. package/dist/empty/root/empty-root.d.ts +34 -2
  104. package/dist/empty/root/empty-root.js +26 -4
  105. package/dist/file-input/root/file-input-root.d.ts +99 -8
  106. package/dist/file-input/root/file-input-root.js +120 -22
  107. package/dist/file-input/screen.d.ts +2 -1
  108. package/dist/file-input/status.d.ts +24 -0
  109. package/dist/file-input/status.js +10 -0
  110. package/dist/filter-input/chip/filter-chip.d.ts +23 -0
  111. package/dist/filter-input/chip/filter-chip.js +11 -2
  112. package/dist/filter-input/menu/filter-menu.d.ts +2 -0
  113. package/dist/filter-input/menu/filter-menu.js +12 -4
  114. package/dist/filter-input/root/filter-input-root.d.ts +38 -6
  115. package/dist/filter-input/root/filter-input-root.js +18 -28
  116. package/dist/filter-input/suggest.d.ts +28 -3
  117. package/dist/filter-input/suggest.js +18 -8
  118. package/dist/format-date/options.d.ts +3 -4
  119. package/dist/format-date/options.js +2 -2
  120. package/dist/format-date/root/format-date-root.d.ts +27 -17
  121. package/dist/format-date/root/format-date-root.js +27 -48
  122. package/dist/heatmap/root/buckets.d.ts +21 -0
  123. package/dist/heatmap/root/buckets.js +34 -0
  124. package/dist/heatmap/root/heatmap-root.d.ts +83 -11
  125. package/dist/heatmap/root/heatmap-root.js +104 -12
  126. package/dist/icon/index.d.ts +1 -1
  127. package/dist/icon/index.js +1 -1
  128. package/dist/icon/registry.d.ts +26 -1
  129. package/dist/icon/registry.js +12 -1
  130. package/dist/icon/root/icon-root.d.ts +25 -1
  131. package/dist/icon/root/icon-root.js +44 -12
  132. package/dist/icon/root/index.d.ts +1 -1
  133. package/dist/icon/root/index.js +1 -1
  134. package/dist/icon/settle.d.ts +7 -0
  135. package/dist/icon/settle.js +10 -0
  136. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  137. package/dist/image/root/image-root.d.ts +14 -1
  138. package/dist/image/root/image-root.js +7 -2
  139. package/dist/input/root/input-root.d.ts +34 -3
  140. package/dist/input/root/input-root.js +17 -4
  141. package/dist/kbd/keys.d.ts +29 -0
  142. package/dist/kbd/keys.js +52 -0
  143. package/dist/kbd/root/kbd-root.d.ts +52 -1
  144. package/dist/kbd/root/kbd-root.js +40 -47
  145. package/dist/legend/hidden-series.d.ts +10 -2
  146. package/dist/legend/hidden-series.js +5 -2
  147. package/dist/legend/root/legend-root.d.ts +77 -12
  148. package/dist/legend/root/legend-root.js +71 -17
  149. package/dist/lightbox/root/lightbox-root.d.ts +98 -10
  150. package/dist/lightbox/root/lightbox-root.js +153 -18
  151. package/dist/lightbox/zoom-controller.d.ts +59 -0
  152. package/dist/lightbox/zoom-controller.js +128 -0
  153. package/dist/lightbox/zoom.d.ts +24 -0
  154. package/dist/lightbox/zoom.js +18 -0
  155. package/dist/line-chart/root/line-chart-root.d.ts +38 -1
  156. package/dist/line-chart/root/line-chart-root.js +31 -3
  157. package/dist/list/item/list-item.d.ts +2 -0
  158. package/dist/list/item/list-item.js +11 -2
  159. package/dist/list/root/list-root.d.ts +70 -13
  160. package/dist/list/root/list-root.js +91 -13
  161. package/dist/list/selection.d.ts +54 -7
  162. package/dist/list/selection.js +32 -7
  163. package/dist/listbox/root/listbox-root.d.ts +44 -4
  164. package/dist/listbox/root/listbox-root.js +72 -34
  165. package/dist/loader/busy.d.ts +10 -0
  166. package/dist/loader/busy.js +11 -0
  167. package/dist/loader/root/loader-root.d.ts +9 -2
  168. package/dist/loader/root/loader-root.js +23 -3
  169. package/dist/megamenu/hand-over.d.ts +75 -0
  170. package/dist/megamenu/hand-over.js +67 -0
  171. package/dist/megamenu/root/megamenu-root.d.ts +80 -15
  172. package/dist/megamenu/root/megamenu-root.js +76 -19
  173. package/dist/menu/item/menu-item.d.ts +51 -2
  174. package/dist/menu/item/menu-item.js +50 -26
  175. package/dist/menu/root/menu-root.d.ts +17 -0
  176. package/dist/menu/root/menu-root.js +2 -2
  177. package/dist/meter/root/meter-root.d.ts +62 -1
  178. package/dist/meter/root/meter-root.js +38 -16
  179. package/dist/navigation/root/navigation-root.d.ts +2 -1
  180. package/dist/navigation/root/navigation-root.js +2 -2
  181. package/dist/notifications/root/notifications-root.d.ts +20 -4
  182. package/dist/notifications/root/notifications-root.js +30 -8
  183. package/dist/number-input/grain.d.ts +28 -0
  184. package/dist/number-input/grain.js +14 -0
  185. package/dist/number-input/root/number-input-root.d.ts +34 -9
  186. package/dist/number-input/root/number-input-root.js +31 -25
  187. package/dist/object-inspector/root/object-inspector-root.d.ts +88 -33
  188. package/dist/object-inspector/root/object-inspector-root.js +134 -92
  189. package/dist/object-inspector/rows.d.ts +18 -0
  190. package/dist/object-inspector/rows.js +33 -0
  191. package/dist/option/index.d.ts +1 -0
  192. package/dist/option/index.js +1 -0
  193. package/dist/option/root/option-root.d.ts +5 -3
  194. package/dist/option/separator/option-separator.d.ts +30 -0
  195. package/dist/option/separator/option-separator.js +21 -0
  196. package/dist/outline/root/outline-root.d.ts +30 -0
  197. package/dist/outline/root/outline-root.js +17 -13
  198. package/dist/pagination/size/pagination-size.d.ts +6 -0
  199. package/dist/pagination/size/pagination-size.js +5 -3
  200. package/dist/pin-input/code.d.ts +37 -0
  201. package/dist/pin-input/code.js +25 -0
  202. package/dist/pin-input/root/pin-input-root.d.ts +116 -115
  203. package/dist/pin-input/root/pin-input-root.js +163 -155
  204. package/dist/popover/hide-outside.d.ts +14 -0
  205. package/dist/popover/hide-outside.js +34 -0
  206. package/dist/popover/root/popover-root.d.ts +64 -8
  207. package/dist/popover/root/popover-root.js +67 -4
  208. package/dist/progress/root/progress-root.d.ts +47 -0
  209. package/dist/progress/root/progress-root.js +34 -16
  210. package/dist/qr-code/export.d.ts +45 -1
  211. package/dist/qr-code/export.js +28 -0
  212. package/dist/qr-code/name.d.ts +11 -0
  213. package/dist/qr-code/name.js +7 -0
  214. package/dist/qr-code/root/qr-code-root.d.ts +36 -11
  215. package/dist/qr-code/root/qr-code-root.js +58 -11
  216. package/dist/quote/marks.d.ts +8 -0
  217. package/dist/quote/marks.js +5 -0
  218. package/dist/quote/root/quote-root.d.ts +14 -2
  219. package/dist/quote/root/quote-root.js +23 -1
  220. package/dist/radio/group/radio-group.d.ts +15 -0
  221. package/dist/radio/root/radio-root.d.ts +6 -2
  222. package/dist/radio/root/radio-root.js +7 -2
  223. package/dist/rating/root/rating-root.d.ts +30 -12
  224. package/dist/rating/root/rating-root.js +27 -27
  225. package/dist/scatter-chart/fit.d.ts +15 -0
  226. package/dist/scatter-chart/fit.js +35 -0
  227. package/dist/scatter-chart/root/scatter-chart-root.d.ts +51 -1
  228. package/dist/scatter-chart/root/scatter-chart-root.js +64 -24
  229. package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
  230. package/dist/scroll-area/root/scroll-area-root.js +57 -173
  231. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  232. package/dist/scroll-area/scrollbar-controller.js +172 -0
  233. package/dist/scroll-area/scrollbar.d.ts +27 -8
  234. package/dist/scroll-area/scrollbar.js +10 -1
  235. package/dist/select/align.d.ts +47 -0
  236. package/dist/select/align.js +7 -0
  237. package/dist/select/root/select-root.d.ts +71 -0
  238. package/dist/select/root/select-root.js +78 -6
  239. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  240. package/dist/skeleton/root/skeleton-root.js +4 -2
  241. package/dist/skip-link/root/skip-link-root.js +2 -2
  242. package/dist/slider/root/slider-root.d.ts +59 -5
  243. package/dist/slider/root/slider-root.js +45 -3
  244. package/dist/sparkline/readings.d.ts +36 -0
  245. package/dist/sparkline/readings.js +36 -0
  246. package/dist/sparkline/root/sparkline-root.d.ts +121 -7
  247. package/dist/sparkline/root/sparkline-root.js +160 -26
  248. package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
  249. package/dist/speed-dial/item/speed-dial-item.js +2 -2
  250. package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
  251. package/dist/speed-dial/root/speed-dial-root.js +11 -3
  252. package/dist/splitter/root/splitter-root.d.ts +10 -12
  253. package/dist/splitter/root/splitter-root.js +211 -204
  254. package/dist/stat/root/stat-root.d.ts +14 -5
  255. package/dist/stat/root/stat-root.js +21 -5
  256. package/dist/steps/reach.d.ts +5 -0
  257. package/dist/steps/reach.js +3 -0
  258. package/dist/steps/root/steps-root.d.ts +56 -3
  259. package/dist/steps/root/steps-root.js +50 -6
  260. package/dist/steps/step/step.d.ts +8 -0
  261. package/dist/steps/step/step.js +8 -3
  262. package/dist/switch/root/switch-root.d.ts +10 -0
  263. package/dist/table/column/table-column.d.ts +6 -10
  264. package/dist/table/column/table-column.js +8 -20
  265. package/dist/table/root/table-root.d.ts +31 -10
  266. package/dist/table/root/table-root.js +14 -18
  267. package/dist/table/row/table-row.d.ts +24 -0
  268. package/dist/table/row/table-row.js +37 -1
  269. package/dist/tabs/panel/tab-panel.d.ts +16 -3
  270. package/dist/tabs/panel/tab-panel.js +34 -5
  271. package/dist/tabs/root/tabs-root.d.ts +17 -3
  272. package/dist/tabs/root/tabs-root.js +1 -1
  273. package/dist/tabs/tab/tab.d.ts +5 -0
  274. package/dist/tabs/tab/tab.js +5 -2
  275. package/dist/tag/group/tag-group.d.ts +44 -5
  276. package/dist/tag/group/tag-group.js +60 -9
  277. package/dist/tag/root/tag-root.js +9 -2
  278. package/dist/textarea/root/textarea-root.d.ts +41 -2
  279. package/dist/textarea/root/textarea-root.js +39 -1
  280. package/dist/time-input/root/time-input-root.d.ts +10 -2
  281. package/dist/time-input/root/time-input-root.js +24 -13
  282. package/dist/time-picker/root/time-picker-root.d.ts +28 -17
  283. package/dist/time-picker/root/time-picker-root.js +18 -29
  284. package/dist/time-picker/wheel-name.d.ts +9 -0
  285. package/dist/time-picker/wheel-name.js +15 -0
  286. package/dist/timeline/group/timeline-group.js +2 -2
  287. package/dist/toast/item/toast-item.d.ts +16 -3
  288. package/dist/toast/item/toast-item.js +22 -6
  289. package/dist/toast/root/toast-root.d.ts +34 -4
  290. package/dist/toast/root/toast-root.js +74 -13
  291. package/dist/toast/words.d.ts +12 -0
  292. package/dist/toast/words.js +25 -0
  293. package/dist/toggle/group/toggle-group.d.ts +52 -7
  294. package/dist/toggle/group/toggle-group.js +58 -44
  295. package/dist/toggle/root/toggle-root.js +2 -4
  296. package/dist/toolbar/root/toolbar-root.d.ts +21 -5
  297. package/dist/toolbar/root/toolbar-root.js +52 -8
  298. package/dist/tooltip/root/tooltip-root.d.ts +20 -3
  299. package/dist/tooltip/root/tooltip-root.js +18 -1
  300. package/dist/tour/back.d.ts +10 -0
  301. package/dist/tour/back.js +8 -0
  302. package/dist/tour/root/tour-root.d.ts +45 -2
  303. package/dist/tour/root/tour-root.js +53 -8
  304. package/dist/tour/stop/tour-stop.d.ts +3 -0
  305. package/dist/tour/stop/tour-stop.js +3 -3
  306. package/dist/tree/item/tree-item.d.ts +7 -3
  307. package/dist/tree/item/tree-item.js +3 -0
  308. package/dist/tree/root/tree-root.d.ts +24 -3
  309. package/dist/tree/root/tree-root.js +32 -13
  310. package/dist/tree/selection.js +2 -15
  311. package/dist/trend/figure.d.ts +16 -0
  312. package/dist/trend/figure.js +8 -0
  313. package/dist/trend/root/trend-root.d.ts +83 -19
  314. package/dist/trend/root/trend-root.js +59 -8
  315. package/dist/video/media-events.d.ts +13 -18
  316. package/dist/video/media-events.js +1 -5
  317. package/dist/video/root/extra-controls.d.ts +12 -0
  318. package/dist/video/root/extra-controls.js +6 -2
  319. package/dist/video/root/video-root.d.ts +23 -6
  320. package/dist/video/root/video-root.js +19 -10
  321. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
  322. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  323. package/dist/video-playlist/root/video-playlist-root.d.ts +17 -1
  324. package/dist/video-playlist/root/video-playlist-root.js +3 -0
  325. package/dist/virtual-list/fill.d.ts +11 -8
  326. package/dist/virtual-list/fill.js +10 -17
  327. package/dist/virtual-list/keys.d.ts +16 -7
  328. package/dist/virtual-list/keys.js +17 -6
  329. package/dist/virtual-list/plan.d.ts +65 -0
  330. package/dist/virtual-list/plan.js +27 -0
  331. package/dist/virtual-list/root/virtual-list-root.d.ts +136 -13
  332. package/dist/virtual-list/root/virtual-list-root.js +218 -51
  333. package/lint.json +1 -1
  334. package/package.json +8 -8
  335. package/types/jsx.d.ts +7441 -1458
  336. package/types/svelte.d.ts +1 -0
  337. package/types/vue.d.ts +1501 -326
  338. package/dist/chat/relative-clock.d.ts +0 -39
  339. package/dist/chat/relative-clock.js +0 -31
  340. package/dist/data-table/root/order.d.ts +0 -141
  341. package/dist/data-table/root/order.js +0 -76
  342. package/dist/tag/selection.d.ts +0 -10
  343. package/dist/tag/selection.js +0 -12
@@ -27,6 +27,15 @@ declare const HelixHeadlessFilterChip_base: (new (...args: any[]) => import("@fu
27
27
  * dismissal, which is also how you take control of the interaction for one
28
28
  * press. `requestChange` documents the pattern.
29
29
  *
30
+ * **Keyboard.** The remove button is a tab stop of its own, and Enter or Space
31
+ * on it asks to remove the filter. In a `FilterInput`, Backspace in the empty
32
+ * field asks to remove the last chip.
33
+ *
34
+ * The remove button is named `dismiss-label` followed by the chip's words,
35
+ * such as "Remove filter Status is not open", so a row of chips says which
36
+ * filter each button removes. Write `{label}` in `dismiss-label` to put the
37
+ * words elsewhere.
38
+ *
30
39
  * To let the user change the operator, slot a menu trigger into `operator`.
31
40
  * With the text fallback, the operator is a label. The chip does not interpret
32
41
  * operators: their meaning belongs to your domain, as `FilterOperator`
@@ -100,6 +109,20 @@ export declare class HelixHeadlessFilterChip extends HelixHeadlessFilterChip_bas
100
109
  * makes an unusual filter look unusual.
101
110
  */
102
111
  operatorLabel: string;
112
+ /**
113
+ * The remove button's name: `dismissLabel` with the chip's words, its field,
114
+ * its comparison and its values, such as "Remove filter Status is not open".
115
+ *
116
+ * **Named for its chip**, as File Input names each remove button for its
117
+ * file: a row of buttons each called "Remove filter" says nothing about
118
+ * which filter each one takes away. `{label}` in `dismiss-label` says where
119
+ * the words go, and without it they follow the label.
120
+ *
121
+ * Each word is read from what is slotted and otherwise from `label` and
122
+ * `operator-label`, which is all a server and a hydrating render can read,
123
+ * so the values join the update after.
124
+ */
125
+ private get removeName();
103
126
  protected firstUpdated(changed: PropertyValues): void;
104
127
  protected render(): TemplateResult;
105
128
  }
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { customElement, HelixElement, MixinDismissible } from '@fusion.dev/helix-core';
7
+ import { customElement, HelixElement, MixinDismissible, slottedWords } from '@fusion.dev/helix-core';
8
8
  import { x } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
@@ -16,8 +16,17 @@ let HelixHeadlessFilterChip = class HelixHeadlessFilterChip extends MixinDismiss
16
16
  this.label = '';
17
17
  this.operatorLabel = '';
18
18
  }
19
+ get removeName() {
20
+ const read = (slot, fallback) => (this.childrenKnown && slottedWords(this, [slot])) || fallback;
21
+ const words = [read('field', this.label), read('operator', this.operatorLabel), read('', '')]
22
+ .filter(Boolean)
23
+ .join(' ');
24
+ const label = this.dismissLabel;
25
+ return label.includes('{label}') ? label.replace('{label}', words) : `${label} ${words}`.trim();
26
+ }
19
27
  firstUpdated(changed) {
20
28
  super.firstUpdated(changed);
29
+ this.renderRoot.addEventListener('slotchange', () => this.requestUpdate());
21
30
  this.finishHydration();
22
31
  }
23
32
  render() {
@@ -33,7 +42,7 @@ let HelixHeadlessFilterChip = class HelixHeadlessFilterChip extends MixinDismiss
33
42
  ? html `<button
34
43
  part="dismiss"
35
44
  type="button"
36
- aria-label=${this.dismissLabel}
45
+ aria-label=${this.removeName}
37
46
  @click=${() => this.dismiss()}
38
47
  >
39
48
  <svg part="dismiss-mark" fill="currentColor" viewBox=${x.viewBox} aria-hidden="true">
@@ -71,6 +71,8 @@ import '../../menu/index.js';
71
71
  * @csspart entry-mark - The mark at the end of a row: a check mark on a chosen value, and a caret on a field.
72
72
  * @csspart entry-shortcut - The key drawn for a row's shortcut. The filter menu sets none, so it renders only where a subclass does.
73
73
  * @csspart entry-shortcut-kbd - The key inside it.
74
+ * @csspart entry-shortcut-key - One key of the shortcut's chord.
75
+ * @csspart entry-shortcut-separator - The `+` between two keys of the shortcut, where the platform writes one.
74
76
  * @csspart entry-start - The leading column.
75
77
  * @csspart menu - The menu the fields are offered in.
76
78
  * @csspart menu-back - The button that goes back from a field's page.
@@ -138,7 +138,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
138
138
  return html `<${item}
139
139
  part="entry"
140
140
  exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
141
- shortcut-kbd: entry-shortcut-kbd, start: entry-start"
141
+ shortcut-kbd: entry-shortcut-kbd,
142
+ shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
143
+ start: entry-start"
142
144
  data-facet="field"
143
145
  data-field=${name}
144
146
  >
@@ -147,7 +149,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
147
149
  ? html `<${item}
148
150
  part="entry"
149
151
  exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
150
- shortcut-kbd: entry-shortcut-kbd, start: entry-start"
152
+ shortcut-kbd: entry-shortcut-kbd,
153
+ shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
154
+ start: entry-start"
151
155
  slot="submenu"
152
156
  data-facet="comparison"
153
157
  data-field=${name}
@@ -156,7 +160,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
156
160
  ${operators.map((operator) => html `<${item}
157
161
  part="entry"
158
162
  exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
159
- shortcut-kbd: entry-shortcut-kbd, start: entry-start"
163
+ shortcut-kbd: entry-shortcut-kbd,
164
+ shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
165
+ start: entry-start"
160
166
  slot="submenu"
161
167
  checkable
162
168
  exclusive
@@ -179,7 +185,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
179
185
  ${offered.map((option) => html `<${item}
180
186
  part="entry"
181
187
  exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
182
- shortcut-kbd: entry-shortcut-kbd, start: entry-start"
188
+ shortcut-kbd: entry-shortcut-kbd,
189
+ shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
190
+ start: entry-start"
183
191
  slot="submenu"
184
192
  checkable
185
193
  ?exclusive=${using?.arity === 'one'}
@@ -13,12 +13,36 @@ declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@f
13
13
  * its tokens show a selection it owns, drawn from the options it was given.
14
14
  *
15
15
  * `value` is the typed text. Every keystroke fires `input` with the text on the
16
- * element, so a table can narrow as the user types. A form receives the text
17
- * under `name`, and then one more entry under `name` for each token: its
18
- * `value` attribute, or for a `FilterChip`, its field and values written
19
- * `field:values` as the field reads them typed. Backspace in an empty field fires
20
- * `helix-dismiss` on the last token, the same event its remove control fires,
21
- * so one handler covers the pointer and the keyboard.
16
+ * element, so a table can narrow as the user types. Backspace in an empty field
17
+ * fires `helix-dismiss` on the last token, the same event its remove control
18
+ * fires, so one handler covers the pointer and the keyboard.
19
+ *
20
+ * **What a form receives.** The text under `name`, and then one more entry
21
+ * under `name` for each token, in the order the tokens stand:
22
+ *
23
+ * | Token | Entry |
24
+ * |---|---|
25
+ * | Any element with a `value` attribute | The value as written: `saved:mine` |
26
+ * | `FilterChip` with `name` and values | `status:open,pending` |
27
+ * | The same, with `operator="none"` (what a typed `-status:` makes) | `-status:open,pending` |
28
+ * | The same, with any other `operator` except `any` | `created[after]:2024` |
29
+ * | A token with neither | Nothing |
30
+ *
31
+ * The values are the chip's text outside its `field` and `operator` slots,
32
+ * with the spaces around each comma removed. A server splits an entry at its
33
+ * first colon, reads a leading `-` as the negation, and reads a word in
34
+ * brackets before the colon as the comparison.
35
+ *
36
+ * **Keyboard.** Focus stays in the text. The text names the highlighted
37
+ * suggestion as its `aria-activedescendant`.
38
+ *
39
+ * | Key | What it does |
40
+ * |---|---|
41
+ * | Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. |
42
+ * | Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. |
43
+ * | Home, End | Highlights the first or the last suggestion while the panel is open. |
44
+ * | Escape | Closes the panel and stops there, so a dialog around the field stays open. |
45
+ * | Backspace | In an empty field, asks the last token to go. |
22
46
  *
23
47
  * **Typed filters.** The field parses only the fields you declare. Write
24
48
  * `FilterField` elements, usually inside the `FilterMenu` slotted into `start`,
@@ -73,6 +97,7 @@ declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@f
73
97
  * @aliases SearchField, FacetInput, TokenInput
74
98
  * @documentation https://fusion.dev/helix/components/filter-input
75
99
  *
100
+ * @slot clear-icon - Replaces the cross on the clear button, under `clearable`.
76
101
  * @slot end - Content after the text, such as a count or a control.
77
102
  * @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
78
103
  * @slot hint - Help under the control, for content richer than the `hint` text.
@@ -232,6 +257,11 @@ export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_b
232
257
  * and one that pretends it was never there.
233
258
  */
234
259
  private get suggestions();
260
+ /**
261
+ * Every option slotted into `suggestions`, and every option one level inside
262
+ * a group slotted there, hidden or not.
263
+ */
264
+ private get options();
235
265
  /**
236
266
  * The direction of the selection, named as on `<input>`.
237
267
  *
@@ -413,6 +443,8 @@ export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_b
413
443
  private markActive;
414
444
  /** Puts the caret in the text field. */
415
445
  focus(options?: FocusOptions): void;
446
+ /** The cross on the clear button, behind a seam a tier can move. */
447
+ protected renderClearIcon(): TemplateResult;
416
448
  protected render(): TemplateResult;
417
449
  }
418
450
  declare global {
@@ -162,22 +162,18 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
162
162
  };
163
163
  }
164
164
  narrow() {
165
- const slot = this.renderRoot?.querySelector('slot[name="suggestions"]');
166
165
  const term = this.filterSuggestions
167
166
  ? currentTerm(this.value, this.control?.selectionStart ?? this.value.length)
168
167
  : '';
169
- for (const node of slot?.assignedElements({ flatten: true }) ?? []) {
170
- const options = isOption(node) ? [node] : [...node.children].filter(isOption);
171
- for (const option of options) {
172
- const hide = !suggests(option.textContent ?? '', term);
173
- if (hide && !option.hidden) {
174
- option.hidden = true;
175
- this.narrowed.add(option);
176
- }
177
- else if (!hide && this.narrowed.has(option)) {
178
- option.hidden = false;
179
- this.narrowed.delete(option);
180
- }
168
+ for (const option of this.options) {
169
+ const hide = !suggests(option.textContent ?? '', term);
170
+ if (hide && !option.hidden) {
171
+ option.hidden = true;
172
+ this.narrowed.add(option);
173
+ }
174
+ else if (!hide && this.narrowed.has(option)) {
175
+ option.hidden = false;
176
+ this.narrowed.delete(option);
181
177
  }
182
178
  }
183
179
  }
@@ -220,20 +216,11 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
220
216
  return this.clearable && this.value !== '' && !this.isDisabled;
221
217
  }
222
218
  get suggestions() {
219
+ return this.options.filter((option) => !option.disabled && !option.hidden);
220
+ }
221
+ get options() {
223
222
  const slot = this.renderRoot?.querySelector('slot[name="suggestions"]');
224
- const found = [];
225
- for (const node of slot?.assignedElements({ flatten: true }) ?? []) {
226
- if (isOption(node)) {
227
- found.push(node);
228
- continue;
229
- }
230
- for (const child of node.children) {
231
- if (isOption(child)) {
232
- found.push(child);
233
- }
234
- }
235
- }
236
- return found.filter((option) => !option.disabled && !option.hidden);
223
+ return (slot?.assignedElements({ flatten: true }) ?? []).flatMap((node) => isOption(node) ? [node] : [...node.children].filter(isOption));
237
224
  }
238
225
  get selectionDirection() {
239
226
  return this.control?.selectionDirection ?? 'none';
@@ -364,7 +351,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
364
351
  super.updated(changed);
365
352
  this.releaseCaret?.();
366
353
  this.releaseCaret = undefined;
367
- this.internals.setFormValue(this.formValue());
354
+ this.internals.setFormValue(this.formValue(), this.value);
368
355
  this.sayCount();
369
356
  const control = this.control;
370
357
  if (control) {
@@ -392,6 +379,9 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
392
379
  focus(options) {
393
380
  this.control?.focus(options);
394
381
  }
382
+ renderClearIcon() {
383
+ return html `<slot name="clear-icon">${drawIcon(x)}</slot>`;
384
+ }
395
385
  render() {
396
386
  return html `${this.renderLabel()}
397
387
  <div part="field" @focusin=${this.handleFocusIn} @focusout=${this.handleFocusOut}>
@@ -426,7 +416,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
426
416
  aria-label=${this.clearLabel}
427
417
  @click=${this.handleClear}
428
418
  >
429
- ${drawIcon(x)}
419
+ ${this.renderClearIcon()}
430
420
  </button>`
431
421
  : nothing}
432
422
  </div>
@@ -9,9 +9,34 @@
9
9
  export declare const currentTerm: (text: string, caret?: number) => string;
10
10
  /** Whether a suggestion's words hold the term, ignoring case and accents. */
11
11
  export declare const suggests: (words: string, term: string) => boolean;
12
+ /** What a token says about the filter it shows, as `tokenEntry` reads it. */
13
+ export interface TokenWords {
14
+ /** The field it filters, from its `name` attribute. */
15
+ readonly field: string | null;
16
+ /** The comparison, from its `operator` attribute. */
17
+ readonly operator: string | null;
18
+ /** The values it shows, from its text. */
19
+ readonly text: string;
20
+ /** What it sends as written, from its `value` attribute. */
21
+ readonly value: string | null;
22
+ }
12
23
  /**
13
- * What a token sends a form: its `value` attribute, or for a token naming a
14
- * field, the field and the values it shows, written `field:values` the way the
15
- * field reads them typed. Nothing for a token that says neither.
24
+ * The form entry for a token's words: its `value` where it has one, or else
25
+ * `field:values`, the way the field reads a filter typed.
26
+ *
27
+ * - The values are the token's text, with the spaces around each comma taken
28
+ * out: `status:open,pending`.
29
+ * - The comparison named `none`, which a typed `-field:` asks for, leads with a
30
+ * `-`: `-team:ops`.
31
+ * - Any comparison other than `any` and `none` is written in brackets after
32
+ * the field, so a chip that says `is after` keeps it: `created[after]:2024`.
33
+ * `any`, or no `operator`, writes none.
34
+ * - A token naming no field, or showing no values, sends nothing.
35
+ */
36
+ export declare const entryFor: ({ field, operator, text, value }: TokenWords) => string | null;
37
+ /**
38
+ * The form entry for a slotted token. See `entryFor`. The values are the text
39
+ * of the token's unslotted content, so a name or a comparison slotted into a
40
+ * chip's `field` or `operator` is not read as a value.
16
41
  */
17
42
  export declare const tokenEntry: (token: Element) => string | null;
@@ -8,16 +8,26 @@ export const suggests = (words, term) => {
8
8
  const plain = (text) => text.normalize('NFD').replace(/\p{M}/gu, '').toLowerCase();
9
9
  return term === '' || plain(words).includes(plain(term));
10
10
  };
11
- export const tokenEntry = (token) => {
12
- const written = token.getAttribute('value');
13
- if (written !== null) {
14
- return written;
11
+ export const entryFor = ({ field, operator, text, value }) => {
12
+ if (value !== null) {
13
+ return value;
15
14
  }
16
- const field = token.getAttribute('name');
17
- const values = (token.textContent ?? '').replace(/\s+/gu, ' ').trim();
15
+ const values = text.replace(/\s+/gu, ' ').trim();
18
16
  if (!field || values === '') {
19
17
  return null;
20
18
  }
21
- const negated = token.getAttribute('operator')?.startsWith('not') ? '-' : '';
22
- return `${negated}${field}:${values.replace(/\s*,\s*/gu, ',')}`;
19
+ const shown = values.replace(/\s*,\s*/gu, ',');
20
+ if (operator === 'none') {
21
+ return `-${field}:${shown}`;
22
+ }
23
+ return operator && operator !== 'any' ? `${field}[${operator}]:${shown}` : `${field}:${shown}`;
23
24
  };
25
+ export const tokenEntry = (token) => entryFor({
26
+ field: token.getAttribute('name'),
27
+ operator: token.getAttribute('operator'),
28
+ text: [...token.childNodes]
29
+ .filter((node) => !(node.nodeType === 1 && node.hasAttribute('slot')))
30
+ .map((node) => node.textContent ?? '')
31
+ .join(''),
32
+ value: token.getAttribute('value'),
33
+ });
@@ -1,9 +1,8 @@
1
1
  /**
2
2
  * What a Format Date was asked for, in its own spelling: the `Intl` options a
3
- * consumer set, and whether the timestamp is a day with no time of day.
3
+ * consumer set. The element itself is one, so it passes itself.
4
4
  */
5
5
  export interface Asked {
6
- dateOnly: boolean;
7
6
  dateStyle?: 'full' | 'long' | 'medium' | 'short' | undefined;
8
7
  day?: 'numeric' | '2-digit' | undefined;
9
8
  era?: 'long' | 'narrow' | 'short' | undefined;
@@ -26,8 +25,8 @@ export interface Asked {
26
25
  * given beside `month` or `hour`, so the fields are left out wherever a style
27
26
  * is set. `hourCycle` and `timeZone` go with either.
28
27
  *
29
- * **A day with no time is read in UTC** unless a zone is given. Parsed, it is
28
+ * **A day with no time, `dateOnly`, is read in UTC** unless a zone is given. Parsed, it is
30
29
  * midnight UTC, and read in a zone west of it that is the day before: measured
31
30
  * before this, `2026-08-04` read "August 3, 2026" in Los Angeles.
32
31
  */
33
- export declare const formatOptions: (asked: Asked) => Intl.DateTimeFormatOptions;
32
+ export declare const formatOptions: (asked: Asked, dateOnly?: boolean) => Intl.DateTimeFormatOptions;
@@ -9,7 +9,7 @@ const FIELDS = [
9
9
  'weekday',
10
10
  'year',
11
11
  ];
12
- export const formatOptions = (asked) => {
12
+ export const formatOptions = (asked, dateOnly = false) => {
13
13
  const options = {};
14
14
  const styled = asked.dateStyle !== undefined || asked.timeStyle !== undefined;
15
15
  if (styled) {
@@ -35,7 +35,7 @@ export const formatOptions = (asked) => {
35
35
  if (asked.timeZone) {
36
36
  options.timeZone = asked.timeZone;
37
37
  }
38
- else if (asked.dateOnly) {
38
+ else if (dateOnly) {
39
39
  options.timeZone = 'UTC';
40
40
  }
41
41
  return options;
@@ -25,6 +25,7 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
25
25
  * **The text refreshes on one timer shared by the page.** Each element
26
26
  * schedules an update for when its current reading expires, and an element
27
27
  * showing a date schedules none, so a long feed left open costs almost nothing.
28
+ * `frozen` draws the reading once and leaves it.
28
29
  *
29
30
  * **The output is always `<time datetime>`**, so copy and paste and scripts
30
31
  * parsing the page get the exact instant, whatever the visible text says. A
@@ -85,6 +86,19 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
85
86
  * How the era is written, such as AD, where a date is shown.
86
87
  */
87
88
  era?: 'long' | 'narrow' | 'short';
89
+ /**
90
+ * Draws an `elapsed` or `relative` reading once and leaves it, where it
91
+ * would otherwise move on as it goes stale.
92
+ *
93
+ * For a reading that describes a moment the page itself is about, such as
94
+ * "3 hours ago" in a report generated then, or a list a reader compares
95
+ * line by line while it should not change under them. The reading is taken
96
+ * when the element draws, and again whenever `date` or another option
97
+ * changes. Turned off, the reading catches up and moves on again.
98
+ * `sl-relative-time` and `wa-relative-time` keep still unless `sync` is
99
+ * set; this keeps moving unless `frozen` is.
100
+ */
101
+ frozen: boolean;
88
102
  /**
89
103
  * How the hour is written, where a time of day is shown.
90
104
  */
@@ -100,9 +114,12 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
100
114
  /**
101
115
  * The locale to format the timestamp in.
102
116
  *
103
- * Empty is the runtime's own.
117
+ * Absent is the page's: the `lang` of the nearest element with one, as
118
+ * Shoelace and Web Awesome read it, then the runtime's own.
104
119
  */
105
120
  locale: string;
121
+ /** The locale the words are written in: `locale`, or the page's `lang`. */
122
+ private get language();
106
123
  /**
107
124
  * How the minute is written, where a time of day is shown.
108
125
  */
@@ -154,18 +171,21 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
154
171
  */
155
172
  year?: 'numeric' | '2-digit';
156
173
  /**
157
- * The clock this element last drew against.
174
+ * The clock this element last drew against, moved on when the reading goes
175
+ * stale.
158
176
  *
159
- * A state field and not a read of `Date.now()` inside `render`, which would
160
- * make the template a function of something Lit cannot see change: the element
161
- * would draw the right text once and never notice it had gone stale.
177
+ * A controller's time and not a read of `Date.now()` inside `render`, which
178
+ * would make the template a function of something Lit cannot see change: the
179
+ * element would draw the right text once and never notice it had gone stale.
180
+ * The formatter says when its own answer expires, so the clock wakes at
181
+ * exactly that moment rather than polling: an item minutes old once a minute,
182
+ * an item hours old once an hour, and an item showing a date never.
162
183
  */
163
- private clock;
184
+ private readonly clock;
164
185
  /**
165
186
  * The date read out of the light DOM, where no attribute carried one.
166
187
  */
167
188
  private written;
168
- private stopTicking;
169
189
  private watching;
170
190
  /** Whether the timestamp is a day with no time, which is formatted in UTC. */
171
191
  private get dateOnly();
@@ -184,16 +204,6 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
184
204
  /** The light DOM's own text, which is the other way to write the value. */
185
205
  private read;
186
206
  private watch;
187
- /**
188
- * Schedules the next reading, and only the next one.
189
- *
190
- * The formatter says when its own answer expires, so this asks for exactly
191
- * that moment rather than polling: an item minutes old wakes once a minute, an
192
- * item hours old once an hour, and an item showing a date never, which is the
193
- * difference between a feed that costs nothing to leave open and one that
194
- * does.
195
- */
196
- private tick;
197
207
  protected render(): TemplateResult | typeof nothing;
198
208
  }
199
209
  declare global {
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { customElement, elapsedTime, HelixElement, relativeTime, subscribe, } from '@fusion.dev/helix-core';
7
+ import { customElement, elapsedTime, HelixElement, localeOf, RelativeClockController, relativeTime, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  import { formatOptions } from '../options.js';
@@ -14,12 +14,23 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
14
14
  super(...arguments);
15
15
  this.date = '';
16
16
  this.elapsed = false;
17
+ this.frozen = false;
17
18
  this.locale = '';
18
- this.clock = undefined;
19
+ this.clock = new RelativeClockController(this, {
20
+ expires: (now) => {
21
+ const moment = this.moment;
22
+ if (!moment || !this.reading) {
23
+ return undefined;
24
+ }
25
+ return this.frozen ? Number.POSITIVE_INFINITY : this.readingAt(moment, now).next;
26
+ },
27
+ });
19
28
  this.written = '';
20
- this.stopTicking = undefined;
21
29
  this.watching = undefined;
22
30
  }
31
+ get language() {
32
+ return localeOf(this, this.locale);
33
+ }
23
34
  get dateOnly() {
24
35
  return DATE_ONLY.test((this.date || this.written).trim());
25
36
  }
@@ -32,45 +43,27 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
32
43
  return Number.isNaN(parsed.getTime()) ? undefined : parsed;
33
44
  }
34
45
  get options() {
35
- return formatOptions({
36
- dateOnly: this.dateOnly,
37
- dateStyle: this.dateStyle,
38
- day: this.day,
39
- era: this.era,
40
- hour: this.hour,
41
- hourCycle: this.hourCycle,
42
- minute: this.minute,
43
- month: this.month,
44
- second: this.second,
45
- timeStyle: this.timeStyle,
46
- timeZone: this.timeZone,
47
- timeZoneName: this.timeZoneName,
48
- weekday: this.weekday,
49
- year: this.year,
50
- });
46
+ return formatOptions(this, this.dateOnly);
51
47
  }
52
48
  get reading() {
53
49
  return this.elapsed || this.relative !== undefined;
54
50
  }
55
51
  readingAt(moment, now) {
56
52
  return this.elapsed
57
- ? elapsedTime(this.locale)(moment, now)
58
- : relativeTime(this.locale, {
53
+ ? elapsedTime(this.language)(moment, now)
54
+ : relativeTime(this.language, {
59
55
  numeric: this.numeric ?? 'auto',
60
56
  style: this.relative ?? 'long',
61
57
  })(moment, now);
62
58
  }
63
59
  connectedCallback() {
64
60
  super.connectedCallback();
65
- this.tick();
66
61
  if (this.hasUpdated) {
67
62
  this.watch();
68
63
  }
69
64
  }
70
65
  disconnectedCallback() {
71
66
  super.disconnectedCallback();
72
- this.stopTicking?.();
73
- this.stopTicking = undefined;
74
67
  this.watching?.disconnect();
75
68
  this.watching = undefined;
76
69
  }
@@ -86,10 +79,11 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
86
79
  }
87
80
  if (changed.has('date') ||
88
81
  changed.has('elapsed') ||
82
+ changed.has('frozen') ||
89
83
  changed.has('locale') ||
90
84
  changed.has('numeric') ||
91
85
  changed.has('relative')) {
92
- this.tick();
86
+ this.clock.tick();
93
87
  }
94
88
  }
95
89
  read() {
@@ -99,7 +93,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
99
93
  const written = this.textContent?.trim() ?? '';
100
94
  if (written !== this.written) {
101
95
  this.written = written;
102
- this.tick();
96
+ this.clock.tick();
103
97
  }
104
98
  }
105
99
  watch() {
@@ -107,21 +101,6 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
107
101
  this.watching = new MutationObserver(() => this.read());
108
102
  this.watching.observe(this, { characterData: true, childList: true, subtree: true });
109
103
  }
110
- tick() {
111
- this.stopTicking?.();
112
- this.stopTicking = undefined;
113
- const moment = this.moment;
114
- if (!moment || !this.reading) {
115
- return;
116
- }
117
- const now = new Date();
118
- this.clock = now.getTime();
119
- const { next } = this.readingAt(moment, now);
120
- if (!Number.isFinite(next) || !this.isConnected) {
121
- return;
122
- }
123
- this.stopTicking = subscribe(next, () => this.tick());
124
- }
125
104
  render() {
126
105
  const moment = this.moment;
127
106
  if (!moment) {
@@ -129,18 +108,18 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
129
108
  }
130
109
  const datetime = this.dateOnly ? (this.date || this.written).trim() : moment.toISOString();
131
110
  if (!this.reading) {
132
- const text = new Intl.DateTimeFormat(this.locale || undefined, this.options).format(moment);
111
+ const text = new Intl.DateTimeFormat(this.language || undefined, this.options).format(moment);
133
112
  return html `<time part="time" datetime=${datetime}>${text}</time>`;
134
113
  }
135
- const now = new Date(this.clock ?? Date.now());
114
+ const now = new Date(this.clock.now);
136
115
  const zone = this.timeZone || (this.dateOnly ? 'UTC' : undefined);
137
- const whole = new Intl.DateTimeFormat(this.locale || undefined, {
116
+ const whole = new Intl.DateTimeFormat(this.language || undefined, {
138
117
  dateStyle: 'long',
139
118
  ...(this.dateOnly ? {} : { timeStyle: 'short' }),
140
119
  ...(this.hourCycle ? { hourCycle: this.hourCycle } : {}),
141
120
  ...(zone ? { timeZone: zone } : {}),
142
121
  }).format(moment);
143
- const spoken = relativeTime(this.locale, { numeric: this.numeric ?? 'auto' })(moment, now).text;
122
+ const spoken = relativeTime(this.language, { numeric: this.numeric ?? 'auto' })(moment, now).text;
144
123
  return html `<time
145
124
  part="time"
146
125
  datetime=${datetime}
@@ -164,6 +143,9 @@ __decorate([
164
143
  __decorate([
165
144
  property()
166
145
  ], HelixHeadlessFormatDate.prototype, "era", void 0);
146
+ __decorate([
147
+ property({ type: Boolean })
148
+ ], HelixHeadlessFormatDate.prototype, "frozen", void 0);
167
149
  __decorate([
168
150
  property()
169
151
  ], HelixHeadlessFormatDate.prototype, "hour", void 0);
@@ -203,9 +185,6 @@ __decorate([
203
185
  __decorate([
204
186
  property()
205
187
  ], HelixHeadlessFormatDate.prototype, "year", void 0);
206
- __decorate([
207
- state()
208
- ], HelixHeadlessFormatDate.prototype, "clock", void 0);
209
188
  __decorate([
210
189
  state()
211
190
  ], HelixHeadlessFormatDate.prototype, "written", void 0);