@fusion.dev/helix-headless 0.182.1 → 0.183.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 (184) hide show
  1. package/custom-elements.json +7851 -5810
  2. package/dist/accordion/item/accordion-item.js +1 -6
  3. package/dist/accordion/root/accordion-root.js +1 -6
  4. package/dist/announcement/root/announcement-root.js +1 -6
  5. package/dist/app-header/root/app-header-root.js +1 -6
  6. package/dist/area-chart/root/area-chart-root.d.ts +1 -0
  7. package/dist/area-chart/root/area-chart-root.js +3 -7
  8. package/dist/avatar/group/avatar-group.js +1 -6
  9. package/dist/avatar/root/avatar-root.js +1 -6
  10. package/dist/badge/root/badge-root.js +1 -6
  11. package/dist/bar-chart/root/bar-chart-root.d.ts +2 -0
  12. package/dist/bar-chart/root/bar-chart-root.js +6 -9
  13. package/dist/blockquote/root/blockquote-root.js +1 -6
  14. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +1 -0
  15. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +3 -7
  16. package/dist/breadcrumbs/root/breadcrumbs-root.js +1 -6
  17. package/dist/button/root/button-root.d.ts +7 -3
  18. package/dist/button/root/button-root.js +5 -11
  19. package/dist/button-group/root/button-group-root.js +1 -6
  20. package/dist/callout/root/callout-root.js +1 -6
  21. package/dist/canvas/edge/canvas-edge.js +1 -6
  22. package/dist/canvas/node/canvas-node.js +1 -6
  23. package/dist/canvas/root/canvas-root.js +1 -6
  24. package/dist/card/root/card-root.js +1 -6
  25. package/dist/carousel/root/carousel-root.d.ts +1 -0
  26. package/dist/carousel/root/carousel-root.js +3 -7
  27. package/dist/chat/composer/chat-composer.js +1 -6
  28. package/dist/chat/message/chat-message.js +1 -6
  29. package/dist/chat/root/chat-root.d.ts +1 -0
  30. package/dist/chat/root/chat-root.js +3 -7
  31. package/dist/checkbox/root/checkbox-root.js +1 -6
  32. package/dist/checkbox-group/root/checkbox-group-root.js +1 -6
  33. package/dist/code/root/code-root.js +1 -6
  34. package/dist/code-block/root/code-block-root.js +1 -6
  35. package/dist/color-input/root/color-input-root.js +1 -6
  36. package/dist/color-picker/root/color-picker-root.js +1 -6
  37. package/dist/combobox/root/combobox-root.js +1 -6
  38. package/dist/command/root/command-root.js +1 -6
  39. package/dist/copy-button/root/copy-button-root.js +1 -6
  40. package/dist/data-table/root/data-table-root.d.ts +1 -0
  41. package/dist/data-table/root/data-table-root.js +3 -7
  42. package/dist/date-input/root/date-input-root.js +1 -6
  43. package/dist/date-picker/root/date-picker-root.d.ts +1 -0
  44. package/dist/date-picker/root/date-picker-root.js +3 -7
  45. package/dist/description-list/item/description-list-item.js +1 -6
  46. package/dist/description-list/root/description-list-root.js +1 -6
  47. package/dist/dialog/root/dialog-root.js +1 -6
  48. package/dist/divider/root/divider-root.js +1 -6
  49. package/dist/donut-chart/root/donut-chart-root.d.ts +1 -0
  50. package/dist/donut-chart/root/donut-chart-root.js +3 -7
  51. package/dist/drawer/root/drawer-root.js +1 -6
  52. package/dist/drilldown/item/drilldown-item.d.ts +1 -0
  53. package/dist/drilldown/item/drilldown-item.js +3 -7
  54. package/dist/drilldown/root/drilldown-root.d.ts +1 -0
  55. package/dist/drilldown/root/drilldown-root.js +3 -7
  56. package/dist/empty/root/empty-root.js +1 -6
  57. package/dist/file-input/root/file-input-root.js +1 -6
  58. package/dist/filter-input/chip/filter-chip.js +1 -6
  59. package/dist/filter-input/field/filter-field.js +1 -6
  60. package/dist/filter-input/menu/filter-menu.js +1 -6
  61. package/dist/filter-input/operator/filter-operator.js +1 -6
  62. package/dist/filter-input/root/filter-input-root.js +1 -6
  63. package/dist/format-date/root/format-date-root.js +1 -6
  64. package/dist/graph/root/graph-root.d.ts +1 -0
  65. package/dist/graph/root/graph-root.js +3 -7
  66. package/dist/heatmap/root/heatmap-root.d.ts +11 -1
  67. package/dist/heatmap/root/heatmap-root.js +18 -15
  68. package/dist/icon/root/icon-root.d.ts +1 -0
  69. package/dist/icon/root/icon-root.js +3 -7
  70. package/dist/icon-button/root/icon-button-root.js +1 -6
  71. package/dist/image/root/image-root.js +1 -6
  72. package/dist/input/root/input-root.js +1 -6
  73. package/dist/kbd/root/kbd-root.d.ts +1 -0
  74. package/dist/kbd/root/kbd-root.js +3 -7
  75. package/dist/legend/root/legend-root.js +1 -6
  76. package/dist/lightbox/item/lightbox-item.js +1 -6
  77. package/dist/lightbox/root/lightbox-root.d.ts +1 -0
  78. package/dist/lightbox/root/lightbox-root.js +3 -7
  79. package/dist/line-chart/root/line-chart-root.d.ts +1 -0
  80. package/dist/line-chart/root/line-chart-root.js +3 -7
  81. package/dist/list/item/list-item.js +1 -6
  82. package/dist/list/root/list-root.js +1 -6
  83. package/dist/listbox/root/listbox-root.d.ts +1 -0
  84. package/dist/listbox/root/listbox-root.js +3 -7
  85. package/dist/loader/root/loader-root.js +1 -6
  86. package/dist/map/area/map-area.js +1 -6
  87. package/dist/map/buildings/map-buildings.js +1 -6
  88. package/dist/map/contours/map-contours.js +1 -6
  89. package/dist/map/landcover/map-landcover.js +1 -6
  90. package/dist/map/marker/map-marker.js +1 -6
  91. package/dist/map/points/map-points.js +1 -6
  92. package/dist/map/position/map-position.js +1 -6
  93. package/dist/map/raster/map-raster.js +1 -6
  94. package/dist/map/root/map-root.js +1 -6
  95. package/dist/map/route/map-route.js +1 -6
  96. package/dist/map/terrain/map-terrain.js +1 -6
  97. package/dist/megamenu/root/megamenu-root.js +1 -6
  98. package/dist/menu/item/menu-item.d.ts +1 -0
  99. package/dist/menu/item/menu-item.js +3 -7
  100. package/dist/menu/root/menu-root.d.ts +1 -0
  101. package/dist/menu/root/menu-root.js +3 -7
  102. package/dist/menu/section/menu-section.js +1 -6
  103. package/dist/meter/root/meter-root.js +1 -6
  104. package/dist/navigation/root/navigation-root.js +1 -6
  105. package/dist/notifications/group/notification-group.js +1 -6
  106. package/dist/notifications/notification/notification.js +1 -6
  107. package/dist/notifications/root/notifications-root.js +1 -6
  108. package/dist/number-input/root/number-input-root.js +1 -6
  109. package/dist/object-inspector/root/object-inspector-root.d.ts +1 -0
  110. package/dist/object-inspector/root/object-inspector-root.js +3 -7
  111. package/dist/option/group/option-group.js +1 -6
  112. package/dist/option/root/option-root.js +1 -6
  113. package/dist/option/separator/option-separator.js +1 -6
  114. package/dist/outline/root/outline-root.js +1 -6
  115. package/dist/pagination/root/pagination-root.d.ts +1 -0
  116. package/dist/pagination/root/pagination-root.js +3 -7
  117. package/dist/pagination/size/pagination-size.js +1 -6
  118. package/dist/pagination/summary/pagination-summary.js +1 -6
  119. package/dist/pin-input/root/pin-input-root.js +1 -6
  120. package/dist/popover/root/popover-root.js +1 -6
  121. package/dist/progress/root/progress-root.js +1 -6
  122. package/dist/qr-code/root/qr-code-root.js +1 -6
  123. package/dist/quote/root/quote-root.js +1 -6
  124. package/dist/radio/group/radio-group.js +1 -6
  125. package/dist/radio/root/radio-root.js +1 -6
  126. package/dist/rating/root/rating-root.js +1 -6
  127. package/dist/scatter-chart/root/scatter-chart-root.js +1 -6
  128. package/dist/scroll-area/root/scroll-area-root.d.ts +1 -0
  129. package/dist/scroll-area/root/scroll-area-root.js +3 -7
  130. package/dist/select/root/select-root.js +1 -6
  131. package/dist/skeleton/root/skeleton-root.js +1 -6
  132. package/dist/skip-link/root/skip-link-root.js +1 -6
  133. package/dist/slider/root/slider-root.js +1 -6
  134. package/dist/sparkline/root/sparkline-root.d.ts +1 -0
  135. package/dist/sparkline/root/sparkline-root.js +3 -7
  136. package/dist/speed-dial/group/speed-dial-group.js +1 -6
  137. package/dist/speed-dial/item/speed-dial-item.js +1 -6
  138. package/dist/speed-dial/root/speed-dial-root.js +1 -6
  139. package/dist/splitter/root/splitter-root.js +1 -6
  140. package/dist/stat/group/stat-group.js +1 -6
  141. package/dist/stat/root/stat-root.js +1 -6
  142. package/dist/steps/root/steps-root.js +1 -6
  143. package/dist/steps/step/step.js +1 -6
  144. package/dist/switch/root/switch-root.js +1 -6
  145. package/dist/table/cell/table-cell.js +1 -6
  146. package/dist/table/column/table-column.js +1 -6
  147. package/dist/table/root/table-root.d.ts +1 -0
  148. package/dist/table/root/table-root.js +3 -7
  149. package/dist/table/row/table-row.d.ts +1 -0
  150. package/dist/table/row/table-row.js +3 -7
  151. package/dist/tabs/panel/tab-panel.js +1 -6
  152. package/dist/tabs/root/tabs-root.d.ts +1 -0
  153. package/dist/tabs/root/tabs-root.js +3 -7
  154. package/dist/tabs/tab/tab.js +1 -6
  155. package/dist/tag/group/tag-group.js +1 -6
  156. package/dist/tag/root/tag-root.js +1 -6
  157. package/dist/textarea/root/textarea-root.js +1 -6
  158. package/dist/time-input/root/time-input-root.js +1 -6
  159. package/dist/time-picker/root/time-picker-root.js +1 -6
  160. package/dist/timeline/group/timeline-group.js +1 -6
  161. package/dist/timeline/item/timeline-item.js +1 -6
  162. package/dist/timeline/root/timeline-root.js +1 -6
  163. package/dist/toast/item/toast-item.js +1 -6
  164. package/dist/toast/root/toast-root.js +1 -6
  165. package/dist/toggle/group/toggle-group.js +1 -6
  166. package/dist/toggle/root/toggle-root.js +1 -6
  167. package/dist/toolbar/root/toolbar-root.js +1 -6
  168. package/dist/tooltip/root/tooltip-root.js +1 -6
  169. package/dist/tour/root/tour-root.js +1 -6
  170. package/dist/tour/stop/tour-stop.js +1 -6
  171. package/dist/tree/item/tree-item.js +1 -6
  172. package/dist/tree/root/tree-root.js +1 -6
  173. package/dist/trend/root/trend-root.js +1 -6
  174. package/dist/video/root/video-root.js +1 -6
  175. package/dist/video-playlist/item/video-playlist-item.js +1 -6
  176. package/dist/video-playlist/menu/video-playlist-menu.js +1 -6
  177. package/dist/video-playlist/root/video-playlist-root.js +1 -6
  178. package/dist/virtual-list/reorder/virtual-list-reorder.js +5 -1
  179. package/dist/virtual-list/root/virtual-list-root.d.ts +96 -17
  180. package/dist/virtual-list/root/virtual-list-root.js +126 -35
  181. package/lint.json +1 -1
  182. package/package.json +6 -5
  183. package/types/jsx.d.ts +318 -222
  184. package/types/vue.d.ts +11 -3
@@ -1,10 +1,5 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- import { AriaForwardController, anchorAt, commaList, customElement, elementById, HelixElement, HelixLoadMoreEvent, HelixRangeChangeEvent, inRowOrder, isRtl, pressedOwnControl, rangeAdd, requestValue, searchableById, selectsAll, Typeahead, toggleValue, typesCharacter, VirtualizeController, words, } from '@fusion.dev/helix-core';
1
+ import { __decorate } from "tslib";
2
+ import { AriaForwardController, anchorAt, commaList, customElement, elementById, HelixElement, HelixLoadMoreEvent, HelixRangeChangeEvent, inRowOrder, isRtl, pressedOwnControl, rangeAdd, requestValue, SCROLLER_RULE, searchableById, selectsAll, Typeahead, toggleValue, typesCharacter, VIRTUAL_RULE, VirtualizeController, Waterfall, words, } from '@fusion.dev/helix-core';
8
3
  import { html, nothing, render } from 'lit';
9
4
  import { property, state } from 'lit/decorators.js';
10
5
  import { holdControls, releaseControls } from '../controls.js';
@@ -18,6 +13,7 @@ const nextSectionId = () => {
18
13
  return `virtual-list-${sectionCount}`;
19
14
  };
20
15
  const ROWS = ':scope > [data-index], :scope > [data-section] > [data-index]';
16
+ const LINE = 'helix-line-';
21
17
  let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixElement {
22
18
  constructor() {
23
19
  super(...arguments);
@@ -29,6 +25,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
29
25
  this.gap = 0;
30
26
  this.keyField = '';
31
27
  this.label = '';
28
+ this.layout = 'grid';
32
29
  this.loading = false;
33
30
  this.loadingLabel = 'Loading more';
34
31
  this.measured = false;
@@ -47,7 +44,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
47
44
  this.aria = new AriaForwardController(this, {
48
45
  label: true,
49
46
  target: () => this.partNamed('viewport'),
50
- unnamed: 'Give it a `label`, or an `aria-label` that says what the items are.',
47
+ unnamed: 'virtual-list',
51
48
  });
52
49
  this.virtualize = new VirtualizeController(this, {
53
50
  container: () => this.partNamed('viewport'),
@@ -59,7 +56,12 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
59
56
  horizontal: () => this.horizontal,
60
57
  measured: () => this.measured,
61
58
  rows: () => this.lines(),
59
+ waterfall: () => {
60
+ this.lanes.lanes = this.columnCount;
61
+ return this.waterfall ? this.lanes : undefined;
62
+ },
62
63
  });
64
+ this.lanes = new Waterfall();
63
65
  this.boxWidth = 0;
64
66
  this.measuredAcross = 1;
65
67
  this.handleKeydown = (event) => {
@@ -102,7 +104,9 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
102
104
  }
103
105
  }
104
106
  const extend = event.shiftKey && this.selectionMode === 'multiple';
105
- if (event.altKey || (toggle && !replacing) || (event.shiftKey && !extend)) {
107
+ const ends = event.key === 'Home' || event.key === 'End';
108
+ const lined = this.lined;
109
+ if (event.altKey || (toggle && !replacing && !(lined && ends)) || (event.shiftKey && !extend)) {
106
110
  return;
107
111
  }
108
112
  const count = this.data.length;
@@ -117,13 +121,19 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
117
121
  : event.key === 'ArrowDown' || event.key === 'ArrowUp'
118
122
  ? ''
119
123
  : event.key;
120
- const stepped = stepIndex(key, at, count, last - first - 1, {
121
- across: this.across,
122
- forward,
123
- });
124
+ const disabled = (one) => this.isDisabled(one);
125
+ const across = this.across;
126
+ const start = at - (at % across);
127
+ const stepped = lined && ends && !toggle
128
+ ? key === 'Home'
129
+ ? start
130
+ : Math.min(start + across, count) - 1
131
+ : this.waterfall && !ends
132
+ ? this.inWaterfall(key, at, count, forward)
133
+ : stepIndex(key, at, count, last - first - 1, { across, forward });
124
134
  const next = stepped === undefined
125
135
  ? undefined
126
- : skipDisabled(key, at, stepped, count, (one) => this.isDisabled(one), this.across);
136
+ : skipDisabled(key, at, stepped, count, disabled, this.waterfall ? 1 : across);
127
137
  if (next === undefined) {
128
138
  if (stepped !== undefined) {
129
139
  event.preventDefault();
@@ -177,8 +187,11 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
177
187
  this.requestUpdate();
178
188
  };
179
189
  this.visited = false;
190
+ this.placedWaterfall = false;
191
+ this.drawnLines = [];
180
192
  this.sectionId = nextSectionId();
181
193
  }
194
+ static { this.markRules = [SCROLLER_RULE, VIRTUAL_RULE]; }
182
195
  static { this.words = 'helix-virtual-list'; }
183
196
  get range() {
184
197
  return this.itemsOn(this.virtualize.visible());
@@ -186,7 +199,20 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
186
199
  get space() {
187
200
  return Number.isFinite(this.gap) && this.gap > 0 ? this.gap : 0;
188
201
  }
202
+ get waterfall() {
203
+ return this.layout === 'waterfall';
204
+ }
205
+ get lined() {
206
+ return (!this.selectionMode &&
207
+ !this.waterfall &&
208
+ !this.horizontal &&
209
+ this.sections === undefined &&
210
+ (this.across > 1 || this.minColumnWidth > 0));
211
+ }
189
212
  get across() {
213
+ return this.waterfall ? 1 : this.columnCount;
214
+ }
215
+ get columnCount() {
190
216
  if (this.minColumnWidth > 0 && this.boxWidth > 0) {
191
217
  const space = this.space;
192
218
  return Math.max(1, Math.floor((this.boxWidth + space) / (this.minColumnWidth + space)));
@@ -195,7 +221,9 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
195
221
  }
196
222
  watchWidth() {
197
223
  const viewport = this.partNamed('viewport');
198
- if (this.minColumnWidth <= 0 || !viewport || typeof ResizeObserver === 'undefined') {
224
+ if ((this.minColumnWidth <= 0 && !this.waterfall) ||
225
+ !viewport ||
226
+ typeof ResizeObserver === 'undefined') {
199
227
  this.widthWatch?.disconnect();
200
228
  this.widthWatch = undefined;
201
229
  return;
@@ -222,11 +250,11 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
222
250
  return sections ? entryOf(sections, at) : Math.floor(at / this.across);
223
251
  }
224
252
  get horizontal() {
225
- return this.orientation === 'horizontal' && this.across === 1;
253
+ return this.orientation === 'horizontal' && this.across === 1 && !this.waterfall;
226
254
  }
227
255
  get sections() {
228
256
  const data = this.data;
229
- if (this.sectionField === '' || data.length === 0 || this.across !== 1) {
257
+ if (this.sectionField === '' || data.length === 0 || this.columnCount !== 1 || this.waterfall) {
230
258
  return undefined;
231
259
  }
232
260
  const read = this.sectionsRead;
@@ -279,7 +307,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
279
307
  this.readFor = this.for;
280
308
  this.read();
281
309
  }
282
- const across = this.across;
310
+ const across = this.waterfall ? `${this.columnCount} ${this.boxWidth}` : this.across;
283
311
  if (across !== this.measuredAcross) {
284
312
  this.measuredAcross = across;
285
313
  this.virtualize.forget();
@@ -454,6 +482,16 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
454
482
  rowFor(index) {
455
483
  return ([...this.querySelectorAll(ROWS)].find((row) => row.dataset.index === String(index)) ?? null);
456
484
  }
485
+ inWaterfall(key, at, count, forward) {
486
+ const way = key === forward ? 'next' : key === 'ArrowLeft' || key === 'ArrowRight' ? 'previous' : key;
487
+ const box = this.partNamed('viewport');
488
+ let to = this.lanes.step(way, at, count, box?.clientHeight ?? 0);
489
+ const again = way === 'PageDown' ? 'ArrowDown' : way === 'PageUp' ? 'ArrowUp' : way;
490
+ while (to !== undefined && this.isDisabled(to)) {
491
+ to = this.lanes.step(again, to, count, 0);
492
+ }
493
+ return to;
494
+ }
457
495
  keyAt(at) {
458
496
  return keyOf(this.data[at], at, this.keyField);
459
497
  }
@@ -534,7 +572,22 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
534
572
  : undefined;
535
573
  }
536
574
  mark(element, at, chosen, off) {
537
- element.setAttribute('role', this.selectionMode ? 'option' : 'listitem');
575
+ const lined = this.lined;
576
+ element.setAttribute('role', this.selectionMode ? 'option' : lined ? 'gridcell' : 'listitem');
577
+ const across = this.across;
578
+ for (const [name, value] of [
579
+ ['aria-colindex', lined ? (at % across) + 1 : undefined],
580
+ ['aria-posinset', lined ? undefined : at + 1],
581
+ ['aria-setsize', lined ? undefined : this.data.length],
582
+ ['slot', lined ? `${LINE}${Math.floor(at / across)}` : undefined],
583
+ ]) {
584
+ if (value === undefined) {
585
+ element.removeAttribute(name);
586
+ }
587
+ else {
588
+ element.setAttribute(name, String(value));
589
+ }
590
+ }
538
591
  const selected = Boolean(this.selectionMode) && chosen.has(this.keyAt(at));
539
592
  if (this.selectionMode) {
540
593
  element.setAttribute('aria-selected', String(selected));
@@ -553,8 +606,6 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
553
606
  element.toggleAttribute('data-disabled', disabled);
554
607
  }
555
608
  stamp(element, at) {
556
- element.setAttribute('aria-posinset', String(at + 1));
557
- element.setAttribute('aria-setsize', String(this.data.length));
558
609
  element.setAttribute('data-index', String(at));
559
610
  }
560
611
  fill(elements, at) {
@@ -599,12 +650,13 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
599
650
  this.partNamed('after')?.style.setProperty(size, `${spacers.after}px`);
600
651
  }
601
652
  const sections = this.sections;
602
- const regroup = sections !== this.placedSections;
653
+ const regroup = sections !== this.placedSections || this.waterfall !== this.placedWaterfall;
603
654
  this.placedSections = sections;
655
+ this.placedWaterfall = this.waterfall;
604
656
  const children = [
605
657
  ...[...this.children].filter((child) => child !== template &&
606
658
  child instanceof HTMLElement &&
607
- !child.hasAttribute('slot') &&
659
+ (child.dataset.index !== undefined || !child.hasAttribute('slot')) &&
608
660
  !child.hasAttribute('data-section')),
609
661
  ...this.querySelectorAll(':scope > [data-section] > [data-index]'),
610
662
  ];
@@ -664,9 +716,23 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
664
716
  });
665
717
  const chosen = this.chosen;
666
718
  const off = this.disabled;
719
+ const lines = this.lined ? [...new Set(plan.wanted.map((at) => this.lineOf(at)))] : [];
720
+ if (lines.join() !== this.drawnLines.join()) {
721
+ this.drawnLines = lines;
722
+ this.requestUpdate();
723
+ }
724
+ const gap = this.space;
725
+ const columns = this.columnCount;
667
726
  for (const [at, group] of drawn) {
668
727
  for (const element of group) {
669
728
  this.mark(element, at, chosen, off);
729
+ if (this.waterfall) {
730
+ const style = element.style;
731
+ style.setProperty('position', 'absolute');
732
+ style.setProperty('inset-block-start', `${this.virtualize.offsetOf(at)}px`);
733
+ style.setProperty('inset-inline-start', `calc((100% + ${gap}px) * ${this.lanes.lane(at)} / ${columns})`);
734
+ style.setProperty('inline-size', `calc((100% - ${gap * (columns - 1)}px) / ${columns})`);
735
+ }
670
736
  }
671
737
  const stop = at === this.active;
672
738
  group[0]?.setAttribute('tabindex', stop ? '0' : '-1');
@@ -749,6 +815,9 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
749
815
  return groups;
750
816
  }
751
817
  spacerSizes() {
818
+ if (this.waterfall) {
819
+ return { after: 0, before: 0 };
820
+ }
752
821
  const kept = this.hasUpdated ? this.keptIndex() : undefined;
753
822
  const room = this.virtualize.spacers(kept === undefined ? undefined : this.lineOf(kept));
754
823
  const sections = this.sections;
@@ -783,14 +852,20 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
783
852
  const size = horizontal ? 'inline-size' : 'block-size';
784
853
  const flex = horizontal ? '; flex: none' : '';
785
854
  const gap = this.space;
855
+ const grid = gap === 0 ? '' : `; gap: ${gap}px; padding-block-end: ${gap}px`;
786
856
  const empty = this.readFor !== undefined &&
787
857
  !this.loading &&
788
858
  this.data.length === 0 &&
789
859
  (this.emptyLabel !== '' || this.querySelector(':scope > [slot="empty"]') !== null);
860
+ const lined = this.lined;
861
+ const own = (content) => lined ? html `<div role="gridcell">${content}</div>` : content;
862
+ const role = this.selectionMode ? 'option' : lined ? 'row' : 'listitem';
790
863
  return html `<div
791
864
  data-scroller
792
865
  part="viewport"
793
- role=${this.selectionMode ? 'listbox' : 'list'}
866
+ role=${this.selectionMode ? 'listbox' : lined ? 'grid' : 'list'}
867
+ aria-colcount=${lined ? across : nothing}
868
+ aria-rowcount=${lined ? Math.ceil(this.data.length / across) : nothing}
794
869
  aria-multiselectable=${this.selectionMode === 'multiple' ? 'true' : nothing}
795
870
  aria-busy=${this.loading ? 'true' : nothing}
796
871
  aria-label=${this.label}
@@ -802,24 +877,37 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
802
877
  }}
803
878
  >
804
879
  <div part="before" style="${size}: ${before}px${flex}"></div>
880
+ ${lined
881
+ ? html `<div style=${`display: grid; grid-template-columns: repeat(${across}, minmax(0, 1fr))${grid}`}>
882
+ ${this.drawnLines.map((line) => html `<div
883
+ aria-rowindex=${line + 1}
884
+ role="row"
885
+ style="display: grid; grid-column: 1 / -1; grid-template-columns: subgrid"
886
+ >
887
+ <slot name=${`${LINE}${line}`}></slot>
888
+ </div>`)}
889
+ </div>`
890
+ : nothing}
805
891
  <slot
806
- style=${horizontal
807
- ? `display: flex; flex: none${gap === 0 ? '' : `; column-gap: ${gap}px; padding-inline-end: ${gap}px`}`
808
- : across === 1
809
- ? gap === 0
810
- ? nothing
811
- : `display: flex; flex-direction: column; row-gap: ${gap}px; padding-block-end: ${gap}px`
812
- : `display: grid; grid-template-columns: repeat(${across}, minmax(0, 1fr))${gap === 0 ? '' : `; gap: ${gap}px; padding-block-end: ${gap}px`}`}
892
+ style=${this.waterfall
893
+ ? `display: block; position: relative; block-size: ${this.virtualize.offsetOf(this.data.length)}px`
894
+ : horizontal
895
+ ? `display: flex; flex: none${gap === 0 ? '' : `; column-gap: ${gap}px; padding-inline-end: ${gap}px`}`
896
+ : across === 1 || lined
897
+ ? gap === 0
898
+ ? nothing
899
+ : `display: flex; flex-direction: column; row-gap: ${gap}px; padding-block-end: ${gap}px`
900
+ : `display: grid; grid-template-columns: repeat(${across}, minmax(0, 1fr))${grid}`}
813
901
  ></slot>
814
902
  <div part="after" style="${size}: ${after}px${flex}"></div>
815
903
  ${this.loading
816
- ? html `<div part="loading" role=${this.selectionMode ? 'option' : 'listitem'}>
817
- <slot name="loading">${this.loadingLabel}</slot>
904
+ ? html `<div part="loading" role=${role}>
905
+ ${own(html `<slot name="loading">${this.loadingLabel}</slot>`)}
818
906
  </div>`
819
907
  : nothing}
820
908
  ${empty
821
- ? html `<div part="empty" role=${this.selectionMode ? 'option' : 'listitem'}>
822
- <slot name="empty">${this.emptyLabel}</slot>
909
+ ? html `<div part="empty" role=${role}>
910
+ ${own(html `<slot name="empty">${this.emptyLabel}</slot>`)}
823
911
  </div>`
824
912
  : nothing}
825
913
  </div>`;
@@ -852,6 +940,9 @@ __decorate([
852
940
  __decorate([
853
941
  property()
854
942
  ], HelixHeadlessVirtualList.prototype, "label", void 0);
943
+ __decorate([
944
+ property()
945
+ ], HelixHeadlessVirtualList.prototype, "layout", void 0);
855
946
  __decorate([
856
947
  property({ type: Boolean })
857
948
  ], HelixHeadlessVirtualList.prototype, "loading", void 0);