@fusion.dev/helix-headless 0.25.1 → 0.30.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 (89) hide show
  1. package/custom-elements.json +4966 -755
  2. package/dist/accordion/root/accordion-root.d.ts +5 -6
  3. package/dist/accordion/root/accordion-root.js +13 -36
  4. package/dist/announcement/root/announcement-root.js +1 -1
  5. package/dist/avatar/root/avatar-root.d.ts +17 -3
  6. package/dist/avatar/root/avatar-root.js +27 -8
  7. package/dist/blockquote/root/blockquote-root.js +1 -1
  8. package/dist/button/root/button-root.js +1 -1
  9. package/dist/carousel/root/carousel-root.js +2 -2
  10. package/dist/chat/root/chat-root.js +1 -1
  11. package/dist/checkbox/root/checkbox-root.js +2 -2
  12. package/dist/checkbox-group/root/checkbox-group-root.js +2 -2
  13. package/dist/color-input/root/color-input-root.d.ts +12 -14
  14. package/dist/color-input/root/color-input-root.js +4 -52
  15. package/dist/color-picker/root/color-picker-root.js +2 -2
  16. package/dist/combobox/root/combobox-root.js +11 -14
  17. package/dist/command/root/command-root.js +2 -3
  18. package/dist/data-table/root/data-table-root.js +1 -1
  19. package/dist/date-input/root/date-input-root.d.ts +5 -77
  20. package/dist/date-input/root/date-input-root.js +16 -108
  21. package/dist/date-picker/root/date-picker-root.js +2 -2
  22. package/dist/divider/root/divider-root.js +1 -1
  23. package/dist/drawer/root/drawer-root.js +1 -1
  24. package/dist/drilldown/item/drilldown-item.js +1 -1
  25. package/dist/file-input/root/file-input-root.js +4 -7
  26. package/dist/filter-input/field/filter-field.d.ts +1 -1
  27. package/dist/filter-input/root/filter-input-root.d.ts +2 -2
  28. package/dist/filter-input/root/filter-input-root.js +12 -15
  29. package/dist/heatmap/root/heatmap-root.js +1 -1
  30. package/dist/image/root/image-root.d.ts +7 -0
  31. package/dist/image/root/image-root.js +6 -2
  32. package/dist/input/root/input-root.js +3 -3
  33. package/dist/listbox/root/listbox-root.js +3 -3
  34. package/dist/megamenu/root/megamenu-root.d.ts +12 -2
  35. package/dist/megamenu/root/megamenu-root.js +20 -15
  36. package/dist/menu/item/menu-item.js +1 -1
  37. package/dist/menu/root/menu-root.js +3 -10
  38. package/dist/navigation/root/navigation-root.d.ts +1 -2
  39. package/dist/navigation/root/navigation-root.js +3 -9
  40. package/dist/number-input/root/number-input-root.js +5 -5
  41. package/dist/object-inspector/root/object-inspector-root.js +4 -4
  42. package/dist/outline/root/outline-root.d.ts +0 -1
  43. package/dist/outline/root/outline-root.js +6 -12
  44. package/dist/pin-input/root/pin-input-root.js +2 -2
  45. package/dist/popover/root/popover-root.js +2 -10
  46. package/dist/radio/root/radio-root.js +1 -1
  47. package/dist/scatter-chart/root/scatter-chart-root.js +1 -1
  48. package/dist/scroll-area/root/scroll-area-root.js +1 -1
  49. package/dist/select/root/select-root.js +8 -9
  50. package/dist/slider/root/slider-root.js +2 -2
  51. package/dist/sparkline/root/sparkline-root.d.ts +2 -1
  52. package/dist/sparkline/root/sparkline-root.js +2 -2
  53. package/dist/speed-dial/item/speed-dial-item.js +1 -1
  54. package/dist/speed-dial/root/speed-dial-root.d.ts +2 -2
  55. package/dist/speed-dial/root/speed-dial-root.js +4 -7
  56. package/dist/switch/root/switch-root.js +3 -3
  57. package/dist/table/column/table-column.js +1 -1
  58. package/dist/tabs/root/tabs-root.d.ts +2 -17
  59. package/dist/tabs/root/tabs-root.js +3 -21
  60. package/dist/tabs/tab/tab.js +1 -1
  61. package/dist/textarea/root/textarea-root.js +3 -3
  62. package/dist/time-input/root/time-input-root.d.ts +5 -64
  63. package/dist/time-input/root/time-input-root.js +15 -107
  64. package/dist/time-picker/root/time-picker-root.js +2 -2
  65. package/dist/toggle/group/toggle-group.d.ts +0 -13
  66. package/dist/toggle/group/toggle-group.js +3 -23
  67. package/dist/toggle/root/toggle-root.js +1 -1
  68. package/dist/tooltip/root/tooltip-root.d.ts +0 -13
  69. package/dist/tooltip/root/tooltip-root.js +8 -16
  70. package/dist/tour/root/tour-root.js +6 -6
  71. package/dist/tour/stop/tour-stop.js +2 -2
  72. package/dist/video/root/captions.d.ts +85 -0
  73. package/dist/video/root/captions.js +45 -0
  74. package/dist/video/root/fullscreen.d.ts +28 -0
  75. package/dist/video/root/fullscreen.js +28 -0
  76. package/dist/video/root/idle.d.ts +34 -0
  77. package/dist/video/root/idle.js +24 -0
  78. package/dist/video/root/media-session.d.ts +54 -0
  79. package/dist/video/root/media-session.js +49 -0
  80. package/dist/video/root/remote-playback.d.ts +34 -0
  81. package/dist/video/root/remote-playback.js +38 -0
  82. package/dist/video/root/video-root.d.ts +11 -89
  83. package/dist/video/root/video-root.js +45 -139
  84. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -1
  85. package/dist/video-playlist/menu/video-playlist-menu.js +8 -10
  86. package/dist/virtual-list/root/virtual-list-root.js +1 -1
  87. package/package.json +8 -7
  88. package/types/jsx.d.ts +264 -192
  89. package/types/vue.d.ts +78 -69
@@ -23,9 +23,10 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
23
23
  anchor: () => this.trigger,
24
24
  boundary: () => this,
25
25
  onDismiss: () => this.close(),
26
+ open: () => this.open,
26
27
  place: () => !this.banded,
27
28
  placement: () => 'bottom-start',
28
- surface: () => this.renderRoot?.querySelector('[part="surface"]'),
29
+ surface: () => this.partNamed('surface'),
29
30
  });
30
31
  this.handleScroll = () => {
31
32
  if (!this.open || !this.banded) {
@@ -107,7 +108,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
107
108
  return slot?.assignedElements({ flatten: false })[0];
108
109
  }
109
110
  get trigger() {
110
- return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.renderRoot?.querySelector('[part="trigger"]') ?? this);
111
+ return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.partNamed('trigger') ?? this);
111
112
  }
112
113
  close() {
113
114
  if (!this.requestOpen(false)) {
@@ -148,7 +149,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
148
149
  connectedCallback() {
149
150
  super.connectedCallback();
150
151
  this.watchWidth();
151
- addEventListener('scroll', this.handleScroll, { capture: true, passive: true });
152
+ window.addEventListener('scroll', this.handleScroll, { capture: true, passive: true });
152
153
  this.addEventListener('pointerdown', this.handlePointerDown);
153
154
  this.addEventListener('click', this.handleContentClick);
154
155
  this.addEventListener('pointerenter', this.handlePointerEnter);
@@ -156,7 +157,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
156
157
  }
157
158
  disconnectedCallback() {
158
159
  super.disconnectedCallback();
159
- removeEventListener('scroll', this.handleScroll, { capture: true });
160
+ window.removeEventListener('scroll', this.handleScroll, { capture: true });
160
161
  this.query?.removeEventListener('change', this.handleWidth);
161
162
  this.query = undefined;
162
163
  this.removeEventListener('pointerdown', this.handlePointerDown);
@@ -168,6 +169,21 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
168
169
  showing = undefined;
169
170
  }
170
171
  }
172
+ willUpdate(changed) {
173
+ super.willUpdate(changed);
174
+ if (!changed.has('open')) {
175
+ return;
176
+ }
177
+ if (this.open) {
178
+ if (showing && showing !== this) {
179
+ showing.requestOpen(false);
180
+ }
181
+ showing = this;
182
+ }
183
+ else if (showing === this) {
184
+ showing = undefined;
185
+ }
186
+ }
171
187
  updated(changed) {
172
188
  super.updated?.(changed);
173
189
  if (changed.has('fullBelow')) {
@@ -176,19 +192,8 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
176
192
  this.toggleAttribute('data-narrow', this.narrow);
177
193
  this.tellTrigger();
178
194
  if (this.open) {
179
- if (showing && showing !== this) {
180
- showing.requestOpen(false);
181
- }
182
- showing = this;
183
- this.panel.show();
184
195
  this.band();
185
196
  }
186
- else {
187
- if (showing === this) {
188
- showing = undefined;
189
- }
190
- this.panel.hide();
191
- }
192
197
  }
193
198
  renderTrigger() {
194
199
  return html `<slot name="trigger" @click=${this.handleTriggerClick}>
@@ -70,7 +70,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
70
70
  this.finishHydration();
71
71
  }
72
72
  focus() {
73
- this.renderRoot.querySelector('[part="item"]')?.focus();
73
+ this.partNamed('item')?.focus();
74
74
  }
75
75
  focusItem() {
76
76
  this.focus();
@@ -31,8 +31,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
31
31
  boundary: () => this,
32
32
  offset: () => this.offset,
33
33
  onDismiss: () => this.hide(),
34
+ open: () => this.open,
34
35
  placement: () => this.placement,
35
- surface: () => this.renderRoot?.querySelector('[part="surface"]'),
36
+ surface: () => this.partNamed('surface'),
36
37
  });
37
38
  this.handleSelect = (event) => {
38
39
  const item = event.target;
@@ -56,7 +57,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
56
57
  if (!item) {
57
58
  return;
58
59
  }
59
- const surface = this.renderRoot.querySelector('[part="surface"]');
60
+ const surface = this.partNamed('surface');
60
61
  scrollItemIntoView(item, { padding: 4, ...(surface ? { scroller: surface } : {}) });
61
62
  };
62
63
  this.handleKeydown = (event) => {
@@ -148,14 +149,6 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
148
149
  updated(changed) {
149
150
  super.updated(changed);
150
151
  this.tellTrigger();
151
- if (changed.has('open')) {
152
- if (this.open) {
153
- this.panel.show();
154
- }
155
- else {
156
- this.panel.hide();
157
- }
158
- }
159
152
  for (const child of this.children) {
160
153
  const item = child;
161
154
  if (item.isMenuItem !== true) {
@@ -37,11 +37,10 @@ export declare class HelixHeadlessNavigation extends HelixElement {
37
37
  * Accessible name for the landmark.
38
38
  */
39
39
  label: string;
40
- private observer;
41
40
  private current;
42
41
  /** The destinations the consumer slotted. */
43
42
  private get items();
44
- /** Re-measures when the links change, move, or hand over the current page. */
43
+ /** Re-measures when the links change or hand over the current page. */
45
44
  private watch;
46
45
  connectedCallback(): void;
47
46
  disconnectedCallback(): void;
@@ -12,8 +12,9 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
12
12
  super(...arguments);
13
13
  this.indicator = new IndicatorController(this, {
14
14
  active: () => this.items.find((item) => item.getAttribute('aria-current') === 'page'),
15
- indicator: () => this.renderRoot?.querySelector('[part="indicator"]'),
16
- surface: () => this.renderRoot?.querySelector('[part="nav"]'),
15
+ indicator: () => this.partNamed('indicator'),
16
+ observe: () => this.items,
17
+ surface: () => this.partNamed('nav'),
17
18
  });
18
19
  this.label = 'Main';
19
20
  }
@@ -22,14 +23,8 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
22
23
  return (slot?.assignedElements() ?? []);
23
24
  }
24
25
  watch() {
25
- this.observer?.disconnect();
26
26
  this.current?.disconnect();
27
27
  this.indicator.place();
28
- this.observer = new ResizeObserver(() => this.indicator.place());
29
- this.observer.observe(this);
30
- for (const item of this.items) {
31
- this.observer.observe(item);
32
- }
33
28
  this.current = new MutationObserver(() => this.indicator.place());
34
29
  for (const item of this.items) {
35
30
  this.current.observe(item, { attributeFilter: ['aria-current'] });
@@ -43,7 +38,6 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
43
38
  }
44
39
  disconnectedCallback() {
45
40
  super.disconnectedCallback();
46
- this.observer?.disconnect();
47
41
  this.current?.disconnect();
48
42
  }
49
43
  firstUpdated(changed) {
@@ -15,7 +15,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
15
15
  constructor() {
16
16
  super(...arguments);
17
17
  this.aria = new AriaForwardController(this, {
18
- target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
18
+ target: () => this.partNamed('control'),
19
19
  });
20
20
  this.announcesInput = true;
21
21
  this.autocomplete = '';
@@ -65,7 +65,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
65
65
  }
66
66
  grip.releasePointerCapture(event.pointerId);
67
67
  if (this.value !== this.scrubStart) {
68
- this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
68
+ this.announceChange();
69
69
  }
70
70
  };
71
71
  this.handleInput = (event) => {
@@ -85,7 +85,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
85
85
  };
86
86
  this.handleChange = (event) => {
87
87
  event.stopPropagation();
88
- this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
88
+ this.announceChange();
89
89
  };
90
90
  this.handleKeydown = (event) => {
91
91
  if (event.key === 'ArrowUp') {
@@ -123,7 +123,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
123
123
  delegatesFocus: true,
124
124
  }; }
125
125
  get control() {
126
- return this.renderRoot.querySelector('[part="control"]');
126
+ return this.partNamed('control');
127
127
  }
128
128
  get numeric() {
129
129
  if (this.value.trim() === '') {
@@ -158,7 +158,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
158
158
  restoreValue(control, this.value);
159
159
  }
160
160
  if (applied && this.value !== before) {
161
- this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
161
+ this.announceChange();
162
162
  }
163
163
  }
164
164
  stepUp(large = false) {
@@ -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 { CopyController, customElement, HelixElement, VirtualizeController, } from '@fusion.dev/helix-core';
7
+ import { CopyController, customElement, HelixElement, scrollItemIntoView, VirtualizeController, } from '@fusion.dev/helix-core';
8
8
  import { caretDown, caretRight } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -28,7 +28,7 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
28
28
  this.active = 0;
29
29
  this.revealing = false;
30
30
  this.virtualize = new VirtualizeController(this, {
31
- container: () => this.windowed ? this.renderRoot?.querySelector('[part="tree"]') : null,
31
+ container: () => (this.windowed ? this.partNamed('tree') : null),
32
32
  count: () => this.rows.length,
33
33
  estimate: () => 24,
34
34
  measured: () => this.windowed,
@@ -183,10 +183,10 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
183
183
  }
184
184
  }
185
185
  reveal(attempts = 8) {
186
- const tree = this.renderRoot?.querySelector('[part="tree"]');
186
+ const tree = this.partNamed('tree');
187
187
  const row = tree?.querySelector(`[data-index="${this.active}"]`);
188
188
  if (row) {
189
- row.scrollIntoView({ block: 'nearest' });
189
+ scrollItemIntoView(row);
190
190
  return;
191
191
  }
192
192
  const drawn = [...(tree?.querySelectorAll('[part="row"]') ?? [])];
@@ -82,7 +82,6 @@ export declare class HelixHeadlessOutline extends HelixElement {
82
82
  */
83
83
  private reading;
84
84
  private observer;
85
- private resize;
86
85
  /** The links, in document order. Empty on the server, which has no tree. */
87
86
  private get links();
88
87
  /** What each link points at, paired with the link, skipping anything missing. */
@@ -12,8 +12,8 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
12
12
  super(...arguments);
13
13
  this.indicator = new IndicatorController(this, {
14
14
  active: () => this.links.find((link) => link.hasAttribute('aria-current')),
15
- indicator: () => this.renderRoot?.querySelector('[part="indicator"]'),
16
- surface: () => this.renderRoot?.querySelector('[part="nav"]'),
15
+ indicator: () => this.partNamed('indicator'),
16
+ surface: () => this.partNamed('nav'),
17
17
  });
18
18
  this.behavior = 'auto';
19
19
  this.label = 'On this page';
@@ -47,10 +47,10 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
47
47
  const arrive = () => {
48
48
  clearTimeout(this.landed);
49
49
  this.landing = undefined;
50
- globalThis.document?.removeEventListener('scrollend', arrive, true);
50
+ document.removeEventListener('scrollend', arrive, true);
51
51
  this.mark();
52
52
  };
53
- globalThis.document?.addEventListener('scrollend', arrive, { capture: true, once: true });
53
+ document.addEventListener('scrollend', arrive, { capture: true, once: true });
54
54
  this.landed = setTimeout(arrive, 1200);
55
55
  if (this.behavior === 'auto') {
56
56
  return;
@@ -162,36 +162,30 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
162
162
  disconnectedCallback() {
163
163
  super.disconnectedCallback();
164
164
  this.removeEventListener('click', this.handleClick);
165
- globalThis.document?.removeEventListener('scroll', this.handleScroll, true);
165
+ document.removeEventListener('scroll', this.handleScroll, true);
166
166
  if (this.frame !== 0) {
167
167
  globalThis.cancelAnimationFrame(this.frame);
168
168
  this.frame = 0;
169
169
  }
170
170
  this.observer?.disconnect();
171
171
  this.observer = undefined;
172
- this.resize?.disconnect();
173
- this.resize = undefined;
174
172
  clearTimeout(this.landed);
175
173
  this.landed = undefined;
176
174
  }
177
175
  connectedCallback() {
178
176
  super.connectedCallback();
179
177
  this.addEventListener('click', this.handleClick);
180
- globalThis.document?.addEventListener('scroll', this.handleScroll, {
178
+ document.addEventListener('scroll', this.handleScroll, {
181
179
  capture: true,
182
180
  passive: true,
183
181
  });
184
182
  if (this.hasUpdated) {
185
183
  this.watch();
186
- this.resize = new ResizeObserver(() => this.indicator.place());
187
- this.resize.observe(this);
188
184
  }
189
185
  }
190
186
  firstUpdated(changed) {
191
187
  super.firstUpdated(changed);
192
188
  this.watch();
193
- this.resize = new ResizeObserver(() => this.indicator.place());
194
- this.resize.observe(this);
195
189
  }
196
190
  updated(changed) {
197
191
  super.updated(changed);
@@ -11,7 +11,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
11
11
  constructor() {
12
12
  super(...arguments);
13
13
  this.aria = new AriaForwardController(this, {
14
- target: () => this.renderRoot?.querySelector('[part="cell"]') ?? null,
14
+ target: () => this.partNamed('cell'),
15
15
  });
16
16
  this.announcesInput = true;
17
17
  this.autocomplete = 'one-time-code';
@@ -159,7 +159,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
159
159
  return;
160
160
  }
161
161
  this.committed = this.value;
162
- this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
162
+ this.announceChange();
163
163
  }
164
164
  sync() {
165
165
  this.internals.setFormValue(this.value);
@@ -18,8 +18,9 @@ let HelixHeadlessPopover = class HelixHeadlessPopover extends MixinControllerOpe
18
18
  boundary: () => [this, this.invoker],
19
19
  offset: () => this.offset,
20
20
  onDismiss: () => this.hide(),
21
+ open: () => this.open,
21
22
  placement: () => this.placement,
22
- surface: () => this.renderRoot?.querySelector('[part="popover"]'),
23
+ surface: () => this.partNamed('popover'),
23
24
  });
24
25
  this.commands = new CommandController(this, {
25
26
  commands: {
@@ -73,15 +74,6 @@ let HelixHeadlessPopover = class HelixHeadlessPopover extends MixinControllerOpe
73
74
  updated(changed) {
74
75
  super.updated(changed);
75
76
  this.tellTrigger();
76
- if (!changed.has('open')) {
77
- return;
78
- }
79
- if (this.open) {
80
- this.panel.show();
81
- }
82
- else {
83
- this.panel.hide();
84
- }
85
77
  }
86
78
  render() {
87
79
  return html `<slot name="trigger" @click=${this.handleTriggerClick}></slot>
@@ -22,7 +22,7 @@ let HelixHeadlessRadio = class HelixHeadlessRadio extends HelixElement {
22
22
  this.seeded = next;
23
23
  }
24
24
  focusItem() {
25
- this.renderRoot.querySelector('[part="item"]')?.focus();
25
+ this.partNamed('item')?.focus();
26
26
  }
27
27
  select() {
28
28
  if (this.disabled) {
@@ -53,7 +53,7 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
53
53
  if (event.pointerType !== 'mouse' && event.pointerType !== 'pen') {
54
54
  return;
55
55
  }
56
- const box = this.renderRoot.querySelector('[part="plot"]')?.getBoundingClientRect();
56
+ const box = this.partNamed('plot')?.getBoundingClientRect();
57
57
  if (!box || box.width === 0 || box.height === 0) {
58
58
  return;
59
59
  }
@@ -45,7 +45,7 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
45
45
  };
46
46
  }
47
47
  get scroller() {
48
- return this.renderRoot?.querySelector('[part="viewport"]') ?? null;
48
+ return this.partNamed('viewport');
49
49
  }
50
50
  connectedCallback() {
51
51
  super.connectedCallback();
@@ -16,7 +16,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
16
16
  constructor() {
17
17
  super(...arguments);
18
18
  this.aria = new AriaForwardController(this, {
19
- target: () => this.renderRoot?.querySelector('[part="trigger"]') ?? null,
19
+ target: () => this.partNamed('trigger'),
20
20
  });
21
21
  this.emptyText = 'No matches';
22
22
  this.filterable = false;
@@ -25,15 +25,16 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
25
25
  this.multiple = false;
26
26
  this.placeholder = 'Choose';
27
27
  this.panel = new PopoverController(this, {
28
- anchor: () => this.renderRoot?.querySelector('[part="trigger"]'),
28
+ anchor: () => this.partNamed('trigger'),
29
29
  boundary: () => [
30
- this.renderRoot?.querySelector('[part="surface"]'),
31
- this.renderRoot?.querySelector('[part="trigger"]'),
30
+ this.partNamed('surface'),
31
+ this.partNamed('trigger'),
32
32
  ],
33
33
  offset: () => 4,
34
34
  onDismiss: () => this.close(),
35
+ open: () => this.open,
35
36
  placement: 'bottom-start',
36
- surface: () => this.renderRoot?.querySelector('[part="surface"]'),
37
+ surface: () => this.partNamed('surface'),
37
38
  });
38
39
  this.handleChange = (event) => {
39
40
  const next = event.detail.value;
@@ -66,7 +67,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
66
67
  return this.multiple ? 'select-multiple' : 'select-one';
67
68
  }
68
69
  get listbox() {
69
- return this.renderRoot?.querySelector('[part="listbox"]') ?? null;
70
+ return this.partNamed('listbox');
70
71
  }
71
72
  get display() {
72
73
  const chosen = new Set(this.value === '' ? [] : this.value.split(','));
@@ -80,7 +81,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
80
81
  return;
81
82
  }
82
83
  this.requestOpen(false);
83
- this.renderRoot.querySelector('[part="trigger"]')?.focus();
84
+ this.partNamed('trigger')?.focus();
84
85
  }
85
86
  sync() {
86
87
  this.internals.setFormValue(this.value === '' ? null : this.value);
@@ -99,13 +100,11 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
99
100
  this.sync();
100
101
  this.linkHost();
101
102
  if (this.open) {
102
- this.panel.show();
103
103
  if (changed.has('open')) {
104
104
  this.listbox?.focus();
105
105
  }
106
106
  }
107
107
  else {
108
- this.panel.hide();
109
108
  this.listbox?.requestFilter('');
110
109
  }
111
110
  }
@@ -11,7 +11,7 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
11
11
  constructor() {
12
12
  super(...arguments);
13
13
  this.aria = new AriaForwardController(this, {
14
- target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
14
+ target: () => this.partNamed('control'),
15
15
  });
16
16
  this.announcesInput = true;
17
17
  this.markerLabels = false;
@@ -39,7 +39,7 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
39
39
  };
40
40
  this.handleChange = (event) => {
41
41
  event.stopPropagation();
42
- this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
42
+ this.announceChange();
43
43
  };
44
44
  this.step = 1;
45
45
  }
@@ -49,7 +49,6 @@ import { type PropertyValues, type TemplateResult } from 'lit';
49
49
  * @cssproperty --chart-terminus-y - Where the last point sits vertically, as a percentage.
50
50
  */
51
51
  export declare class HelixHeadlessSparkline extends HelixElement {
52
- #private;
53
52
  /**
54
53
  * How the line gets from one reading to the next.
55
54
  *
@@ -134,6 +133,8 @@ export declare class HelixHeadlessSparkline extends HelixElement {
134
133
  values: string;
135
134
  protected readonly source: SourceController;
136
135
  protected willUpdate(changed: PropertyValues<this>): void;
136
+ /** The series to draw: the table if there is one, the attribute otherwise. */
137
+ private points;
137
138
  protected render(): TemplateResult;
138
139
  }
139
140
  declare global {
@@ -26,14 +26,14 @@ let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
26
26
  this.source.watch();
27
27
  }
28
28
  }
29
- #points() {
29
+ points() {
30
30
  const series = this.source.series;
31
31
  return series.length > 0
32
32
  ? (series[0]?.points.map((point) => point.value) ?? [])
33
33
  : readValues(this.values);
34
34
  }
35
35
  render() {
36
- const points = this.#points();
36
+ const points = this.points();
37
37
  const x = linear([0, Math.max(points.length - 1, 1)], [0, BOX.width]);
38
38
  const [low, high] = extent(points.length > 0 ? points : [0]);
39
39
  const y = this.plot === 'bar'
@@ -18,7 +18,7 @@ let HelixHeadlessSpeedDialItem = class HelixHeadlessSpeedDialItem extends HelixE
18
18
  };
19
19
  }
20
20
  focus() {
21
- this.renderRoot?.querySelector('[part="item"]')?.focus();
21
+ this.partNamed('item')?.focus();
22
22
  }
23
23
  focusItem() {
24
24
  this.focus();
@@ -1,4 +1,4 @@
1
- import { HelixElement, KeyboardNavigationController, type Placement } from '@fusion.dev/helix-core';
1
+ import { HelixElement, KeyboardNavigationController, type Placement, PopoverController } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessSpeedDial_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
4
4
  /**
@@ -61,7 +61,7 @@ export declare class HelixHeadlessSpeedDial extends HelixHeadlessSpeedDial_base
61
61
  */
62
62
  placement: Placement;
63
63
  protected readonly keys: KeyboardNavigationController;
64
- private readonly panel;
64
+ protected readonly panel: PopoverController;
65
65
  /** Whatever the consumer slotted, or the button rendered in its place. */
66
66
  private get trigger();
67
67
  /** The actions, which are this element's own rows and nothing else slotted. */
@@ -23,8 +23,9 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
23
23
  boundary: () => this,
24
24
  offset: () => this.offset,
25
25
  onDismiss: () => this.close(),
26
+ open: () => this.open,
26
27
  placement: () => this.placement,
27
- surface: () => this.renderRoot?.querySelector('[part="actions"]'),
28
+ surface: () => this.partNamed('actions'),
28
29
  });
29
30
  this.handleTriggerClick = () => {
30
31
  this.requestOpen(!this.open);
@@ -46,7 +47,7 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
46
47
  };
47
48
  }
48
49
  get trigger() {
49
- return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.renderRoot?.querySelector('[part="trigger"]') ?? this);
50
+ return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.partNamed('trigger') ?? this);
50
51
  }
51
52
  get items() {
52
53
  const slot = this.renderRoot?.querySelector('slot:not([name])');
@@ -70,7 +71,7 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
70
71
  }
71
72
  announce() {
72
73
  const trigger = this.trigger;
73
- if (trigger === this.renderRoot?.querySelector('[part="trigger"]')) {
74
+ if (trigger === this.partNamed('trigger')) {
74
75
  return;
75
76
  }
76
77
  tellDisclosure(trigger, this.open);
@@ -79,16 +80,12 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
79
80
  super.updated?.(changed);
80
81
  this.announce();
81
82
  if (this.open) {
82
- this.panel.show();
83
83
  this.updateComplete.then(() => {
84
84
  if (this.open) {
85
85
  this.items.find((one) => !one.disabled)?.focusItem();
86
86
  }
87
87
  });
88
88
  }
89
- else {
90
- this.panel.hide();
91
- }
92
89
  }
93
90
  renderTrigger() {
94
91
  return html `<slot name="trigger" @click=${this.handleTriggerClick}>
@@ -11,7 +11,7 @@ let HelixHeadlessSwitch = class HelixHeadlessSwitch extends MixinControllerCheck
11
11
  constructor() {
12
12
  super(...arguments);
13
13
  this.aria = new AriaForwardController(this, {
14
- target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
14
+ target: () => this.partNamed('control'),
15
15
  });
16
16
  this.value = 'on';
17
17
  this.handleChange = (event) => {
@@ -22,7 +22,7 @@ let HelixHeadlessSwitch = class HelixHeadlessSwitch extends MixinControllerCheck
22
22
  if (!taken) {
23
23
  return;
24
24
  }
25
- this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
25
+ this.announceChange();
26
26
  };
27
27
  }
28
28
  sync() {
@@ -38,7 +38,7 @@ let HelixHeadlessSwitch = class HelixHeadlessSwitch extends MixinControllerCheck
38
38
  this.sync();
39
39
  }
40
40
  markEmpty() {
41
- const region = this.renderRoot?.querySelector('[part="label"]');
41
+ const region = this.partNamed('label');
42
42
  const empty = !slotFilled(this.renderRoot?.querySelector('[part="label"] slot'));
43
43
  region?.toggleAttribute('data-empty', empty);
44
44
  region?.toggleAttribute('hidden', empty);
@@ -115,7 +115,7 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
115
115
  }
116
116
  }
117
117
  observeHeading() {
118
- const heading = this.renderRoot?.querySelector('[part="column"]');
118
+ const heading = this.partNamed('column');
119
119
  if (heading) {
120
120
  this.watcher?.observe(heading);
121
121
  }