@fusion.dev/helix-headless 0.31.0 → 0.33.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 (62) hide show
  1. package/custom-elements.json +880 -177
  2. package/dist/area-chart/root/area-chart-root.d.ts +8 -0
  3. package/dist/area-chart/root/area-chart-root.js +1 -0
  4. package/dist/bar-chart/root/bar-chart-root.d.ts +8 -0
  5. package/dist/bar-chart/root/bar-chart-root.js +2 -1
  6. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +1 -1
  7. package/dist/carousel/root/carousel-root.d.ts +12 -0
  8. package/dist/carousel/root/carousel-root.js +17 -11
  9. package/dist/chat/composer/chat-composer.d.ts +4 -0
  10. package/dist/chat/root/chat-root.d.ts +17 -0
  11. package/dist/chat/root/chat-root.js +12 -1
  12. package/dist/code-block/root/code-block-root.d.ts +8 -0
  13. package/dist/code-block/root/code-block-root.js +4 -1
  14. package/dist/color-picker/root/color-picker-root.js +2 -1
  15. package/dist/copy-button/root/copy-button-root.d.ts +8 -0
  16. package/dist/copy-button/root/copy-button-root.js +4 -1
  17. package/dist/data-table/root/data-table-root.d.ts +22 -3
  18. package/dist/data-table/root/data-table-root.js +25 -16
  19. package/dist/date-input/root/date-input-root.d.ts +34 -1
  20. package/dist/date-input/root/date-input-root.js +27 -1
  21. package/dist/date-picker/root/date-picker-root.js +6 -8
  22. package/dist/donut-chart/root/donut-chart-root.d.ts +21 -5
  23. package/dist/donut-chart/root/donut-chart-root.js +18 -6
  24. package/dist/drilldown/item/drilldown-item.d.ts +36 -1
  25. package/dist/drilldown/item/drilldown-item.js +30 -3
  26. package/dist/drilldown/root/drilldown-root.js +5 -4
  27. package/dist/heatmap/root/heatmap-root.d.ts +11 -2
  28. package/dist/icon/root/icon-root.d.ts +8 -0
  29. package/dist/icon/root/icon-root.js +5 -0
  30. package/dist/line-chart/root/line-chart-root.d.ts +9 -1
  31. package/dist/line-chart/root/line-chart-root.js +1 -0
  32. package/dist/menu/item/menu-item.js +1 -1
  33. package/dist/menu/root/menu-root.js +5 -4
  34. package/dist/object-inspector/root/object-inspector-root.d.ts +8 -0
  35. package/dist/object-inspector/root/object-inspector-root.js +20 -15
  36. package/dist/pagination/root/pagination-root.js +1 -1
  37. package/dist/pin-input/root/pin-input-root.d.ts +7 -1
  38. package/dist/pin-input/root/pin-input-root.js +5 -7
  39. package/dist/scatter-chart/root/scatter-chart-root.d.ts +20 -0
  40. package/dist/scatter-chart/root/scatter-chart-root.js +15 -9
  41. package/dist/scroll-area/root/scroll-area-root.js +3 -2
  42. package/dist/sparkline/root/sparkline-root.js +1 -0
  43. package/dist/splitter/root/splitter-root.d.ts +11 -0
  44. package/dist/splitter/root/splitter-root.js +16 -16
  45. package/dist/table/cell/table-cell.d.ts +2 -0
  46. package/dist/table/column/table-column.d.ts +50 -5
  47. package/dist/table/column/table-column.js +24 -5
  48. package/dist/table/root/table-root.d.ts +76 -11
  49. package/dist/table/root/table-root.js +90 -3
  50. package/dist/table/row/table-row.d.ts +14 -0
  51. package/dist/table/row/table-row.js +16 -0
  52. package/dist/toolbar/root/toolbar-root.js +6 -5
  53. package/dist/tooltip/root/tooltip-root.d.ts +20 -0
  54. package/dist/tooltip/root/tooltip-root.js +21 -3
  55. package/dist/tour/root/tour-root.js +1 -1
  56. package/dist/tour/stop/tour-stop.d.ts +15 -0
  57. package/dist/tour/stop/tour-stop.js +16 -2
  58. package/dist/tree/root/tree-root.js +4 -3
  59. package/dist/video/root/video-root.js +7 -0
  60. package/package.json +5 -5
  61. package/types/jsx.d.ts +1556 -582
  62. package/types/vue.d.ts +65 -22
@@ -17,6 +17,20 @@ import { type PropertyValues, type TemplateResult } from 'lit';
17
17
  * @slot - The row's cells.
18
18
  */
19
19
  export declare class HelixHeadlessTableRow extends HelixElement {
20
+ /**
21
+ * @internal Read by the table to find its rows among its children, the way it
22
+ * finds its columns. Not a consumer's to read or set.
23
+ */
24
+ readonly isTableRow = true;
25
+ /** The table's rules this row holds, so the next ones replace them rather than pile up. */
26
+ private columnRules;
27
+ /**
28
+ * @internal Takes the rules the table wrote to line each cell up under its
29
+ * heading, called by that table. Not a consumer's to call: the rules are the
30
+ * table's, and they say which column a cell is in by counting, which only the
31
+ * table that holds the columns can do.
32
+ */
33
+ alignCells(rules: CSSStyleSheet): void;
20
34
  protected willUpdate(changed: PropertyValues): void;
21
35
  protected render(): TemplateResult;
22
36
  }
@@ -7,6 +7,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.isTableRow = true;
13
+ this.columnRules = undefined;
14
+ }
15
+ alignCells(rules) {
16
+ const root = this.renderRoot;
17
+ if (rules === this.columnRules || !(root instanceof ShadowRoot)) {
18
+ return;
19
+ }
20
+ root.adoptedStyleSheets = [
21
+ ...root.adoptedStyleSheets.filter((sheet) => sheet !== this.columnRules),
22
+ rules,
23
+ ];
24
+ this.columnRules = rules;
25
+ }
10
26
  willUpdate(changed) {
11
27
  super.willUpdate(changed);
12
28
  hostAria(this.internals, { role: 'row' });
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { customElement, HelixElement } from '@fusion.dev/helix-core';
7
+ import { customElement, HelixElement, inlineStep } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  const KEYS = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End']);
@@ -41,21 +41,22 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
41
41
  }
42
42
  };
43
43
  this.handleKeydown = (event) => {
44
- const forward = this.axis === 'horizontal' ? 'ArrowRight' : 'ArrowDown';
45
- const back = this.axis === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';
46
44
  if (!KEYS.has(event.key) || claimed(event)) {
47
45
  return;
48
46
  }
47
+ const along = inlineStep(this, event.key);
48
+ const forward = this.axis === 'horizontal' ? along === 1 : event.key === 'ArrowDown';
49
+ const back = this.axis === 'horizontal' ? along === -1 : event.key === 'ArrowUp';
49
50
  const controls = this.controls;
50
51
  const current = controls.findIndex((entry) => entry.contains(event.target));
51
52
  if (current === -1) {
52
53
  return;
53
54
  }
54
55
  let next = current;
55
- if (event.key === forward) {
56
+ if (forward) {
56
57
  next = (current + 1) % controls.length;
57
58
  }
58
- else if (event.key === back) {
59
+ else if (back) {
59
60
  next = (current - 1 + controls.length) % controls.length;
60
61
  }
61
62
  else if (event.key === 'Home') {
@@ -52,9 +52,21 @@ declare const HelixHeadlessTooltip_base: (new (...args: any[]) => import("@fusio
52
52
  * @event {Event} toggle - Says the state moved, carrying `newState` and `oldState`.
53
53
  *
54
54
  * @csspart arrow - The point, resting against the trigger.
55
+ * @csspart arrow-bottom - The point while the bubble is below its trigger, so on the bubble's top edge, beside `arrow`.
56
+ * @csspart arrow-left - The point while the bubble is left of its trigger, so on the bubble's right edge, beside `arrow`.
57
+ * @csspart arrow-right - The point while the bubble is right of its trigger, so on the bubble's left edge, beside `arrow`.
58
+ * @csspart arrow-top - The point while the bubble is above its trigger, so on the bubble's bottom edge, beside `arrow`.
55
59
  * @csspart tooltip - The bubble.
60
+ * @csspart tooltip-bottom - The bubble while it is below its trigger, beside `tooltip`.
61
+ * @csspart tooltip-left - The bubble while it is left of its trigger, beside `tooltip`.
62
+ * @csspart tooltip-right - The bubble while it is right of its trigger, beside `tooltip`.
63
+ * @csspart tooltip-top - The bubble while it is above its trigger, beside `tooltip`.
56
64
  *
57
65
  * @cssstate open - While the tooltip shows.
66
+ * @cssstate placed-bottom - While the bubble sits below its trigger.
67
+ * @cssstate placed-left - While the bubble sits to the left of its trigger.
68
+ * @cssstate placed-right - While the bubble sits to the right of its trigger.
69
+ * @cssstate placed-top - While the bubble sits above its trigger.
58
70
  */
59
71
  export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
60
72
  /**
@@ -150,6 +162,14 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
150
162
  * `FloatingController` for what happens if it is applied to the rest.
151
163
  */
152
164
  within: string;
165
+ /**
166
+ * The side of its trigger the bubble last landed on, which is not always
167
+ * `placement`: a bubble with no room there is moved.
168
+ *
169
+ * Undefined until the first placement, which the server never makes, so a
170
+ * part name it adds is never markup the server did not send.
171
+ */
172
+ private side?;
153
173
  private timer;
154
174
  /**
155
175
  * What is currently keeping the bubble up.
@@ -6,7 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { anchorElement, customElement, HelixElement, hostAria, MixinControllerOpen, PopoverController, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
- import { property } from 'lit/decorators.js';
9
+ import { property, state } from 'lit/decorators.js';
10
10
  const GENERIC = new Set(['div', 'p', 'section', 'span']);
11
11
  let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpen(HelixElement) {
12
12
  constructor() {
@@ -33,6 +33,14 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
33
33
  this.holds.clear();
34
34
  this.hide();
35
35
  },
36
+ onPlace: (placement) => {
37
+ const side = placement.split('-')[0];
38
+ this.toggleState('placed-bottom', side === 'bottom');
39
+ this.toggleState('placed-left', side === 'left');
40
+ this.toggleState('placed-right', side === 'right');
41
+ this.toggleState('placed-top', side === 'top');
42
+ this.side = side;
43
+ },
36
44
  placement: () => this.placement,
37
45
  surface: () => this.partNamed('tooltip'),
38
46
  within: () => this.enclosure,
@@ -235,9 +243,16 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
235
243
  });
236
244
  }
237
245
  render() {
246
+ const side = this.side;
238
247
  return html `<slot></slot>
239
- <div part="tooltip" popover="manual" role="tooltip">
240
- <span part="arrow"></span>
248
+ <div
249
+ part="tooltip${side ? { bottom: ' tooltip-bottom', left: ' tooltip-left', right: ' tooltip-right', top: ' tooltip-top' }[side] : ''}"
250
+ popover="manual"
251
+ role="tooltip"
252
+ >
253
+ <span
254
+ part="arrow${side ? { bottom: ' arrow-bottom', left: ' arrow-left', right: ' arrow-right', top: ' arrow-top' }[side] : ''}"
255
+ ></span>
241
256
  <slot name="content" @slotchange=${this.handleContentChange}
242
257
  >${this.content}</slot
243
258
  >
@@ -271,6 +286,9 @@ __decorate([
271
286
  __decorate([
272
287
  property()
273
288
  ], HelixHeadlessTooltip.prototype, "within", void 0);
289
+ __decorate([
290
+ state()
291
+ ], HelixHeadlessTooltip.prototype, "side", void 0);
274
292
  HelixHeadlessTooltip = __decorate([
275
293
  customElement('helix-headless-tooltip')
276
294
  ], HelixHeadlessTooltip);
@@ -192,7 +192,7 @@ let HelixHeadlessTour = class HelixHeadlessTour extends HelixElement {
192
192
  : html `<div
193
193
  part="spotlight"
194
194
  aria-hidden="true"
195
- style=${`inset-block-start: ${spot.top}px; inset-inline-start: ${spot.left}px; block-size: ${spot.height}px; inline-size: ${spot.width}px`}
195
+ style=${`left: ${spot.left}px; top: ${spot.top}px; block-size: ${spot.height}px; inline-size: ${spot.width}px`}
196
196
  ></div>`}
197
197
  <slot></slot>`;
198
198
  }
@@ -46,6 +46,10 @@ import '../../button/index.js';
46
46
  *
47
47
  * @csspart actions - The row the controls sit in.
48
48
  * @csspart arrow - The point, which the floating pass places against the target.
49
+ * @csspart arrow-bottom - The point while the panel is below its target, so on the panel's top edge, beside `arrow`.
50
+ * @csspart arrow-left - The point while the panel is left of its target, so on the panel's right edge, beside `arrow`.
51
+ * @csspart arrow-right - The point while the panel is right of its target, so on the panel's left edge, beside `arrow`.
52
+ * @csspart arrow-top - The point while the panel is above its target, so on the panel's bottom edge, beside `arrow`.
49
53
  * @csspart back - The control that goes to the previous stop.
50
54
  * @csspart back-button - The inner control.
51
55
  * @csspart bubble - The panel that points at the target.
@@ -54,6 +58,11 @@ import '../../button/index.js';
54
58
  * @csspart next-button - The inner control.
55
59
  * @csspart skip - The control that leaves the tour.
56
60
  * @csspart skip-button - The inner control.
61
+ *
62
+ * @cssstate placed-bottom - While the panel sits below its target.
63
+ * @cssstate placed-left - While the panel sits to the left of its target.
64
+ * @cssstate placed-right - While the panel sits to the right of its target.
65
+ * @cssstate placed-top - While the panel sits above its target.
57
66
  */
58
67
  export declare class HelixHeadlessTourStop extends HelixElement {
59
68
  /**
@@ -98,6 +107,12 @@ export declare class HelixHeadlessTourStop extends HelixElement {
98
107
  * Label for the control that leaves the tour.
99
108
  */
100
109
  skipLabel: string;
110
+ /**
111
+ * The side of its target the panel last landed on, which names the arrow's
112
+ * second part. Undefined until the first placement, which the server never
113
+ * makes.
114
+ */
115
+ private side?;
101
116
  /** The element this stop is about, or null where the id resolves to nothing. */
102
117
  get target(): HTMLElement | null;
103
118
  private readonly floating;
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { customElement, HelixElement, HelixTourAskEvent, hostAria, PopoverController, } from '@fusion.dev/helix-core';
8
- import { property } from 'lit/decorators.js';
8
+ import { property, state } from 'lit/decorators.js';
9
9
  import { html } from 'lit/static-html.js';
10
10
  import '../../button/index.js';
11
11
  let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
@@ -28,6 +28,14 @@ let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
28
28
  return ((tour?.spotlightPadding ?? 0) + (this.partNamed('arrow')?.offsetWidth ?? 0) / Math.SQRT2);
29
29
  },
30
30
  onDismiss: () => { },
31
+ onPlace: (placement) => {
32
+ const side = placement.split('-')[0];
33
+ this.toggleState('placed-bottom', side === 'bottom');
34
+ this.toggleState('placed-left', side === 'left');
35
+ this.toggleState('placed-right', side === 'right');
36
+ this.toggleState('placed-top', side === 'top');
37
+ this.side = side;
38
+ },
31
39
  placement: () => this.placement,
32
40
  surface: () => this.partNamed('bubble'),
33
41
  });
@@ -80,7 +88,10 @@ let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
80
88
  render() {
81
89
  return html `<div part="bubble" popover="manual" ?hidden=${!this.current}>
82
90
  ${''}
83
- <div part="arrow" aria-hidden="true"></div>
91
+ <div
92
+ part="arrow${this.side ? { bottom: ' arrow-bottom', left: ' arrow-left', right: ' arrow-right', top: ' arrow-top' }[this.side] : ''}"
93
+ aria-hidden="true"
94
+ ></div>
84
95
  <div part="content"><slot></slot></div>
85
96
  <div part="actions">
86
97
  ${this.renderActions()}
@@ -118,6 +129,9 @@ __decorate([
118
129
  __decorate([
119
130
  property({ attribute: 'skip-label' })
120
131
  ], HelixHeadlessTourStop.prototype, "skipLabel", void 0);
132
+ __decorate([
133
+ state()
134
+ ], HelixHeadlessTourStop.prototype, "side", void 0);
121
135
  HelixHeadlessTourStop = __decorate([
122
136
  customElement('helix-headless-tour-stop')
123
137
  ], HelixHeadlessTourStop);
@@ -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 { closestInstance, customElement, HelixElement, MixinCollection, MixinControllerActive, scrollItemIntoView, } from '@fusion.dev/helix-core';
7
+ import { closestInstance, customElement, HelixElement, inlineStep, MixinCollection, MixinControllerActive, scrollItemIntoView, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { HelixHeadlessTreeItem } from '../item/tree-item.js';
@@ -31,6 +31,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
31
31
  if (!current || !this.items.includes(current) || !KEYS.has(event.key)) {
32
32
  return;
33
33
  }
34
+ const along = inlineStep(this, event.key);
34
35
  if (event.key === 'ArrowDown') {
35
36
  this.move(current, 1);
36
37
  }
@@ -43,7 +44,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
43
44
  else if (event.key === 'End') {
44
45
  this.focusOn(this.visibleItems.at(-1));
45
46
  }
46
- else if (event.key === 'ArrowRight') {
47
+ else if (along === 1) {
47
48
  if (current.isBranch && !current.open) {
48
49
  current.requestOpen(true);
49
50
  this.syncItems();
@@ -52,7 +53,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
52
53
  this.move(current, 1);
53
54
  }
54
55
  }
55
- else if (event.key === 'ArrowLeft') {
56
+ else if (along === -1) {
56
57
  if (current.isBranch && current.open) {
57
58
  current.requestOpen(false);
58
59
  this.syncItems();
@@ -689,8 +689,15 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
689
689
  ${drawIcon(this.playing ? pause : play)}
690
690
  </button>
691
691
  <span part="time">${clock(this.position)} / ${clock(this.knownDuration)}</span>
692
+ <!-- Left to right on every page. A player's timeline is a tape running
693
+ one way rather than a line of text, which is why its skip glyphs are
694
+ not mirrored and the left arrow rewinds whatever the script. Allowed
695
+ to follow the page, a range turns round on a right-to-left one, and
696
+ the arrows on the scrubber moved through time the other way to the
697
+ same arrows pressed on the video. -->
692
698
  <input
693
699
  part="scrubber"
700
+ dir="ltr"
694
701
  type="range"
695
702
  min="0"
696
703
  max=${Number.isFinite(this.knownDuration) && this.knownDuration > 0 ? this.knownDuration : 0}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fusion.dev/helix-headless",
3
3
  "description": "Headless component tier. Structure, accessibility, state, and form participation. No styling.",
4
- "version": "0.31.0",
4
+ "version": "0.33.0",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -46,14 +46,14 @@
46
46
  },
47
47
  "bugs": "https://github.com/project-fusion/fusion/issues",
48
48
  "dependencies": {
49
- "@fusion.dev/helix-core": "0.31.0",
50
- "@fusion.dev/helix-icons": "0.31.0",
49
+ "@fusion.dev/helix-core": "0.33.0",
50
+ "@fusion.dev/helix-icons": "0.33.0",
51
51
  "uqr": "^0.1.3"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@custom-elements-manifest/analyzer": "^0.11.0",
55
- "@fusion.dev/helix-cem": "0.31.0",
56
- "@fusion.dev/helix-testing": "0.31.0",
55
+ "@fusion.dev/helix-cem": "0.33.0",
56
+ "@fusion.dev/helix-testing": "0.33.0",
57
57
  "@fusion.dev/scripts": "0.0.0-dev",
58
58
  "@happy-dom/global-registrator": "^20.0.0",
59
59
  "@lit-labs/ssr": "^4.1.0",