@fusion.dev/helix-core 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 (302) hide show
  1. package/custom-elements.json +6585 -1920
  2. package/dist/controllers/aria-forward-controller/aria-forward-controller.d.ts +3 -2
  3. package/dist/controllers/aria-forward-controller/aria-forward-controller.js +8 -17
  4. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +71 -3
  5. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +50 -9
  6. package/dist/controllers/chart-pointer-controller/reading-step.d.ts +7 -1
  7. package/dist/controllers/chart-pointer-controller/reading-step.js +5 -0
  8. package/dist/controllers/copy-controller/copy-controller.d.ts +4 -1
  9. package/dist/controllers/copy-controller/copy-controller.js +2 -1
  10. package/dist/controllers/countdown-controller/countdown-controller.d.ts +4 -1
  11. package/dist/controllers/countdown-controller/countdown-controller.js +3 -1
  12. package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.d.ts +14 -55
  13. package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.js +7 -39
  14. package/dist/controllers/relative-clock-controller/relative-clock-controller.d.ts +44 -0
  15. package/dist/controllers/relative-clock-controller/relative-clock-controller.js +31 -0
  16. package/dist/controllers/source-controller/source-controller.d.ts +10 -3
  17. package/dist/controllers/source-controller/source-controller.js +9 -4
  18. package/dist/controllers/swipe-controller/swipe-controller.d.ts +10 -1
  19. package/dist/controllers/swipe-controller/swipe-controller.js +1 -1
  20. package/dist/controllers/virtualize-controller/virtualize-controller.d.ts +48 -1
  21. package/dist/controllers/virtualize-controller/virtualize-controller.js +52 -7
  22. package/dist/events/action.d.ts +12 -0
  23. package/dist/events/action.js +6 -0
  24. package/dist/events/activate.d.ts +22 -0
  25. package/dist/events/activate.js +11 -0
  26. package/dist/events/aura-fallback.d.ts +12 -0
  27. package/dist/events/aura-fallback.js +11 -0
  28. package/dist/events/band.d.ts +13 -0
  29. package/dist/events/band.js +11 -0
  30. package/dist/events/before-activate.d.ts +24 -0
  31. package/dist/events/before-activate.js +11 -0
  32. package/dist/events/before-change.d.ts +26 -0
  33. package/dist/events/before-change.js +11 -0
  34. package/dist/events/before-close.d.ts +6 -0
  35. package/dist/events/before-close.js +11 -0
  36. package/dist/events/before-collapse.d.ts +6 -0
  37. package/dist/events/before-collapse.js +11 -0
  38. package/dist/events/before-edit.d.ts +6 -0
  39. package/dist/events/before-edit.js +11 -0
  40. package/dist/events/before-move.d.ts +17 -0
  41. package/dist/events/before-move.js +11 -0
  42. package/dist/events/before-open.d.ts +17 -0
  43. package/dist/events/before-open.js +11 -0
  44. package/dist/events/before-panel-resize.d.ts +13 -0
  45. package/dist/events/before-panel-resize.js +11 -0
  46. package/dist/events/before-pin.d.ts +6 -0
  47. package/dist/events/before-pin.js +11 -0
  48. package/dist/events/before-reconnect.d.ts +14 -0
  49. package/dist/events/before-reconnect.js +11 -0
  50. package/dist/events/before-relabel.d.ts +15 -0
  51. package/dist/events/before-relabel.js +11 -0
  52. package/dist/events/before-resize.d.ts +6 -0
  53. package/dist/events/before-resize.js +11 -0
  54. package/dist/events/before-split.d.ts +12 -0
  55. package/dist/events/before-split.js +11 -0
  56. package/dist/events/before-toggle.d.ts +23 -0
  57. package/dist/events/before-toggle.js +11 -0
  58. package/dist/events/canvas-edit.d.ts +16 -0
  59. package/dist/events/canvas-edit.js +11 -0
  60. package/dist/events/canvas-pan.d.ts +13 -0
  61. package/dist/events/canvas-pan.js +11 -0
  62. package/dist/events/canvas-view.d.ts +14 -0
  63. package/dist/events/canvas-view.js +11 -0
  64. package/dist/events/canvas-zoom.d.ts +6 -0
  65. package/dist/events/canvas-zoom.js +11 -0
  66. package/dist/events/caret.d.ts +17 -0
  67. package/dist/events/caret.js +11 -0
  68. package/dist/events/clear.d.ts +11 -0
  69. package/dist/events/clear.js +6 -0
  70. package/dist/events/collapse.d.ts +12 -0
  71. package/dist/events/collapse.js +11 -0
  72. package/dist/events/complete.d.ts +26 -0
  73. package/dist/events/complete.js +11 -0
  74. package/dist/events/connect.d.ts +14 -0
  75. package/dist/events/connect.js +11 -0
  76. package/dist/events/console.d.ts +13 -0
  77. package/dist/events/console.js +11 -0
  78. package/dist/events/copy-error.d.ts +9 -0
  79. package/dist/events/copy-error.js +6 -0
  80. package/dist/events/copy.d.ts +12 -0
  81. package/dist/events/copy.js +10 -0
  82. package/dist/events/create.d.ts +18 -0
  83. package/dist/events/create.js +11 -0
  84. package/dist/events/details.d.ts +459 -0
  85. package/dist/events/details.js +1 -0
  86. package/dist/events/dismiss.d.ts +16 -0
  87. package/dist/events/dismiss.js +11 -0
  88. package/dist/events/edit.d.ts +12 -0
  89. package/dist/events/edit.js +11 -0
  90. package/dist/events/end.d.ts +9 -0
  91. package/dist/events/end.js +6 -0
  92. package/dist/events/events.d.ts +113 -1478
  93. package/dist/events/events.js +93 -863
  94. package/dist/events/expand.d.ts +10 -0
  95. package/dist/events/expand.js +11 -0
  96. package/dist/events/facet.d.ts +17 -0
  97. package/dist/events/facet.js +11 -0
  98. package/dist/events/filter.d.ts +12 -0
  99. package/dist/events/filter.js +11 -0
  100. package/dist/events/filtered.d.ts +12 -0
  101. package/dist/events/filtered.js +11 -0
  102. package/dist/events/graph-filter.d.ts +10 -0
  103. package/dist/events/graph-filter.js +11 -0
  104. package/dist/events/graph-layout.d.ts +10 -0
  105. package/dist/events/graph-layout.js +11 -0
  106. package/dist/events/graph-pan.d.ts +9 -0
  107. package/dist/events/graph-pan.js +11 -0
  108. package/dist/events/graph-part-change.d.ts +10 -0
  109. package/dist/events/graph-part-change.js +11 -0
  110. package/dist/events/graph-ready.d.ts +8 -0
  111. package/dist/events/graph-ready.js +6 -0
  112. package/dist/events/graph-signal.d.ts +11 -0
  113. package/dist/events/graph-signal.js +11 -0
  114. package/dist/events/graph-zoom.d.ts +6 -0
  115. package/dist/events/graph-zoom.js +11 -0
  116. package/dist/events/history.d.ts +16 -0
  117. package/dist/events/history.js +11 -0
  118. package/dist/events/load-more.d.ts +12 -0
  119. package/dist/events/load-more.js +6 -0
  120. package/dist/events/load.d.ts +12 -0
  121. package/dist/events/load.js +6 -0
  122. package/dist/events/map-cluster.d.ts +15 -0
  123. package/dist/events/map-cluster.js +11 -0
  124. package/dist/events/map-pan.d.ts +18 -0
  125. package/dist/events/map-pan.js +11 -0
  126. package/dist/events/map-part-change.d.ts +16 -0
  127. package/dist/events/map-part-change.js +11 -0
  128. package/dist/events/map-ready.d.ts +15 -0
  129. package/dist/events/map-ready.js +6 -0
  130. package/dist/events/map-rotate.d.ts +9 -0
  131. package/dist/events/map-rotate.js +11 -0
  132. package/dist/events/map-tilt.d.ts +9 -0
  133. package/dist/events/map-tilt.js +11 -0
  134. package/dist/events/map-zoom.d.ts +13 -0
  135. package/dist/events/map-zoom.js +11 -0
  136. package/dist/events/move.d.ts +11 -0
  137. package/dist/events/move.js +11 -0
  138. package/dist/events/names.d.ts +18 -0
  139. package/dist/events/names.js +13 -0
  140. package/dist/events/navigate.d.ts +13 -0
  141. package/dist/events/navigate.js +11 -0
  142. package/dist/events/next.d.ts +23 -0
  143. package/dist/events/next.js +11 -0
  144. package/dist/events/panel-resize.d.ts +12 -0
  145. package/dist/events/panel-resize.js +11 -0
  146. package/dist/events/pin.d.ts +12 -0
  147. package/dist/events/pin.js +11 -0
  148. package/dist/events/press.d.ts +19 -0
  149. package/dist/events/press.js +11 -0
  150. package/dist/events/preview.d.ts +14 -0
  151. package/dist/events/preview.js +11 -0
  152. package/dist/events/previous.d.ts +6 -0
  153. package/dist/events/previous.js +11 -0
  154. package/dist/events/range-change.d.ts +10 -0
  155. package/dist/events/range-change.js +11 -0
  156. package/dist/events/read.d.ts +19 -0
  157. package/dist/events/read.js +11 -0
  158. package/dist/events/reconnect.d.ts +6 -0
  159. package/dist/events/reconnect.js +11 -0
  160. package/dist/events/reject.d.ts +13 -0
  161. package/dist/events/reject.js +11 -0
  162. package/dist/events/relabel.d.ts +6 -0
  163. package/dist/events/relabel.js +11 -0
  164. package/dist/events/remove.d.ts +12 -0
  165. package/dist/events/remove.js +11 -0
  166. package/dist/events/reorder.d.ts +18 -0
  167. package/dist/events/reorder.js +11 -0
  168. package/dist/events/reordered.d.ts +12 -0
  169. package/dist/events/reordered.js +11 -0
  170. package/dist/events/resize.d.ts +19 -0
  171. package/dist/events/resize.js +11 -0
  172. package/dist/events/resized.d.ts +16 -0
  173. package/dist/events/resized.js +11 -0
  174. package/dist/events/sample-end.d.ts +5 -0
  175. package/dist/events/sample-end.js +6 -0
  176. package/dist/events/sample-start.d.ts +18 -0
  177. package/dist/events/sample-start.js +6 -0
  178. package/dist/events/scrolled.d.ts +32 -0
  179. package/dist/events/scrolled.js +11 -0
  180. package/dist/events/select.d.ts +12 -0
  181. package/dist/events/select.js +11 -0
  182. package/dist/events/selected.d.ts +12 -0
  183. package/dist/events/selected.js +11 -0
  184. package/dist/events/send.d.ts +18 -0
  185. package/dist/events/send.js +11 -0
  186. package/dist/events/shortcut.d.ts +13 -0
  187. package/dist/events/shortcut.js +11 -0
  188. package/dist/events/sort.d.ts +17 -0
  189. package/dist/events/sort.js +11 -0
  190. package/dist/events/sorted.d.ts +15 -0
  191. package/dist/events/sorted.js +11 -0
  192. package/dist/events/split.d.ts +12 -0
  193. package/dist/events/split.js +11 -0
  194. package/dist/events/toggle.d.ts +15 -0
  195. package/dist/events/toggle.js +11 -0
  196. package/dist/events/tour-ask.d.ts +16 -0
  197. package/dist/events/tour-ask.js +11 -0
  198. package/dist/events/tour-status.d.ts +14 -0
  199. package/dist/events/tour-status.js +11 -0
  200. package/dist/events/typing.d.ts +10 -0
  201. package/dist/events/typing.js +11 -0
  202. package/dist/helix-element/helix-element.js +9 -43
  203. package/dist/helix-element/react-bridge.d.ts +23 -0
  204. package/dist/helix-element/react-bridge.js +2 -2
  205. package/dist/helix-form-element/helix-form-element.d.ts +5 -20
  206. package/dist/helix-form-element/helix-form-element.js +4 -56
  207. package/dist/index.d.ts +30 -9
  208. package/dist/index.js +30 -9
  209. package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +24 -2
  210. package/dist/mixins/mixin-chart-source/mixin-chart-source.js +23 -1
  211. package/dist/mixins/mixin-controller-active/mixin-controller-active.js +4 -3
  212. package/dist/mixins/mixin-controller-checked/mixin-controller-checked.d.ts +5 -2
  213. package/dist/mixins/mixin-controller-checked/mixin-controller-checked.js +2 -1
  214. package/dist/mixins/mixin-controller-value/mixin-controller-value.d.ts +4 -2
  215. package/dist/mixins/mixin-controller-value/mixin-controller-value.js +7 -2
  216. package/dist/mixins/mixin-dismissible/mixin-dismissible.js +44 -7
  217. package/dist/mixins/mixin-field/mixin-field.js +2 -2
  218. package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.d.ts +42 -0
  219. package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.js +46 -0
  220. package/dist/mixins/mixin-picker-field/mixin-picker-field.d.ts +7 -4
  221. package/dist/mixins/mixin-picker-field/mixin-picker-field.js +6 -4
  222. package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +19 -9
  223. package/dist/utils/audit-name/audit-name-off.d.ts +10 -0
  224. package/dist/utils/audit-name/audit-name-off.js +1 -0
  225. package/dist/utils/audit-name/audit-name.d.ts +26 -8
  226. package/dist/utils/audit-name/audit-name.js +22 -30
  227. package/dist/utils/audit-source/audit-source-off.d.ts +10 -0
  228. package/dist/utils/audit-source/audit-source-off.js +1 -0
  229. package/dist/utils/audit-source/audit-source.d.ts +19 -0
  230. package/dist/utils/audit-source/audit-source.js +27 -0
  231. package/dist/utils/calendar/calendar.js +7 -7
  232. package/dist/utils/call-listener/call-listener.d.ts +16 -0
  233. package/dist/utils/call-listener/call-listener.js +17 -0
  234. package/dist/utils/chord/chord.d.ts +14 -0
  235. package/dist/utils/chord/chord.js +1 -0
  236. package/dist/utils/clamp/clamp.d.ts +7 -0
  237. package/dist/utils/clamp/clamp.js +1 -0
  238. package/dist/utils/css-color/css-color.js +1 -1
  239. package/dist/utils/draw-tooltip/draw-tooltip.d.ts +1 -1
  240. package/dist/utils/draw-tooltip/draw-tooltip.js +3 -1
  241. package/dist/utils/draw-tooltip/spoken-reading.d.ts +6 -2
  242. package/dist/utils/draw-tooltip/spoken-reading.js +5 -4
  243. package/dist/utils/elapsed-time/elapsed-time.d.ts +1 -1
  244. package/dist/utils/elapsed-time/elapsed-time.js +2 -5
  245. package/dist/utils/heading-level/heading-level.d.ts +8 -0
  246. package/dist/utils/heading-level/heading-level.js +4 -0
  247. package/dist/utils/host-words/host-words.d.ts +16 -0
  248. package/dist/utils/host-words/host-words.js +13 -0
  249. package/dist/utils/implicit-submit/implicit-submit.d.ts +25 -0
  250. package/dist/utils/implicit-submit/implicit-submit.js +52 -0
  251. package/dist/utils/load-more/load-more.d.ts +25 -0
  252. package/dist/utils/load-more/load-more.js +1 -0
  253. package/dist/utils/locale-of/locale-of.d.ts +18 -0
  254. package/dist/utils/locale-of/locale-of.js +26 -0
  255. package/dist/utils/name-text/name-text.d.ts +12 -0
  256. package/dist/utils/name-text/name-text.js +25 -0
  257. package/dist/utils/nearest/nearest.d.ts +9 -0
  258. package/dist/utils/nearest/nearest.js +9 -0
  259. package/dist/utils/number-format/number-format.d.ts +11 -1
  260. package/dist/utils/number-format/number-format.js +17 -5
  261. package/dist/utils/own-rule/own-rule.d.ts +16 -0
  262. package/dist/utils/own-rule/own-rule.js +7 -0
  263. package/dist/utils/plain-click/plain-click.d.ts +10 -0
  264. package/dist/utils/plain-click/plain-click.js +1 -0
  265. package/dist/utils/platform/platform.d.ts +8 -0
  266. package/dist/utils/platform/platform.js +1 -0
  267. package/dist/utils/press-type/press-type.d.ts +20 -0
  268. package/dist/utils/press-type/press-type.js +15 -0
  269. package/dist/utils/read-series/read-series.d.ts +14 -0
  270. package/dist/utils/read-series/read-series.js +15 -0
  271. package/dist/utils/relative-time/relative-time.d.ts +8 -0
  272. package/dist/utils/relative-time/relative-time.js +5 -2
  273. package/dist/utils/report-render/report-render.js +2 -14
  274. package/dist/utils/report-runtime/report-runtime.d.ts +11 -4
  275. package/dist/utils/report-runtime/report-runtime.js +2 -14
  276. package/dist/utils/report-usage/report-usage.js +2 -14
  277. package/dist/utils/row-data/row-data.d.ts +15 -0
  278. package/dist/utils/row-data/row-data.js +17 -0
  279. package/dist/utils/row-order/row-order.d.ts +141 -0
  280. package/dist/utils/row-order/row-order.js +76 -0
  281. package/dist/utils/scroll-item-into-view/scroll-item-into-view.d.ts +33 -0
  282. package/dist/utils/scroll-item-into-view/scroll-item-into-view.js +13 -3
  283. package/dist/utils/slotted-glyph/slotted-glyph.d.ts +33 -0
  284. package/dist/utils/slotted-glyph/slotted-glyph.js +27 -0
  285. package/dist/utils/tell-disclosure/tell-disclosure.d.ts +4 -0
  286. package/dist/utils/tree-arrow/tree-arrow.d.ts +23 -0
  287. package/dist/utils/tree-arrow/tree-arrow.js +9 -0
  288. package/dist/utils/typeahead/typeahead.d.ts +75 -0
  289. package/dist/utils/typeahead/typeahead.js +37 -0
  290. package/dist/utils/value-as/value-as.d.ts +9 -0
  291. package/dist/utils/value-as/value-as.js +9 -1
  292. package/dist/utils/verdict-flags/verdict-flags.d.ts +13 -0
  293. package/dist/utils/verdict-flags/verdict-flags.js +6 -0
  294. package/dist/utils/watch-labels/watch-labels.d.ts +16 -0
  295. package/dist/utils/watch-labels/watch-labels.js +34 -0
  296. package/dist/utils/words-converter/words-converter.d.ts +14 -0
  297. package/dist/utils/words-converter/words-converter.js +15 -0
  298. package/dist/utils/written-list/written-list.d.ts +60 -0
  299. package/dist/utils/written-list/written-list.js +46 -0
  300. package/dist/version.d.ts +1 -1
  301. package/dist/version.js +1 -1
  302. package/package.json +29 -5
@@ -107,13 +107,20 @@ export declare class SourceController implements ReactiveController {
107
107
  get hidden(): ReadonlySet<string>;
108
108
  /**
109
109
  * Hides these series on the table and shows every other, for every chart
110
- * and legend reading it, which then redraw.
110
+ * and legend reading it, which then redraw. Answers the table it wrote to,
111
+ * or null where `for` names none.
112
+ *
113
+ * Given `among`, only those names are shown or hidden, and a series hidden
114
+ * outside them stays hidden. A legend passes its own entries, so a legend
115
+ * of the rows and a legend of the columns on one table each keep what the
116
+ * other hid.
111
117
  *
112
118
  * Names are matched without regard to case or surrounding space, as a
113
119
  * column's heading is everywhere else. Nothing happens where `for` names no
114
- * table, or the set is already this one.
120
+ * table, or the set is already this one, so two writers that agree stop
121
+ * asking each other to redraw.
115
122
  */
116
- hide(names: Iterable<string>): void;
123
+ hide(names: Iterable<string>, among?: Iterable<string>): Element | null;
117
124
  /** Counts this controller among the readers of the table it watches, or of none. */
118
125
  private enlist;
119
126
  hostConnected(): void;
@@ -1,3 +1,4 @@
1
+ import { auditSource } from '#audit-source';
1
2
  import { elementById } from '../../utils/element-by-id/element-by-id.js';
2
3
  import { readRows, readSeries, seriesKey, } from '../../utils/read-series/read-series.js';
3
4
  const HIDDEN = new WeakMap();
@@ -54,15 +55,17 @@ export class SourceController {
54
55
  const element = this.element;
55
56
  return element ? (HIDDEN.get(element) ?? NONE) : NONE;
56
57
  }
57
- hide(names) {
58
+ hide(names, among) {
58
59
  const element = this.resolve();
59
60
  if (!element) {
60
- return;
61
+ return null;
61
62
  }
62
- const next = new Set([...names].map(seriesKey).filter(Boolean));
63
63
  const now = HIDDEN.get(element) ?? NONE;
64
+ const mine = among === undefined ? undefined : new Set([...among].map(seriesKey));
65
+ const kept = mine === undefined ? [] : [...now].filter((one) => !mine.has(one));
66
+ const next = new Set([...kept, ...[...names].map(seriesKey)].filter(Boolean));
64
67
  if (next.size === now.size && [...next].every((one) => now.has(one))) {
65
- return;
68
+ return element;
66
69
  }
67
70
  if (next.size === 0) {
68
71
  HIDDEN.delete(element);
@@ -73,6 +76,7 @@ export class SourceController {
73
76
  for (const reader of READERS.get(element) ?? []) {
74
77
  reader.host.requestUpdate();
75
78
  }
79
+ return element;
76
80
  }
77
81
  enlist(element) {
78
82
  if (this.watched) {
@@ -89,6 +93,7 @@ export class SourceController {
89
93
  }
90
94
  hostConnected() {
91
95
  this.watch();
96
+ auditSource(this.host, () => this.resolve());
92
97
  }
93
98
  hostUpdated() {
94
99
  if (this.deferred) {
@@ -10,6 +10,12 @@ export interface SwipeOptions {
10
10
  end: (dx: number, dy: number, vx: number, vy: number) => void;
11
11
  /** Called as the pointer moves, with how far it has gone from the press. */
12
12
  move: (dx: number, dy: number) => void;
13
+ /**
14
+ * How far a press travels before it is a swipe, in pixels: 8 where this is
15
+ * not given. A mouse drag that takes over sooner, such as Carousel's at 4,
16
+ * says so here.
17
+ */
18
+ slop?: number;
13
19
  /**
14
20
  * Whether a press may start a swipe, given the element it landed on. Every
15
21
  * press may where this is not given. A field, a scroller that has its own use
@@ -32,7 +38,10 @@ export interface SwipeOptions {
32
38
  * axis.** Before that it is still a press, so a tap on a button inside the
33
39
  * surface is a tap, and a drag across the axis, a reader scrolling, is left to
34
40
  * the page. Once it is a swipe, the click that ends it is swallowed, so a
35
- * swipe that started on a button does not also press it.
41
+ * swipe that started on a button does not also press it. The swallow is held on
42
+ * the window for one task after the release, so a spec that swipes and then
43
+ * presses a control in the same task sees that press swallowed: wait a task
44
+ * between them, as a reader's next press always does.
36
45
  *
37
46
  * The move and the release are heard on the window, so a pointer that leaves
38
47
  * the surface mid-swipe is still followed.
@@ -34,7 +34,7 @@ export class SwipeController {
34
34
  if (!this.swiping) {
35
35
  const along = Math.abs(axis === 'x' ? dx : dy);
36
36
  const across = Math.abs(axis === 'x' ? dy : dx);
37
- if (Math.max(along, across) < SLOP) {
37
+ if (Math.max(along, across) < (this.options.slop ?? SLOP)) {
38
38
  return;
39
39
  }
40
40
  if (across >= along) {
@@ -20,7 +20,9 @@ export interface VirtualizeOptions {
20
20
  * the straight line the note below defends. A host that returns its row
21
21
  * elements gets each one measured after it renders and placed by what it
22
22
  * came to; a host that returns nothing gets every item at `estimate`, which
23
- * is right whenever the rows really are uniform and is cheaper.
23
+ * is right whenever the rows really are uniform and is cheaper. A host that
24
+ * returns its rows and turns `measured` off keeps the straight line, with its
25
+ * slope read once from the rows it drew.
24
26
  *
25
27
  * **Each row carries its own index rather than being counted off from
26
28
  * `window.first`.** A host is free to place its rows whenever it likes, and
@@ -129,6 +131,15 @@ export declare class VirtualizeController implements ReactiveController {
129
131
  private readonly heights;
130
132
  /** Room `shift` added above the window, owed to the scroll offset once drawn. */
131
133
  private owed;
134
+ /**
135
+ * The drawn rows' height on the straight line, read once per estimate.
136
+ *
137
+ * Undefined until a host that offers `rows` has drawn some on the uniform
138
+ * path, and again after `forget`.
139
+ */
140
+ private sample;
141
+ /** The length of the set when `endInSight` last answered true. */
142
+ private askedAt;
132
143
  constructor(host: ReactiveControllerHost, options: VirtualizeOptions);
133
144
  hostConnected(): void;
134
145
  hostDisconnected(): void;
@@ -145,6 +156,28 @@ export declare class VirtualizeController implements ReactiveController {
145
156
  measure(): void;
146
157
  /** The straight line: one estimate, so offset and index convert by division. */
147
158
  private uniform;
159
+ /**
160
+ * How tall one item is on the straight line: the drawn rows' height once
161
+ * read, and `estimate` until then.
162
+ *
163
+ * **An estimate that is wrong on the straight line leaves the end of the
164
+ * set out of reach.** Rows of 21 pixels placed at 32 fill two thirds of the
165
+ * room they are counted for, so the window stops short of the bottom of the
166
+ * box and the spacer after it holds the rest: in Chromium, `scrollToIndex`
167
+ * on the last of 5,000 such rows scrolled to the end and drew nothing there.
168
+ * Reading the drawn rows once corrects the slope, and it is still a line.
169
+ */
170
+ private line;
171
+ /**
172
+ * Reads the drawn rows' height once for the straight line, for a host that
173
+ * offers `rows` and does not measure.
174
+ *
175
+ * The mean of the rows drawn, each item's elements counted together. A row
176
+ * with no height, such as one that is not laid out, says nothing. When the
177
+ * line moves, the scroll offset moves with it, so the item at the top of the
178
+ * box stays there.
179
+ */
180
+ private sampleRows;
148
181
  /** Whether this pass places by measurement: offered, and wanted. */
149
182
  private measuring;
150
183
  /**
@@ -176,6 +209,20 @@ export declare class VirtualizeController implements ReactiveController {
176
209
  * host draws around the rows.
177
210
  */
178
211
  remaining(): number;
212
+ /**
213
+ * Whether a reader has come within one screen of the end of the set, true
214
+ * once for each length of it.
215
+ *
216
+ * For a host that asks for more items as a reader nears the end: it sends
217
+ * its request when this answers true, and the set growing lets it answer
218
+ * true again. False while the box has no height or the set no items, so a
219
+ * list that has not been laid out asks for nothing.
220
+ *
221
+ * `length` is what the answer is kept for, the count by default. A host
222
+ * whose count is a filtered view of what it holds passes what it holds, so
223
+ * new items that the filter hides still let it ask again.
224
+ */
225
+ endInSight(length?: number): boolean;
179
226
  /**
180
227
  * The two spacers' heights for the window, with item `kept` drawn too.
181
228
  *
@@ -1,3 +1,4 @@
1
+ import { endInSight } from '../../utils/load-more/load-more.js';
1
2
  import { reportRuntime } from '../../utils/report-runtime/report-runtime.js';
2
3
  import { Heights } from './heights.js';
3
4
  const UNSTABLE = 10;
@@ -8,6 +9,7 @@ export class VirtualizeController {
8
9
  this.warned = false;
9
10
  this.window = { after: 0, before: 0, first: 0, last: 0 };
10
11
  this.owed = 0;
12
+ this.askedAt = -1;
11
13
  this.handleScroll = () => {
12
14
  this.settling = 0;
13
15
  this.measure();
@@ -46,7 +48,7 @@ export class VirtualizeController {
46
48
  this.watch();
47
49
  const box = this.options.container();
48
50
  const total = Math.max(0, this.options.count());
49
- const size = Math.max(1, this.options.estimate());
51
+ const size = this.line();
50
52
  if (!box) {
51
53
  return;
52
54
  }
@@ -80,6 +82,36 @@ export class VirtualizeController {
80
82
  const last = Math.min(total, first + fits);
81
83
  return { after: Math.max(0, (total - last) * size), before: first * size, first, last };
82
84
  }
85
+ line() {
86
+ const estimate = Math.max(1, this.options.estimate());
87
+ return this.sample?.estimate === estimate ? this.sample.size : estimate;
88
+ }
89
+ sampleRows() {
90
+ const estimate = Math.max(1, this.options.estimate());
91
+ if (this.sample?.estimate === estimate) {
92
+ return;
93
+ }
94
+ const heights = new Map();
95
+ for (const { element, index } of this.options.rows?.() ?? []) {
96
+ heights.set(index, (heights.get(index) ?? 0) + element.getBoundingClientRect().height);
97
+ }
98
+ const seen = [...heights.values()].filter((height) => height > 0);
99
+ if (seen.length === 0) {
100
+ return;
101
+ }
102
+ const was = this.line();
103
+ const size = Math.max(1, seen.reduce((sum, height) => sum + height, 0) / seen.length);
104
+ this.sample = { estimate, size };
105
+ if (Math.abs(size - was) < 0.5) {
106
+ return;
107
+ }
108
+ const box = this.options.container();
109
+ if (box && box.scrollTop > 0) {
110
+ box.scrollTop = (box.scrollTop / was) * size;
111
+ }
112
+ this.settling = 0;
113
+ this.measure();
114
+ }
83
115
  measuring() {
84
116
  return this.options.rows !== undefined && (this.options.measured?.() ?? true);
85
117
  }
@@ -107,7 +139,7 @@ export class VirtualizeController {
107
139
  const top = Math.max(0, box.scrollTop);
108
140
  const bottom = top + box.clientHeight;
109
141
  if (!this.measuring()) {
110
- const size = Math.max(1, this.options.estimate());
142
+ const size = this.line();
111
143
  const first = Math.min(Math.floor(top / size), total);
112
144
  return { first, last: Math.max(first, Math.min(total, Math.ceil(bottom / size))) };
113
145
  }
@@ -124,11 +156,22 @@ export class VirtualizeController {
124
156
  if (!box) {
125
157
  return 0;
126
158
  }
127
- const length = this.measuring()
128
- ? this.heights.total(total)
129
- : total * Math.max(1, this.options.estimate());
159
+ const length = this.measuring() ? this.heights.total(total) : total * this.line();
130
160
  return Math.max(0, length - Math.max(0, box.scrollTop) - box.clientHeight);
131
161
  }
162
+ endInSight(length = Math.max(0, this.options.count())) {
163
+ if (this.options.count() <= 0 ||
164
+ !endInSight({
165
+ askedAt: this.askedAt,
166
+ count: length,
167
+ remaining: this.remaining(),
168
+ screen: this.options.container()?.clientHeight ?? 0,
169
+ })) {
170
+ return false;
171
+ }
172
+ this.askedAt = length;
173
+ return true;
174
+ }
132
175
  spacers(kept) {
133
176
  const { after, before, first, last } = this.window;
134
177
  if (kept === undefined || (kept >= first && kept < last)) {
@@ -149,6 +192,7 @@ export class VirtualizeController {
149
192
  this.owed = 0;
150
193
  }
151
194
  if (!this.measuring()) {
195
+ this.sampleRows();
152
196
  return;
153
197
  }
154
198
  const rows = this.options.rows?.();
@@ -190,7 +234,7 @@ export class VirtualizeController {
190
234
  this.owed += room;
191
235
  }
192
236
  sizeOf(index) {
193
- return this.measuring() ? this.heights.at(index) : Math.max(1, this.options.estimate());
237
+ return this.measuring() ? this.heights.at(index) : this.line();
194
238
  }
195
239
  reveal(index, inset = 0, { align = 'nearest', behavior } = {}) {
196
240
  const box = this.options.container();
@@ -231,10 +275,11 @@ export class VirtualizeController {
231
275
  const total = Math.max(0, this.options.count());
232
276
  return this.measuring()
233
277
  ? this.heights.before(index, total)
234
- : Math.max(0, Math.min(index, total)) * Math.max(1, this.options.estimate());
278
+ : Math.max(0, Math.min(index, total)) * this.line();
235
279
  }
236
280
  forget() {
237
281
  this.heights.forget();
282
+ this.sample = undefined;
238
283
  }
239
284
  report() {
240
285
  if (this.warned) {
@@ -0,0 +1,12 @@
1
+ /**
2
+ * A reader acted on a row: Enter on a list row, or a press in a list that
3
+ * selects nothing. Sent from the row, so `target` is the row acted on.
4
+ *
5
+ * Carries nothing, because the row is the whole of the answer. Not cancelable:
6
+ * a row with a link follows it and sends nothing, so there is no default left
7
+ * to refuse.
8
+ */
9
+ export declare class HelixActionEvent extends Event {
10
+ static readonly eventName = "helix-action";
11
+ constructor();
12
+ }
@@ -0,0 +1,6 @@
1
+ export class HelixActionEvent extends Event {
2
+ static { this.eventName = 'helix-action'; }
3
+ constructor() {
4
+ super(HelixActionEvent.eventName, { bubbles: true, cancelable: false, composed: true });
5
+ }
6
+ }
@@ -0,0 +1,22 @@
1
+ import type { ActivateDetail } from './details.js';
2
+ /**
3
+ * A set has made a different child current.
4
+ *
5
+ * The notification half of `helix-before-activate`, dispatched after the state
6
+ * has moved, so `currentTarget.active` is the new value and the detail is a fact
7
+ * rather than a proposal. `previous` is the value that was current before, where
8
+ * the set knows it, as Web Awesome's `wa-video-change` carries both.
9
+ *
10
+ * **Not cancelable**, for the reason every notification here is not: the
11
+ * decision was taken by the event before it, and a second refusable event for
12
+ * one transition is two answers to one question.
13
+ *
14
+ * **Prefixed, and it has to be.** `activate` unprefixed is not in any
15
+ * `*EventMap` in the DOM library, checked rather than assumed, but the prefix is
16
+ * what stops an event dispatched inside a shadow root and retargeted to the host
17
+ * being mistaken for something the host's own contents sent.
18
+ */
19
+ export declare class HelixActivateEvent extends CustomEvent<ActivateDetail> {
20
+ static readonly eventName = "helix-activate";
21
+ constructor(detail: ActivateDetail);
22
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixActivateEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-activate'; }
3
+ constructor(detail) {
4
+ super(HelixActivateEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: false,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,12 @@
1
+ import type { AuraFallbackDetail } from './details.js';
2
+ /**
3
+ * An aura stopped drawing its shader and shows its gradient, and says why.
4
+ *
5
+ * Sent each time it falls back, from the aura, which then matches
6
+ * `:state(fallback)` until it draws again. Not cancelable: there is nothing
7
+ * left to refuse.
8
+ */
9
+ export declare class HelixAuraFallbackEvent extends CustomEvent<AuraFallbackDetail> {
10
+ static readonly eventName = "helix-aura-fallback";
11
+ constructor(detail: AuraFallbackDetail);
12
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixAuraFallbackEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-aura-fallback'; }
3
+ constructor(detail) {
4
+ super(HelixAuraFallbackEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: false,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,13 @@
1
+ import type { BandDetail } from './details.js';
2
+ /**
3
+ * A reading moved into another band: a meter whose value crossed `low`,
4
+ * `high` or `optimum` into `good`, `fair` or `poor`.
5
+ *
6
+ * Sent once for each crossing, not on every value, so a listener can say the
7
+ * change aloud or recolor something else on the page. Not cancelable, since
8
+ * the reading has already moved. Bubbles and is composed.
9
+ */
10
+ export declare class HelixBandEvent extends CustomEvent<BandDetail> {
11
+ static readonly eventName = "helix-band";
12
+ constructor(detail: BandDetail);
13
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBandEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-band'; }
3
+ constructor(detail) {
4
+ super(HelixBandEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: false,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,24 @@
1
+ import type { ChangeDetail } from './details.js';
2
+ /**
3
+ * A set is about to make a different child current, and can be refused.
4
+ *
5
+ * **Not a generic `helix-change`.** `Tabs` moving to another tab, `Tree` marking
6
+ * another row and `Steps` advancing are not a value changing, they are a set
7
+ * choosing, and the platform's word for a committed value would say the wrong
8
+ * thing. `active` names which child is current, so `activate` is the verb, and
9
+ * unlike `change` the platform has no claim on it.
10
+ *
11
+ * **This fires before the state moves.** Inside a handler `currentTarget.active`
12
+ * still holds the previous value, and `detail.value` is a proposal another
13
+ * listener may refuse, so a consumer who only wants to know which child is
14
+ * current listens for `helix-activate` instead. `helix-select` is not that
15
+ * notification either: it fires when an item is *chosen*, not when `active` is
16
+ * assigned.
17
+ *
18
+ * The shape is the one `MixinControllerOpen` already has, a cancelable request
19
+ * and a plain notification after the state has moved.
20
+ */
21
+ export declare class HelixBeforeActivateEvent extends CustomEvent<ChangeDetail> {
22
+ static readonly eventName = "helix-before-activate";
23
+ constructor(detail: ChangeDetail);
24
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforeActivateEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-activate'; }
3
+ constructor(detail) {
4
+ super(HelixBeforeActivateEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,26 @@
1
+ import type { ChangeDetail } from './details.js';
2
+ /**
3
+ * A value is about to change, and the change can be refused.
4
+ *
5
+ * **The request half of every value control.** It announces the value being
6
+ * *proposed*, before anything moves, so a listener calling `preventDefault()`
7
+ * refuses it and the control stays where it was. That is how a consumer takes
8
+ * one decision without declaring a mode, which is what 294 settled: the element
9
+ * always owns and applies its state, and refusing is the way to take it over.
10
+ *
11
+ * **The notification is native and separate.** Once this has gone out and the
12
+ * value has moved, the control announces it again under the platform's own
13
+ * name, `input` while a reader is editing and `change` when they are done, so
14
+ * `onChange` in React and `onchange=` in HTML both reach it and
15
+ * `currentTarget.value` is correct by the time a handler reads it. This event
16
+ * carries the detail because at the moment it fires the value is not on the
17
+ * element yet.
18
+ *
19
+ * **`announcesInput` picks which native notification fires, not which name this
20
+ * carries.** Granularity is the platform's own distinction, `input` against
21
+ * `change`; the request is always this one event.
22
+ */
23
+ export declare class HelixBeforeChangeEvent extends CustomEvent<ChangeDetail> {
24
+ static readonly eventName = "helix-before-change";
25
+ constructor(detail: ChangeDetail);
26
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforeChangeEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-change'; }
3
+ constructor(detail) {
4
+ super(HelixBeforeChangeEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,6 @@
1
+ import type { OpenDetail } from './details.js';
2
+ /** Fired when an element is about to close. See `HelixBeforeOpenEvent`. */
3
+ export declare class HelixBeforeCloseEvent extends CustomEvent<OpenDetail> {
4
+ static readonly eventName = "helix-before-close";
5
+ constructor();
6
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforeCloseEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-close'; }
3
+ constructor() {
4
+ super(HelixBeforeCloseEvent.eventName, {
5
+ bubbles: false,
6
+ cancelable: true,
7
+ composed: false,
8
+ detail: { open: false },
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,6 @@
1
+ import type { ChangeDetail } from './details.js';
2
+ /** A pane is about to collapse or reopen, and can be refused. */
3
+ export declare class HelixBeforeCollapseEvent extends CustomEvent<ChangeDetail> {
4
+ static readonly eventName = "helix-before-collapse";
5
+ constructor(detail: ChangeDetail);
6
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforeCollapseEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-collapse'; }
3
+ constructor(detail) {
4
+ super(HelixBeforeCollapseEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,6 @@
1
+ import type { ChangeDetail } from './details.js';
2
+ /** Source is about to be edited, and can be refused. */
3
+ export declare class HelixBeforeEditEvent extends CustomEvent<ChangeDetail> {
4
+ static readonly eventName = "helix-before-edit";
5
+ constructor(detail: ChangeDetail);
6
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforeEditEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-edit'; }
3
+ constructor(detail) {
4
+ super(HelixBeforeEditEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,17 @@
1
+ import type { MoveDetail } from './details.js';
2
+ /**
3
+ * Cards are about to move, and can be refused.
4
+ *
5
+ * **This is the controlled half, the way `helix-before-open` is for a
6
+ * dialog.** A board moves its own cards by default, writing `x` and `y` onto
7
+ * each one the way an input writes its own value. A consumer who keeps the
8
+ * positions in their own state calls `preventDefault()` here, writes what the
9
+ * detail says into that state, and renders the cards where it puts them.
10
+ *
11
+ * Sent for every step of a drag, so a controlled board follows the pointer
12
+ * rather than jumping on the drop.
13
+ */
14
+ export declare class HelixBeforeMoveEvent extends CustomEvent<MoveDetail> {
15
+ static readonly eventName = "helix-before-move";
16
+ constructor(detail: MoveDetail);
17
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforeMoveEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-move'; }
3
+ constructor(detail) {
4
+ super(HelixBeforeMoveEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,17 @@
1
+ import type { OpenDetail } from './details.js';
2
+ /**
3
+ * Fired when an element is about to open.
4
+ *
5
+ * Cancelable: `preventDefault()` refuses the change, and the element stays
6
+ * closed. Paired with `helix-before-close` rather than being one event carrying a
7
+ * boolean, so a listener that only cares about one direction says so by which
8
+ * event it listens for.
9
+ *
10
+ * Neither bubbles nor composed. A dialog inside a drawer inside a popover is
11
+ * three overlays, and an inner one opening must not read as the outer one
12
+ * opening.
13
+ */
14
+ export declare class HelixBeforeOpenEvent extends CustomEvent<OpenDetail> {
15
+ static readonly eventName = "helix-before-open";
16
+ constructor();
17
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforeOpenEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-open'; }
3
+ constructor() {
4
+ super(HelixBeforeOpenEvent.eventName, {
5
+ bubbles: false,
6
+ cancelable: true,
7
+ composed: false,
8
+ detail: { open: true },
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,13 @@
1
+ import type { ChangeDetail } from './details.js';
2
+ /**
3
+ * A sandbox's panel is about to change height, and can be refused.
4
+ *
5
+ * The sibling of `helix-before-split`, and named for the divider rather than for
6
+ * the axis because a reader binding one of the two is choosing which divider they
7
+ * care about. `value` is pixels here and a percentage there, which is what each
8
+ * property already publishes.
9
+ */
10
+ export declare class HelixBeforePanelResizeEvent extends CustomEvent<ChangeDetail> {
11
+ static readonly eventName = "helix-before-panel-resize";
12
+ constructor(detail: ChangeDetail);
13
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforePanelResizeEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-panel-resize'; }
3
+ constructor(detail) {
4
+ super(HelixBeforePanelResizeEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,6 @@
1
+ import type { ChangeDetail } from './details.js';
2
+ /** A message is about to be pinned or unpinned, and can be refused. */
3
+ export declare class HelixBeforePinEvent extends CustomEvent<ChangeDetail> {
4
+ static readonly eventName = "helix-before-pin";
5
+ constructor(detail: ChangeDetail);
6
+ }