@fusion.dev/helix-headless 0.145.0 → 0.146.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 (278) hide show
  1. package/custom-elements.json +7373 -3849
  2. package/dist/accordion/item/accordion-item.d.ts +14 -0
  3. package/dist/accordion/item/accordion-item.js +16 -6
  4. package/dist/accordion/root/accordion-root.d.ts +8 -5
  5. package/dist/announcement/root/announcement-root.d.ts +3 -2
  6. package/dist/announcement/root/announcement-root.js +3 -1
  7. package/dist/app-header/root/app-header-root.d.ts +7 -2
  8. package/dist/app-header/root/app-header-root.js +9 -1
  9. package/dist/app-header/sectioning.d.ts +3 -1
  10. package/dist/app-header/sectioning.js +3 -2
  11. package/dist/avatar/group/avatar-group.d.ts +20 -14
  12. package/dist/avatar/group/avatar-group.js +17 -19
  13. package/dist/badge/root/badge-root.d.ts +3 -1
  14. package/dist/badge/root/badge-root.js +2 -2
  15. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  16. package/dist/bar-chart/root/bar-chart-root.js +52 -15
  17. package/dist/bar-chart/stack.d.ts +15 -0
  18. package/dist/bar-chart/stack.js +19 -0
  19. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
  20. package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
  21. package/dist/button/root/button-root.d.ts +26 -0
  22. package/dist/button/root/button-root.js +38 -18
  23. package/dist/button-group/root/button-group-root.d.ts +2 -1
  24. package/dist/button-group/root/button-group-root.js +5 -1
  25. package/dist/canvas/node/canvas-node.d.ts +4 -3
  26. package/dist/canvas/node/canvas-node.js +3 -2
  27. package/dist/canvas/root/canvas-root.js +2 -2
  28. package/dist/card/root/card-root.d.ts +24 -3
  29. package/dist/card/root/card-root.js +20 -8
  30. package/dist/carousel/root/carousel-root.d.ts +43 -4
  31. package/dist/carousel/root/carousel-root.js +40 -12
  32. package/dist/carousel/stops.d.ts +20 -0
  33. package/dist/carousel/stops.js +30 -0
  34. package/dist/chat/message/chat-message.js +5 -4
  35. package/dist/chat/naming.d.ts +5 -1
  36. package/dist/chat/naming.js +4 -2
  37. package/dist/chat/root/chat-root.d.ts +25 -3
  38. package/dist/chat/root/chat-root.js +22 -5
  39. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  40. package/dist/checkbox/root/checkbox-root.js +14 -1
  41. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  42. package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
  43. package/dist/checkbox-group/select-all.d.ts +27 -0
  44. package/dist/checkbox-group/select-all.js +12 -0
  45. package/dist/code-block/highlight.d.ts +15 -0
  46. package/dist/code-block/highlight.js +4 -0
  47. package/dist/code-block/root/code-block-root.d.ts +49 -1
  48. package/dist/code-block/root/code-block-root.js +58 -3
  49. package/dist/color-input/root/color-input-root.d.ts +3 -0
  50. package/dist/color-input/root/color-input-root.js +6 -3
  51. package/dist/color-picker/root/color-picker-root.d.ts +33 -4
  52. package/dist/color-picker/root/color-picker-root.js +80 -21
  53. package/dist/color-picker/swatches.d.ts +12 -0
  54. package/dist/color-picker/swatches.js +26 -0
  55. package/dist/combobox/root/combobox-root.d.ts +43 -0
  56. package/dist/combobox/root/combobox-root.js +79 -15
  57. package/dist/command/root/command-root.d.ts +16 -1
  58. package/dist/command/root/command-root.js +22 -4
  59. package/dist/copy-button/root/copy-button-root.d.ts +5 -0
  60. package/dist/copy-button/root/copy-button-root.js +10 -3
  61. package/dist/data-table/index.d.ts +1 -1
  62. package/dist/data-table/index.js +1 -1
  63. package/dist/data-table/keys.d.ts +24 -0
  64. package/dist/data-table/keys.js +24 -0
  65. package/dist/data-table/root/data-table-root.d.ts +27 -18
  66. package/dist/data-table/root/data-table-root.js +20 -52
  67. package/dist/data-table/tree.d.ts +16 -1
  68. package/dist/data-table/tree.js +2 -3
  69. package/dist/date-input/root/date-input-root.d.ts +3 -1
  70. package/dist/date-input/root/date-input-root.js +18 -7
  71. package/dist/date-picker/root/date-picker-root.js +12 -6
  72. package/dist/dialog/description.js +15 -1
  73. package/dist/dialog/root/dialog-root.d.ts +8 -2
  74. package/dist/dialog/root/dialog-root.js +16 -1
  75. package/dist/divider/root/divider-root.d.ts +3 -0
  76. package/dist/divider/root/divider-root.js +2 -1
  77. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  78. package/dist/donut-chart/root/donut-chart-root.js +48 -1
  79. package/dist/drawer/reveal.d.ts +8 -0
  80. package/dist/drawer/reveal.js +1 -0
  81. package/dist/drawer/root/drawer-root.d.ts +59 -0
  82. package/dist/drawer/root/drawer-root.js +63 -4
  83. package/dist/drilldown/item/drilldown-item.js +1 -1
  84. package/dist/drilldown/root/drilldown-root.d.ts +21 -3
  85. package/dist/drilldown/root/drilldown-root.js +21 -3
  86. package/dist/element-events.generated.js +31 -5
  87. package/dist/empty/root/empty-root.d.ts +3 -1
  88. package/dist/empty/root/empty-root.js +3 -2
  89. package/dist/file-input/root/file-input-root.d.ts +69 -6
  90. package/dist/file-input/root/file-input-root.js +82 -19
  91. package/dist/file-input/screen.d.ts +2 -1
  92. package/dist/filter-input/menu/filter-menu.d.ts +2 -0
  93. package/dist/filter-input/menu/filter-menu.js +12 -4
  94. package/dist/filter-input/root/filter-input-root.d.ts +30 -6
  95. package/dist/filter-input/root/filter-input-root.js +1 -1
  96. package/dist/filter-input/suggest.d.ts +28 -3
  97. package/dist/filter-input/suggest.js +18 -8
  98. package/dist/format-date/root/format-date-root.d.ts +9 -16
  99. package/dist/format-date/root/format-date-root.js +10 -27
  100. package/dist/heatmap/root/heatmap-root.d.ts +24 -13
  101. package/dist/heatmap/root/heatmap-root.js +34 -12
  102. package/dist/icon/root/icon-root.d.ts +12 -1
  103. package/dist/icon/root/icon-root.js +21 -10
  104. package/dist/icon/settle.d.ts +7 -0
  105. package/dist/icon/settle.js +10 -0
  106. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  107. package/dist/image/root/image-root.d.ts +5 -1
  108. package/dist/image/root/image-root.js +1 -1
  109. package/dist/input/root/input-root.d.ts +12 -2
  110. package/dist/input/root/input-root.js +11 -2
  111. package/dist/kbd/root/kbd-root.d.ts +35 -1
  112. package/dist/kbd/root/kbd-root.js +23 -4
  113. package/dist/legend/root/legend-root.d.ts +55 -8
  114. package/dist/legend/root/legend-root.js +55 -13
  115. package/dist/lightbox/root/lightbox-root.d.ts +49 -6
  116. package/dist/lightbox/root/lightbox-root.js +86 -19
  117. package/dist/lightbox/zoom-controller.d.ts +59 -0
  118. package/dist/lightbox/zoom-controller.js +128 -0
  119. package/dist/lightbox/zoom.d.ts +22 -0
  120. package/dist/lightbox/zoom.js +16 -0
  121. package/dist/line-chart/root/line-chart-root.d.ts +22 -1
  122. package/dist/line-chart/root/line-chart-root.js +21 -1
  123. package/dist/list/item/list-item.d.ts +2 -0
  124. package/dist/list/item/list-item.js +11 -2
  125. package/dist/list/root/list-root.d.ts +62 -13
  126. package/dist/list/root/list-root.js +70 -13
  127. package/dist/list/selection.d.ts +37 -7
  128. package/dist/list/selection.js +16 -7
  129. package/dist/listbox/root/listbox-root.d.ts +37 -1
  130. package/dist/listbox/root/listbox-root.js +49 -3
  131. package/dist/loader/busy.d.ts +10 -0
  132. package/dist/loader/busy.js +11 -0
  133. package/dist/loader/root/loader-root.d.ts +9 -2
  134. package/dist/loader/root/loader-root.js +23 -3
  135. package/dist/megamenu/root/megamenu-root.d.ts +51 -10
  136. package/dist/megamenu/root/megamenu-root.js +76 -5
  137. package/dist/menu/item/menu-item.d.ts +51 -2
  138. package/dist/menu/item/menu-item.js +47 -23
  139. package/dist/menu/root/menu-root.d.ts +14 -0
  140. package/dist/menu/root/menu-root.js +2 -2
  141. package/dist/meter/root/meter-root.d.ts +20 -1
  142. package/dist/meter/root/meter-root.js +11 -15
  143. package/dist/navigation/root/navigation-root.d.ts +2 -1
  144. package/dist/navigation/root/navigation-root.js +2 -2
  145. package/dist/notifications/root/notifications-root.d.ts +10 -3
  146. package/dist/notifications/root/notifications-root.js +19 -7
  147. package/dist/number-input/root/number-input-root.d.ts +17 -8
  148. package/dist/number-input/root/number-input-root.js +2 -7
  149. package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
  150. package/dist/object-inspector/root/object-inspector-root.js +117 -76
  151. package/dist/object-inspector/rows.d.ts +18 -0
  152. package/dist/object-inspector/rows.js +33 -0
  153. package/dist/option/root/option-root.d.ts +5 -3
  154. package/dist/outline/root/outline-root.d.ts +18 -0
  155. package/dist/outline/root/outline-root.js +23 -5
  156. package/dist/pagination/size/pagination-size.d.ts +1 -0
  157. package/dist/pagination/size/pagination-size.js +1 -1
  158. package/dist/pin-input/code.d.ts +10 -0
  159. package/dist/pin-input/code.js +13 -0
  160. package/dist/pin-input/root/pin-input-root.d.ts +25 -1
  161. package/dist/pin-input/root/pin-input-root.js +10 -11
  162. package/dist/popover/hide-outside.d.ts +14 -0
  163. package/dist/popover/hide-outside.js +41 -0
  164. package/dist/popover/root/popover-root.d.ts +57 -7
  165. package/dist/popover/root/popover-root.js +58 -3
  166. package/dist/progress/root/progress-root.d.ts +20 -0
  167. package/dist/progress/root/progress-root.js +15 -15
  168. package/dist/qr-code/export.d.ts +26 -1
  169. package/dist/qr-code/export.js +14 -0
  170. package/dist/qr-code/root/qr-code-root.d.ts +19 -5
  171. package/dist/qr-code/root/qr-code-root.js +58 -9
  172. package/dist/quote/marks.d.ts +8 -0
  173. package/dist/quote/marks.js +5 -0
  174. package/dist/quote/root/quote-root.d.ts +14 -2
  175. package/dist/quote/root/quote-root.js +23 -1
  176. package/dist/radio/root/radio-root.d.ts +6 -2
  177. package/dist/radio/root/radio-root.js +6 -1
  178. package/dist/rating/root/rating-root.d.ts +9 -4
  179. package/dist/rating/root/rating-root.js +31 -7
  180. package/dist/rating/steps.d.ts +7 -0
  181. package/dist/rating/steps.js +9 -0
  182. package/dist/scatter-chart/fit.d.ts +15 -0
  183. package/dist/scatter-chart/fit.js +35 -0
  184. package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
  185. package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
  186. package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
  187. package/dist/scroll-area/root/scroll-area-root.js +57 -173
  188. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  189. package/dist/scroll-area/scrollbar-controller.js +172 -0
  190. package/dist/scroll-area/scrollbar.d.ts +27 -0
  191. package/dist/scroll-area/scrollbar.js +9 -0
  192. package/dist/select/root/select-root.d.ts +15 -0
  193. package/dist/select/root/select-root.js +18 -6
  194. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  195. package/dist/skeleton/root/skeleton-root.js +4 -2
  196. package/dist/skip-link/root/skip-link-root.js +2 -2
  197. package/dist/slider/root/slider-root.d.ts +41 -4
  198. package/dist/slider/root/slider-root.js +23 -3
  199. package/dist/sparkline/readings.d.ts +18 -0
  200. package/dist/sparkline/readings.js +19 -0
  201. package/dist/sparkline/root/sparkline-root.d.ts +78 -7
  202. package/dist/sparkline/root/sparkline-root.js +118 -23
  203. package/dist/speed-dial/root/speed-dial-root.js +2 -2
  204. package/dist/splitter/root/splitter-root.d.ts +7 -12
  205. package/dist/splitter/root/splitter-root.js +209 -204
  206. package/dist/stat/root/stat-root.d.ts +14 -5
  207. package/dist/stat/root/stat-root.js +21 -5
  208. package/dist/steps/reach.d.ts +5 -0
  209. package/dist/steps/reach.js +3 -0
  210. package/dist/steps/root/steps-root.d.ts +49 -3
  211. package/dist/steps/root/steps-root.js +44 -5
  212. package/dist/steps/step/step.d.ts +7 -0
  213. package/dist/steps/step/step.js +7 -2
  214. package/dist/switch/root/switch-root.d.ts +10 -0
  215. package/dist/table/column/table-column.d.ts +0 -10
  216. package/dist/table/column/table-column.js +3 -19
  217. package/dist/table/root/table-root.d.ts +31 -10
  218. package/dist/table/root/table-root.js +2 -13
  219. package/dist/tabs/panel/tab-panel.d.ts +16 -3
  220. package/dist/tabs/panel/tab-panel.js +34 -5
  221. package/dist/tabs/root/tabs-root.d.ts +12 -0
  222. package/dist/tabs/root/tabs-root.js +1 -1
  223. package/dist/tabs/tab/tab.d.ts +5 -0
  224. package/dist/tabs/tab/tab.js +5 -2
  225. package/dist/tag/group/tag-group.d.ts +31 -4
  226. package/dist/tag/group/tag-group.js +46 -7
  227. package/dist/tag/root/tag-root.js +9 -2
  228. package/dist/textarea/root/textarea-root.d.ts +28 -1
  229. package/dist/textarea/root/textarea-root.js +40 -1
  230. package/dist/time-input/root/time-input-root.d.ts +5 -1
  231. package/dist/time-input/root/time-input-root.js +16 -8
  232. package/dist/time-picker/root/time-picker-root.d.ts +18 -4
  233. package/dist/time-picker/root/time-picker-root.js +7 -10
  234. package/dist/time-picker/wheel-name.d.ts +9 -0
  235. package/dist/time-picker/wheel-name.js +15 -0
  236. package/dist/timeline/group/timeline-group.js +2 -2
  237. package/dist/toast/item/toast-item.d.ts +14 -1
  238. package/dist/toast/item/toast-item.js +22 -5
  239. package/dist/toast/root/toast-root.d.ts +6 -0
  240. package/dist/toast/root/toast-root.js +16 -1
  241. package/dist/toggle/group/toggle-group.d.ts +24 -3
  242. package/dist/toggle/group/toggle-group.js +34 -5
  243. package/dist/tooltip/root/tooltip-root.d.ts +13 -2
  244. package/dist/tooltip/root/tooltip-root.js +9 -1
  245. package/dist/tour/back.d.ts +10 -0
  246. package/dist/tour/back.js +8 -0
  247. package/dist/tour/root/tour-root.d.ts +30 -2
  248. package/dist/tour/root/tour-root.js +34 -8
  249. package/dist/tree/item/tree-item.d.ts +7 -3
  250. package/dist/tree/item/tree-item.js +3 -0
  251. package/dist/tree/root/tree-root.d.ts +24 -3
  252. package/dist/tree/root/tree-root.js +32 -13
  253. package/dist/tree/selection.js +2 -15
  254. package/dist/trend/root/trend-root.d.ts +43 -18
  255. package/dist/trend/root/trend-root.js +31 -6
  256. package/dist/video/media-events.d.ts +13 -18
  257. package/dist/video/media-events.js +1 -5
  258. package/dist/video/root/video-root.d.ts +18 -5
  259. package/dist/video/root/video-root.js +19 -10
  260. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
  261. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  262. package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
  263. package/dist/virtual-list/fill.d.ts +0 -8
  264. package/dist/virtual-list/fill.js +1 -17
  265. package/dist/virtual-list/plan.d.ts +49 -0
  266. package/dist/virtual-list/plan.js +16 -0
  267. package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
  268. package/dist/virtual-list/root/virtual-list-root.js +183 -40
  269. package/lint.json +1 -1
  270. package/package.json +8 -8
  271. package/types/jsx.d.ts +4577 -835
  272. package/types/vue.d.ts +926 -168
  273. package/dist/chat/relative-clock.d.ts +0 -39
  274. package/dist/chat/relative-clock.js +0 -31
  275. package/dist/data-table/root/order.d.ts +0 -141
  276. package/dist/data-table/root/order.js +0 -76
  277. package/dist/tag/selection.d.ts +0 -10
  278. package/dist/tag/selection.js +0 -12
@@ -42,20 +42,28 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
42
42
  target: () => this.partNamed('control'),
43
43
  });
44
44
  this.accept = '';
45
+ this.addedText = 'Added: {names}';
45
46
  this.directory = false;
46
47
  this.locale = '';
47
48
  this.multiple = false;
48
49
  this.rejectedText = 'Not added: {names}';
50
+ this.removedText = 'Removed: {name}';
49
51
  this.removeLabel = 'Remove {name}';
50
52
  this.triggerLabel = 'Choose files';
51
53
  this.status = new StatusController(this);
54
+ this.removeIcon = undefined;
55
+ this.removeIcons = new Map();
56
+ this.handleRemoveIcon = (event) => {
57
+ this.removeIcons.clear();
58
+ this.removeIcon = event.target.assignedElements({ flatten: true })[0];
59
+ };
52
60
  this.handlePaste = (event) => {
53
61
  const pasted = [...(event.clipboardData?.files ?? [])];
54
62
  if (this.isDisabled || pasted.length === 0) {
55
63
  return;
56
64
  }
57
65
  event.preventDefault();
58
- this.take(pasted, this.multiple ? this.files : []);
66
+ this.take(pasted, this.files);
59
67
  };
60
68
  this.dropping = false;
61
69
  this.committed = [];
@@ -84,7 +92,7 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
84
92
  if (dropped.length === 0) {
85
93
  return;
86
94
  }
87
- this.take(dropped, this.multiple ? this.files : []);
95
+ this.take(dropped, this.files);
88
96
  };
89
97
  this.handleRemove = (event) => {
90
98
  const at = Number(event.currentTarget.dataset.at);
@@ -106,21 +114,50 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
106
114
  multiple: this.multiple || picked,
107
115
  validate: this.validate,
108
116
  });
109
- const same = (one, two) => one.length === two.length && one.every((file, at) => file === two[at]);
110
- if (picked || !(same(kept, this.committed) && same(kept, this.files))) {
111
- this.commit(kept);
117
+ const taken = kept.filter((file) => !keeping.includes(file));
118
+ const transform = this.transformFiles;
119
+ if (!transform || taken.length === 0) {
120
+ this.finish(kept, taken, refused, picked);
121
+ return;
112
122
  }
123
+ const held = kept.filter((file) => keeping.includes(file));
124
+ Promise.resolve()
125
+ .then(() => transform(taken))
126
+ .then((made) => this.finish([...held, ...made], made, refused, picked), (error) => {
127
+ const message = error instanceof Error ? error.message : String(error);
128
+ this.finish(held, [], [...refused, ...taken.map((file) => ({ file, message, reason: 'invalid' }))], picked);
129
+ });
130
+ }
131
+ finish(next, added, refused, picked) {
132
+ const same = (one, two) => one.length === two.length && one.every((file, at) => file === two[at]);
133
+ const moved = picked || !(same(next, this.committed) && same(next, this.files));
134
+ const applied = moved && this.commit(next);
113
135
  if (refused.length > 0) {
114
- this.refuse(refused);
136
+ this.dispatchEvent(new HelixRejectEvent({ files: refused }));
137
+ }
138
+ const words = [
139
+ applied && !picked && added.length > 0 ? this.listed(this.addedText, added) : '',
140
+ refused.length > 0
141
+ ? this.listed(this.rejectedText, refused.map((one) => one.file))
142
+ : '',
143
+ ].filter((one) => one !== '');
144
+ if (words.length > 0) {
145
+ this.status.say(words.join(' '));
115
146
  }
116
147
  }
117
- refuse(refused) {
118
- this.dispatchEvent(new HelixRejectEvent({ files: refused }));
119
- const words = fillTemplate(this.rejectedText, {
120
- count: formatNumbers(this.lang)(refused.length),
121
- names: new Intl.ListFormat(this.lang || undefined, { style: 'short', type: 'unit' }).format(refused.map((one) => one.file.name)),
148
+ listed(sentence, files) {
149
+ return fillTemplate(sentence, {
150
+ count: formatNumbers(this.lang)(files.length),
151
+ names: new Intl.ListFormat(this.lang || undefined, { style: 'short', type: 'unit' }).format(files.map((file) => file.name)),
122
152
  });
123
- this.status.say(words);
153
+ }
154
+ removeMark(at) {
155
+ if (!this.removeIcon) {
156
+ return drawIcon(trash);
157
+ }
158
+ const held = this.removeIcons.get(at) ?? this.removeIcon.cloneNode(true);
159
+ this.removeIcons.set(at, held);
160
+ return held;
124
161
  }
125
162
  get files() {
126
163
  return [...(this.control?.files ?? [])];
@@ -132,12 +169,15 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
132
169
  this.commit([]);
133
170
  }
134
171
  removeAt(at) {
135
- this.commit(this.files.filter((_, index) => index !== at));
172
+ const gone = this.files[at];
173
+ if (gone && this.commit(this.files.filter((_, index) => index !== at))) {
174
+ this.status.say(fillTemplate(this.removedText, { name: gone.name }));
175
+ }
136
176
  }
137
177
  commit(next) {
138
178
  const control = this.control;
139
179
  if (!control) {
140
- return;
180
+ return false;
141
181
  }
142
182
  const previous = this.committed;
143
183
  const applied = requestChange({
@@ -152,6 +192,7 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
152
192
  if (!applied) {
153
193
  this.put(control, previous);
154
194
  }
195
+ return applied;
155
196
  }
156
197
  put(control, files) {
157
198
  if (files.length === 0) {
@@ -197,6 +238,8 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
197
238
  updated(changed) {
198
239
  super.updated(changed);
199
240
  this.sync();
241
+ this.toggleState('dropping', this.dropping);
242
+ this.toggleState('has-files', this.files.length > 0);
200
243
  }
201
244
  focus(options) {
202
245
  this.control?.focus(options);
@@ -246,6 +289,9 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
246
289
  <slot name="trigger">${this.triggerLabel}</slot>
247
290
  </label>
248
291
  </div>
292
+ <!-- Hidden, because this is where the icon arrives: each remove button
293
+ shows a copy. -->
294
+ <slot name="remove-icon" hidden @slotchange=${this.handleRemoveIcon}></slot>
249
295
  <!-- The hint sits under the field and the list goes last, which is the
250
296
  one ordering decision this component makes differently from the way it
251
297
  reads. Reasoning above renderMeta. -->
@@ -256,10 +302,12 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
256
302
  : html `<ul part="list">
257
303
  ${files.map((file, at) => html `<li part="file">
258
304
  <span part="detail">
259
- <span part="name">${file.name}</span>
260
- <span part="meta">
261
- ${this.renderMeta(file)}
262
- </span>
305
+ ${this.renderFile
306
+ ? this.renderFile(file, at)
307
+ : html `<span part="name">${file.name}</span>
308
+ <span part="meta">
309
+ ${this.renderMeta(file)}
310
+ </span>`}
263
311
  </span>
264
312
  <button
265
313
  part="remove"
@@ -269,7 +317,7 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
269
317
  ?disabled=${this.isDisabled}
270
318
  @click=${this.handleRemove}
271
319
  >
272
- ${drawIcon(trash)}
320
+ ${this.removeMark(at)}
273
321
  </button>
274
322
  </li>`)}
275
323
  </ul>`}`;
@@ -278,6 +326,9 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
278
326
  __decorate([
279
327
  property()
280
328
  ], HelixHeadlessFileInput.prototype, "accept", void 0);
329
+ __decorate([
330
+ property({ attribute: 'added-text' })
331
+ ], HelixHeadlessFileInput.prototype, "addedText", void 0);
281
332
  __decorate([
282
333
  property()
283
334
  ], HelixHeadlessFileInput.prototype, "capture", void 0);
@@ -299,15 +350,27 @@ __decorate([
299
350
  __decorate([
300
351
  property({ attribute: 'rejected-text' })
301
352
  ], HelixHeadlessFileInput.prototype, "rejectedText", void 0);
353
+ __decorate([
354
+ property({ attribute: 'removed-text' })
355
+ ], HelixHeadlessFileInput.prototype, "removedText", void 0);
302
356
  __decorate([
303
357
  property({ attribute: 'remove-label' })
304
358
  ], HelixHeadlessFileInput.prototype, "removeLabel", void 0);
359
+ __decorate([
360
+ property({ attribute: false })
361
+ ], HelixHeadlessFileInput.prototype, "renderFile", void 0);
362
+ __decorate([
363
+ property({ attribute: false })
364
+ ], HelixHeadlessFileInput.prototype, "transformFiles", void 0);
305
365
  __decorate([
306
366
  property({ attribute: 'trigger-label' })
307
367
  ], HelixHeadlessFileInput.prototype, "triggerLabel", void 0);
308
368
  __decorate([
309
369
  property({ attribute: false })
310
370
  ], HelixHeadlessFileInput.prototype, "validate", void 0);
371
+ __decorate([
372
+ state()
373
+ ], HelixHeadlessFileInput.prototype, "removeIcon", void 0);
311
374
  __decorate([
312
375
  state()
313
376
  ], HelixHeadlessFileInput.prototype, "dropping", void 0);
@@ -27,7 +27,8 @@ export declare const accepts: (file: File, accept: string) => boolean;
27
27
  /**
28
28
  * Screens arriving files against the rules, given the files the field keeps.
29
29
  * `kept` is what the field holds afterward: the files it keeps and the
30
- * arrivals it took, or for a single-file field the last arrival it took.
30
+ * arrivals it took, or for a single-file field the last arrival it took, and
31
+ * the file it keeps when it took none.
31
32
  */
32
33
  export declare const screenFiles: (arriving: File[], keeping: File[], rules: ScreenRules) => {
33
34
  kept: File[];
@@ -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`,
@@ -364,7 +364,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
364
364
  super.updated(changed);
365
365
  this.releaseCaret?.();
366
366
  this.releaseCaret = undefined;
367
- this.internals.setFormValue(this.formValue());
367
+ this.internals.setFormValue(this.formValue(), this.value);
368
368
  this.sayCount();
369
369
  const control = this.control;
370
370
  if (control) {
@@ -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
+ });
@@ -154,18 +154,21 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
154
154
  */
155
155
  year?: 'numeric' | '2-digit';
156
156
  /**
157
- * The clock this element last drew against.
157
+ * The clock this element last drew against, moved on when the reading goes
158
+ * stale.
158
159
  *
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.
160
+ * A controller's time and not a read of `Date.now()` inside `render`, which
161
+ * would make the template a function of something Lit cannot see change: the
162
+ * element would draw the right text once and never notice it had gone stale.
163
+ * The formatter says when its own answer expires, so the clock wakes at
164
+ * exactly that moment rather than polling: an item minutes old once a minute,
165
+ * an item hours old once an hour, and an item showing a date never.
162
166
  */
163
- private clock;
167
+ private readonly clock;
164
168
  /**
165
169
  * The date read out of the light DOM, where no attribute carried one.
166
170
  */
167
171
  private written;
168
- private stopTicking;
169
172
  private watching;
170
173
  /** Whether the timestamp is a day with no time, which is formatted in UTC. */
171
174
  private get dateOnly();
@@ -184,16 +187,6 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
184
187
  /** The light DOM's own text, which is the other way to write the value. */
185
188
  private read;
186
189
  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
190
  protected render(): TemplateResult | typeof nothing;
198
191
  }
199
192
  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, 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';
@@ -15,9 +15,13 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
15
15
  this.date = '';
16
16
  this.elapsed = false;
17
17
  this.locale = '';
18
- this.clock = undefined;
18
+ this.clock = new RelativeClockController(this, {
19
+ expires: (now) => {
20
+ const moment = this.moment;
21
+ return moment && this.reading ? this.readingAt(moment, now).next : undefined;
22
+ },
23
+ });
19
24
  this.written = '';
20
- this.stopTicking = undefined;
21
25
  this.watching = undefined;
22
26
  }
23
27
  get dateOnly() {
@@ -62,15 +66,12 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
62
66
  }
63
67
  connectedCallback() {
64
68
  super.connectedCallback();
65
- this.tick();
66
69
  if (this.hasUpdated) {
67
70
  this.watch();
68
71
  }
69
72
  }
70
73
  disconnectedCallback() {
71
74
  super.disconnectedCallback();
72
- this.stopTicking?.();
73
- this.stopTicking = undefined;
74
75
  this.watching?.disconnect();
75
76
  this.watching = undefined;
76
77
  }
@@ -89,7 +90,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
89
90
  changed.has('locale') ||
90
91
  changed.has('numeric') ||
91
92
  changed.has('relative')) {
92
- this.tick();
93
+ this.clock.tick();
93
94
  }
94
95
  }
95
96
  read() {
@@ -99,7 +100,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
99
100
  const written = this.textContent?.trim() ?? '';
100
101
  if (written !== this.written) {
101
102
  this.written = written;
102
- this.tick();
103
+ this.clock.tick();
103
104
  }
104
105
  }
105
106
  watch() {
@@ -107,21 +108,6 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
107
108
  this.watching = new MutationObserver(() => this.read());
108
109
  this.watching.observe(this, { characterData: true, childList: true, subtree: true });
109
110
  }
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
111
  render() {
126
112
  const moment = this.moment;
127
113
  if (!moment) {
@@ -132,7 +118,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
132
118
  const text = new Intl.DateTimeFormat(this.locale || undefined, this.options).format(moment);
133
119
  return html `<time part="time" datetime=${datetime}>${text}</time>`;
134
120
  }
135
- const now = new Date(this.clock ?? Date.now());
121
+ const now = new Date(this.clock.now);
136
122
  const zone = this.timeZone || (this.dateOnly ? 'UTC' : undefined);
137
123
  const whole = new Intl.DateTimeFormat(this.locale || undefined, {
138
124
  dateStyle: 'long',
@@ -203,9 +189,6 @@ __decorate([
203
189
  __decorate([
204
190
  property()
205
191
  ], HelixHeadlessFormatDate.prototype, "year", void 0);
206
- __decorate([
207
- state()
208
- ], HelixHeadlessFormatDate.prototype, "clock", void 0);
209
192
  __decorate([
210
193
  state()
211
194
  ], HelixHeadlessFormatDate.prototype, "written", void 0);
@@ -1,6 +1,7 @@
1
1
  import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
2
2
  import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
3
  import '../../tooltip/index.js';
4
+ import { type Reading } from './buckets.js';
4
5
  declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface);
5
6
  /**
6
7
  * @summary A strip of cells, each colored by its reading, for uptime, contributions, or activity.
@@ -30,7 +31,13 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
30
31
  * down arrows move a cell, the left and right arrows move a column, which is a
31
32
  * week with `rows="7"`, and Home and End go to the first and the last. The
32
33
  * tooltip follows, the `live` part says the cell's row in words, and Escape
33
- * puts the tooltip away.
34
+ * puts the tooltip away. PageUp and PageDown move four columns, which is four
35
+ * weeks with `rows="7"`.
36
+ *
37
+ * **The strip describes itself.** The `overview` part says the busiest
38
+ * reading and the total of the readings drawn, "Busiest: 11 Jun 12; Total
39
+ * 84", and the strip is described by it, as every chart is by its summary.
40
+ * Hide it visually. The `summary` slot is still yours, for words of your own.
34
41
  *
35
42
  * @since 0.1.0
36
43
  * @status stable
@@ -51,6 +58,7 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
51
58
  * @csspart footer - The three-slot row under the strip.
52
59
  * @csspart live - The readout: a polite live region that says the cell the keys moved to. Hide it visually.
53
60
  * @csspart mark - The invisible point the tooltip is anchored to.
61
+ * @csspart overview - The busiest reading and the total of the readings drawn, written as a sentence for screen readers, which describes the strip. Rendered once there are cells. Hide it visually.
54
62
  * @csspart start - The leading slot's box.
55
63
  * @csspart strip - The grid of cells, which takes focus to be read by key. It is named by the host's `aria-labelledby` or `aria-label`, then by `label`, then by the caption of the table.
56
64
  * @csspart summary - The middle slot's box.
@@ -87,6 +95,10 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
87
95
  * @cssproperty --heatmap-tone-warning - The color of the `warning` tone.
88
96
  */
89
97
  export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
98
+ /**
99
+ * The word the `overview` puts before the busiest reading.
100
+ */
101
+ busiestLabel: string;
90
102
  /**
91
103
  * Shown when the table has no readings in it.
92
104
  *
@@ -151,6 +163,10 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
151
163
  * no order in it.
152
164
  */
153
165
  tones: string;
166
+ /**
167
+ * The word the `overview` puts before the total of the readings drawn.
168
+ */
169
+ totalLabel: string;
154
170
  /**
155
171
  * How many cells are actually drawn.
156
172
  *
@@ -197,18 +213,6 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
197
213
  * image a reader lands on. The host is a generic around it.
198
214
  */
199
215
  protected readonly aria: AriaForwardController;
200
- /**
201
- * Hears an `aria-label` written on the element, which no property mirrors.
202
- *
203
- * Lit observes the attributes of its own properties only, and `ariaLabel`
204
- * belongs to the platform.
205
- */
206
- static get observedAttributes(): string[];
207
- /**
208
- * Called by the browser when an observed attribute changes. A new
209
- * `aria-label` asks for an update, because it names the strip.
210
- */
211
- attributeChangedCallback(name: string, old: string | null, value: string | null): void;
212
216
  private observer;
213
217
  private announced;
214
218
  /**
@@ -314,6 +318,13 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
314
318
  private markEmpty;
315
319
  protected updated(changed: PropertyValues): void;
316
320
  protected render(): TemplateResult;
321
+ /**
322
+ * What the strip shows, in a sentence: the busiest reading drawn, as the
323
+ * table writes it, and the total of them all, in `locale`. The strip is
324
+ * described by it, so a reader landing on the strip hears what it holds
325
+ * before walking it.
326
+ */
327
+ protected renderOverview(cells: Reading[]): TemplateResult;
317
328
  /**
318
329
  * The bubble over the cell a pointer is resting on.
319
330
  *