@fusion.dev/helix-headless 0.164.0 → 0.166.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 (44) hide show
  1. package/custom-elements.json +837 -64
  2. package/dist/callout/root/callout-root.d.ts +8 -2
  3. package/dist/callout/root/callout-root.js +14 -1
  4. package/dist/code-block/root/code-block-root.d.ts +63 -0
  5. package/dist/code-block/root/code-block-root.js +117 -6
  6. package/dist/date-input/root/date-input-root.d.ts +3 -3
  7. package/dist/date-input/root/date-input-root.js +8 -5
  8. package/dist/element-events.generated.js +15 -2
  9. package/dist/filter-input/menu/filter-menu.d.ts +1 -0
  10. package/dist/filter-input/menu/filter-menu.js +1 -1
  11. package/dist/format-date/root/format-date-root.d.ts +3 -1
  12. package/dist/format-date/root/format-date-root.js +4 -1
  13. package/dist/lightbox/item/lightbox-item.js +3 -1
  14. package/dist/lightbox/root/lightbox-root.d.ts +28 -0
  15. package/dist/lightbox/root/lightbox-root.js +21 -2
  16. package/dist/listbox/root/listbox-root.js +2 -5
  17. package/dist/menu/item/menu-item.d.ts +20 -0
  18. package/dist/menu/item/menu-item.js +53 -20
  19. package/dist/menu/root/menu-root.d.ts +84 -1
  20. package/dist/menu/root/menu-root.js +187 -44
  21. package/dist/number-input/root/number-input-root.d.ts +32 -9
  22. package/dist/number-input/root/number-input-root.js +53 -9
  23. package/dist/object-inspector/root/object-inspector-root.d.ts +5 -0
  24. package/dist/object-inspector/root/object-inspector-root.js +5 -0
  25. package/dist/option/root/index.d.ts +1 -0
  26. package/dist/option/root/index.js +1 -0
  27. package/dist/steps/root/steps-root.d.ts +7 -0
  28. package/dist/steps/root/steps-root.js +7 -0
  29. package/dist/tag/root/index.d.ts +1 -0
  30. package/dist/tag/root/index.js +1 -0
  31. package/dist/time-input/root/time-input-root.d.ts +4 -3
  32. package/dist/time-input/root/time-input-root.js +5 -4
  33. package/dist/time-picker/root/time-picker-root.d.ts +1 -1
  34. package/dist/time-picker/root/time-picker-root.js +5 -2
  35. package/dist/video/root/video-root.d.ts +2 -0
  36. package/dist/video/root/video-root.js +4 -2
  37. package/dist/video-playlist/menu/video-playlist-menu.d.ts +1 -0
  38. package/dist/video-playlist/menu/video-playlist-menu.js +1 -1
  39. package/dist/video-playlist/root/video-playlist-root.js +15 -1
  40. package/lint.json +1 -1
  41. package/package.json +5 -5
  42. package/types/jsx.d.ts +310 -44
  43. package/types/vue.d.ts +68 -11
  44. package/types/words.d.ts +18 -0
@@ -390,6 +390,11 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
390
390
  private counted;
391
391
  /** Says how many entries the filter matched, and nothing for an empty one. */
392
392
  private tell;
393
+ /**
394
+ * Moves focus to the row the keys move from, or to the tree while that row
395
+ * is scrolled out of the window, as Tab reaches them.
396
+ */
397
+ focus(options?: FocusOptions): void;
393
398
  protected firstUpdated(changed: PropertyValues): void;
394
399
  protected updated(changed: PropertyValues): void;
395
400
  /**
@@ -268,6 +268,11 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
268
268
  this.status.say(this.counted('result', this.found.size));
269
269
  }
270
270
  }
271
+ focus(options) {
272
+ this.renderRoot
273
+ ?.querySelector('#tree[tabindex="0"], #tree [tabindex="0"]')
274
+ ?.focus(options);
275
+ }
271
276
  firstUpdated(changed) {
272
277
  super.firstUpdated(changed);
273
278
  this.finishHydration();
@@ -0,0 +1 @@
1
+ export * from './option-root.js';
@@ -0,0 +1 @@
1
+ export * from './option-root.js';
@@ -158,6 +158,13 @@ export declare class HelixHeadlessSteps extends HelixHeadlessSteps_base {
158
158
  * calls to `next()` in one task then move two stages.
159
159
  */
160
160
  private get at();
161
+ /**
162
+ * Requests a new current stage, and returns whether it moved.
163
+ *
164
+ * Where only a step's `current` says where the reader is, `active` is first
165
+ * written with that step, so `helix-activate` names it as `previous`.
166
+ */
167
+ requestActive(next: string, cause?: string): boolean;
161
168
  /**
162
169
  * Moves to the next stage that can be gone to, as Ark UI's `goToNextStep`
163
170
  * does. Returns whether it moved: not past the last stage, not into a stage
@@ -65,6 +65,13 @@ let HelixHeadlessSteps = class HelixHeadlessSteps extends MixinControllerActive(
65
65
  const item = this.resolveActive(steps);
66
66
  return item ? steps.indexOf(item) : -1;
67
67
  }
68
+ requestActive(next, cause) {
69
+ const here = this.active === '' ? this.steps[this.at]?.value : undefined;
70
+ if (here) {
71
+ this.active = here;
72
+ }
73
+ return super.requestActive(next, cause);
74
+ }
68
75
  next() {
69
76
  return this.step(1);
70
77
  }
@@ -0,0 +1 @@
1
+ export * from './tag-root.js';
@@ -0,0 +1 @@
1
+ export * from './tag-root.js';
@@ -1,6 +1,6 @@
1
1
  import { AriaForwardController, HelixFormElement, type HourCycle } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
- import '../../tag/index.js';
3
+ import '../../tag/root/index.js';
4
4
  import '../../time-picker/index.js';
5
5
  declare const HelixHeadlessTimeInput_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinSegmentedFieldInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinPickerEditingInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinPickerFieldInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinTokensInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
6
6
  /**
@@ -349,8 +349,9 @@ export declare class HelixHeadlessTimeInput extends HelixHeadlessTimeInput_base
349
349
  /**
350
350
  * Each time, where `mode` holds several, sent one entry each.
351
351
  *
352
- * One time that is text and no time, such as `2:45 P`, is sent as an empty
353
- * entry, as a native time field sends a time it cannot read.
352
+ * Text that is no time, such as `2:45 P`, is sent as one empty entry, as a
353
+ * native time field sends a time it cannot read. Measured before this: a
354
+ * range written `09:00/10:30` was invalid and submitted the text.
354
355
  */
355
356
  protected get answers(): readonly string[] | undefined;
356
357
  /** What is wrong with the times, which the text input cannot say. */
@@ -4,13 +4,13 @@ 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 { AriaForwardController, valueAsTime as asTime, clockLocale, customElement, drawIcon, formatWords, timeAsValue as fromTime, HelixClearEvent, HelixFormElement, handedLocale, isClockValue, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerEditing, MixinPickerField, MixinSegmentedField, MixinTokens, readWrittenTime, timeFault, words, wordsLocale, writeClock, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, valueAsTime as asTime, clockLocale, customElement, drawIcon, formatWords, timeAsValue as fromTime, HelixClearEvent, HelixFormElement, handedLocale, hostWords, isClockValue, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerEditing, MixinPickerField, MixinSegmentedField, MixinTokens, readWrittenTime, slottedWords, timeFault, words, wordsLocale, writeClock, } from '@fusion.dev/helix-core';
8
8
  import { clock, x } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
11
11
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
12
12
  import { html } from 'lit/static-html.js';
13
- import '../../tag/index.js';
13
+ import '../../tag/root/index.js';
14
14
  import '../../time-picker/index.js';
15
15
  let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmentedField(MixinPickerEditing(MixinPickerField(MixinControllerOpen(MixinTokens(MixinControllerValue(MixinField(HelixFormElement))))))) {
16
16
  constructor() {
@@ -174,7 +174,8 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmented
174
174
  }
175
175
  get answers() {
176
176
  if (this.mode !== undefined) {
177
- return this.held;
177
+ const held = this.held;
178
+ return held.every((one) => this.isTime(one)) ? held : [''];
178
179
  }
179
180
  const text = this.value.trim();
180
181
  return text === '' || this.isTime(text) ? undefined : [''];
@@ -242,7 +243,7 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmented
242
243
  variant=${this.variant ?? nothing}
243
244
  disable-times=${this.disableTimes || nothing}
244
245
  manual
245
- label=${this.label || 'Time'}
246
+ label=${hostWords(this, slottedWords(this, ['label']) || this.label) || 'Time'}
246
247
  hour-cycle=${this.hourCycle ?? nothing}
247
248
  locale=${handedLocale(this) || nothing}
248
249
  max=${this.max}
@@ -1,7 +1,7 @@
1
1
  import { HelixFormElement, type HourCycle, type PickerFailure } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  import '../../listbox/index.js';
4
- import '../../option/index.js';
4
+ import '../../option/root/index.js';
5
5
  declare const HelixHeadlessTimePicker_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinPickerFeedbackInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & typeof HelixFormElement;
6
6
  /**
7
7
  * @summary A control for choosing a time from a list or from wheels.
@@ -10,7 +10,7 @@ import { property, state } from 'lit/decorators.js';
10
10
  import { html } from 'lit/static-html.js';
11
11
  import { wheelName } from '../wheel-name.js';
12
12
  import '../../listbox/index.js';
13
- import '../../option/index.js';
13
+ import '../../option/root/index.js';
14
14
  let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerFeedback(MixinControllerValue(HelixFormElement)) {
15
15
  constructor() {
16
16
  super(...arguments);
@@ -275,7 +275,8 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
275
275
  this.internals.setFormValue(null);
276
276
  return;
277
277
  }
278
- reportValues(this.internals, this.name, this.held);
278
+ const held = this.held;
279
+ reportValues(this.internals, this.name, held.every((one) => valueAsSeconds(one) !== null) ? held : ['']);
279
280
  }
280
281
  async revealWhenSettled() {
281
282
  const settling = [
@@ -356,6 +357,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
356
357
  data-column=${part}
357
358
  aria-describedby=${this.describedBy}
358
359
  aria-invalid=${this.marked ? 'true' : nothing}
360
+ aria-required=${this.required ? 'true' : nothing}
359
361
  exportparts="empty: column-empty, error: column-error, feedback: column-feedback, filter-icon: column-filter-icon,
360
362
  filter-mark: column-filter-mark, hint: column-hint, items: column-items, label: column-label,
361
363
  live: column-live, loading: column-loading, search: column-search, search-field: column-search-field"
@@ -408,6 +410,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
408
410
  part="list"
409
411
  aria-describedby=${this.describedBy}
410
412
  aria-invalid=${this.marked ? 'true' : nothing}
413
+ aria-required=${this.required ? 'true' : nothing}
411
414
  exportparts="empty: list-empty, error: list-error, feedback: list-feedback, filter-icon: list-filter-icon,
412
415
  filter-mark: list-filter-mark, hint: list-hint, items: list-items, label: list-label,
413
416
  live: list-live, loading: list-loading, search: list-search, search-field: list-search-field"
@@ -115,6 +115,7 @@ import '../../menu/index.js';
115
115
  * @csspart captions-menu-header - The bar above a submenu, holding the way back and its name.
116
116
  * @csspart captions-menu-live - The inner menu's `live` part, a live region that repeats the empty and loading text for screen readers.
117
117
  * @csspart captions-menu-loading - The text shown while the items are loading.
118
+ * @csspart captions-menu-search-field - The inner menu's filter field, drawn with `filterable`.
118
119
  * @csspart captions-menu-surface - The floating panel the menu is drawn on.
119
120
  * @csspart captions-menu-title - The name of the submenu that is showing.
120
121
  * @csspart controls - The control bar along the bottom.
@@ -148,6 +149,7 @@ import '../../menu/index.js';
148
149
  * @csspart overflow-header - The bar above a submenu, holding the way back and its name.
149
150
  * @csspart overflow-live - The inner menu's `live` part, a live region that repeats the empty and loading text for screen readers.
150
151
  * @csspart overflow-loading - The text shown while the items are loading.
152
+ * @csspart overflow-search-field - The inner menu's filter field, drawn with `filterable`.
151
153
  * @csspart overflow-surface - The floating panel the menu is drawn on.
152
154
  * @csspart overflow-title - The name of the submenu that is showing.
153
155
  * @csspart pip - The picture-in-picture button, when `extra-controls` includes it and the browser supports it.
@@ -594,7 +594,8 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
594
594
  }
595
595
  return html `<${this.tag('menu')} part="captions-menu"
596
596
  exportparts="back: captions-menu-back, back-mark: captions-menu-back-mark, empty: captions-menu-empty,
597
- header: captions-menu-header, live: captions-menu-live, loading: captions-menu-loading, surface: captions-menu-surface,
597
+ header: captions-menu-header, live: captions-menu-live, loading: captions-menu-loading,
598
+ search-field: captions-menu-search-field, surface: captions-menu-surface,
598
599
  title: captions-menu-title" label=${this.subtitlesLabel} placement="top-end"
599
600
  @toggle=${(event) => this.heardMenu('captions', event)}>
600
601
  <button
@@ -804,7 +805,8 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
804
805
  ? nothing
805
806
  : html `<${this.tag('menu')} part="overflow"
806
807
  exportparts="back: overflow-back, back-mark: overflow-back-mark, empty: overflow-empty,
807
- header: overflow-header, live: overflow-live, loading: overflow-loading, surface: overflow-surface,
808
+ header: overflow-header, live: overflow-live, loading: overflow-loading,
809
+ search-field: overflow-search-field, surface: overflow-surface,
808
810
  title: overflow-title" label=${this.moreLabel} placement="top-end"
809
811
  @toggle=${(event) => this.heardMenu('overflow', event)}>
810
812
  <button
@@ -38,6 +38,7 @@ import '../../menu/index.js';
38
38
  * @csspart menu-header - The bar above a submenu, holding the back button and the submenu's name.
39
39
  * @csspart menu-live - The inner menu's `live` part, the region screen readers announce its empty and loading messages from.
40
40
  * @csspart menu-loading - Shown while the items are loading.
41
+ * @csspart menu-search-field - The inner menu's filter field, drawn with `filterable`.
41
42
  * @csspart menu-surface - The floating panel the menu is drawn on.
42
43
  * @csspart menu-title - The name of the submenu that is shown.
43
44
  * @csspart poster - An entry's poster image, if it has one.
@@ -84,7 +84,7 @@ let HelixHeadlessVideoPlaylistMenu = class HelixHeadlessVideoPlaylistMenu extend
84
84
  renderMenu() {
85
85
  return html `<${this.tag('menu')} part="menu"
86
86
  exportparts="back: menu-back, back-mark: menu-back-mark, empty: menu-empty, header: menu-header,
87
- live: menu-live, loading: menu-loading, surface: menu-surface, title: menu-title" label=${this.label} placement=${this.placement}
87
+ live: menu-live, loading: menu-loading, search-field: menu-search-field, surface: menu-surface, title: menu-title" label=${this.label} placement=${this.placement}
88
88
  @toggle=${this.heardToggle}>
89
89
  <slot name="trigger" slot="trigger">
90
90
  <button
@@ -47,8 +47,16 @@ let HelixHeadlessVideoPlaylist = class HelixHeadlessVideoPlaylist extends MixinC
47
47
  if (event.defaultPrevented) {
48
48
  return;
49
49
  }
50
+ const value = event.detail.value;
51
+ const player = this.player;
52
+ if (value === this.active) {
53
+ if (player && player.paused !== false) {
54
+ void Promise.resolve(player.play()).catch(() => { });
55
+ }
56
+ return;
57
+ }
50
58
  this.chased = true;
51
- this.requestActive(event.detail.value, 'press');
59
+ this.requestActive(value, 'press');
52
60
  };
53
61
  this.handleFocusIn = (event) => {
54
62
  const entry = event.target;
@@ -259,6 +267,12 @@ let HelixHeadlessVideoPlaylist = class HelixHeadlessVideoPlaylist extends MixinC
259
267
  if (changed.has('shuffle') && !this.shuffle) {
260
268
  this.dealt = undefined;
261
269
  }
270
+ if (this.active === '' && this.childrenKnown) {
271
+ const opening = this.resolveActive(this.items);
272
+ if (opening) {
273
+ this.active = opening.value;
274
+ }
275
+ }
262
276
  }
263
277
  updated(changed) {
264
278
  super.updated?.(changed);