@fusion.dev/helix-headless 0.32.0 → 0.33.1

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 (61) hide show
  1. package/custom-elements.json +876 -164
  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 +11 -7
  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 +25 -3
  13. package/dist/code-block/root/code-block-root.js +16 -5
  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.js +1 -1
  25. package/dist/drilldown/root/drilldown-root.js +5 -4
  26. package/dist/heatmap/root/heatmap-root.d.ts +11 -2
  27. package/dist/icon/root/icon-root.d.ts +8 -0
  28. package/dist/icon/root/icon-root.js +5 -0
  29. package/dist/line-chart/root/line-chart-root.d.ts +9 -1
  30. package/dist/line-chart/root/line-chart-root.js +1 -0
  31. package/dist/menu/item/menu-item.js +1 -1
  32. package/dist/menu/root/menu-root.js +5 -4
  33. package/dist/object-inspector/root/object-inspector-root.d.ts +8 -0
  34. package/dist/object-inspector/root/object-inspector-root.js +20 -15
  35. package/dist/pagination/root/pagination-root.js +1 -1
  36. package/dist/pin-input/root/pin-input-root.d.ts +7 -1
  37. package/dist/pin-input/root/pin-input-root.js +5 -7
  38. package/dist/scatter-chart/root/scatter-chart-root.d.ts +20 -0
  39. package/dist/scatter-chart/root/scatter-chart-root.js +15 -9
  40. package/dist/scroll-area/root/scroll-area-root.js +3 -2
  41. package/dist/sparkline/root/sparkline-root.js +1 -0
  42. package/dist/splitter/root/splitter-root.d.ts +11 -0
  43. package/dist/splitter/root/splitter-root.js +16 -16
  44. package/dist/table/cell/table-cell.d.ts +2 -0
  45. package/dist/table/column/table-column.d.ts +40 -6
  46. package/dist/table/column/table-column.js +23 -3
  47. package/dist/table/root/table-root.d.ts +76 -11
  48. package/dist/table/root/table-root.js +90 -3
  49. package/dist/table/row/table-row.d.ts +14 -0
  50. package/dist/table/row/table-row.js +16 -0
  51. package/dist/toolbar/root/toolbar-root.js +6 -5
  52. package/dist/tooltip/root/tooltip-root.d.ts +20 -0
  53. package/dist/tooltip/root/tooltip-root.js +21 -3
  54. package/dist/tour/root/tour-root.js +1 -1
  55. package/dist/tour/stop/tour-stop.d.ts +10 -0
  56. package/dist/tour/stop/tour-stop.js +9 -2
  57. package/dist/tree/root/tree-root.js +4 -3
  58. package/dist/video/root/video-root.js +7 -0
  59. package/package.json +5 -5
  60. package/types/jsx.d.ts +1506 -596
  61. package/types/vue.d.ts +55 -23
@@ -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 { valueAsDate as asDate, customElement, dateAsValue as fromDate, HelixFormElement, HelixNavigateEvent, hostAria, MixinControllerValue, requestChange, } from '@fusion.dev/helix-core';
7
+ import { valueAsDate as asDate, customElement, dateAsValue as fromDate, HelixFormElement, HelixNavigateEvent, hostAria, inlineStep, MixinControllerValue, requestChange, } from '@fusion.dev/helix-core';
8
8
  import { caretLeft, caretRight } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -75,14 +75,12 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
75
75
  return;
76
76
  }
77
77
  const from = this.anchor;
78
+ const along = inlineStep(this, event.key);
78
79
  if (event.key === 'Enter' || event.key === ' ') {
79
80
  this.select(from);
80
81
  }
81
- else if (event.key === 'ArrowLeft') {
82
- this.moveTo(addDays(from, -1));
83
- }
84
- else if (event.key === 'ArrowRight') {
85
- this.moveTo(addDays(from, 1));
82
+ else if (along !== 0) {
83
+ this.moveTo(addDays(from, along));
86
84
  }
87
85
  else if (event.key === 'ArrowUp') {
88
86
  this.moveTo(addDays(from, -7));
@@ -296,14 +294,14 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
296
294
  }
297
295
  renderPreviousMark() {
298
296
  return html `<slot name="previous-icon">
299
- <svg part="previous-mark" fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
297
+ <svg part="previous-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
300
298
  ${unsafeSVG(caretLeft.content)}
301
299
  </svg>
302
300
  </slot>`;
303
301
  }
304
302
  renderNextMark() {
305
303
  return html `<slot name="next-icon">
306
- <svg part="next-mark" fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
304
+ <svg part="next-mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
307
305
  ${unsafeSVG(caretRight.content)}
308
306
  </svg>
309
307
  </slot>`;
@@ -33,9 +33,17 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
33
33
  * @csspart tooltip - The bubble, forwarded from `Tooltip`.
34
34
  * @csspart tooltip-anchor - The `Tooltip` element itself.
35
35
  * @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
36
+ * @csspart tooltip-arrow-bottom - The point while the bubble is below the reading, so on its top edge, beside `tooltip-arrow`.
37
+ * @csspart tooltip-arrow-left - The point while the bubble is left of the reading, so on its right edge, beside `tooltip-arrow`.
38
+ * @csspart tooltip-arrow-right - The point while the bubble is right of the reading, so on its left edge, beside `tooltip-arrow`.
39
+ * @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
40
+ * @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
36
41
  * @csspart tooltip-cell - One column's name and value inside the tooltip.
37
42
  * @csspart tooltip-label - The slice's own name inside the tooltip.
43
+ * @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
38
44
  * @csspart tooltip-name - A column's name inside the tooltip.
45
+ * @csspart tooltip-right - The bubble while it is right of the reading, beside `tooltip`.
46
+ * @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
39
47
  * @csspart tooltip-value - A column's value inside the tooltip.
40
48
  * @csspart track - The ring the slices are drawn on.
41
49
  *
@@ -45,7 +53,7 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
45
53
  /**
46
54
  * The pointer is not mapped across this one.
47
55
  *
48
- * Every other chart lays its readings out left to right, so the nearest is
56
+ * Every other chart lays its readings out along the line, so the nearest is
49
57
  * arithmetic on x. A ring's slices are real elements at every angle, and x
50
58
  * alone would answer with whichever slice shared a horizontal position with
51
59
  * the pointer: at three o'clock and at nine o'clock it would give the same
@@ -104,6 +112,14 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
104
112
  sweep?: 'half';
105
113
  /** The fraction of the circle the shares are spread over. */
106
114
  private get span();
115
+ /**
116
+ * Where the first slice starts, as an angle from three o'clock.
117
+ *
118
+ * Twelve for a whole ring and nine for a half, the turns the stylesheet gives
119
+ * the circles. Anything drawn or placed by arithmetic has to start from the
120
+ * same place, or it describes a slice the ring is not showing there.
121
+ */
122
+ private get origin();
107
123
  /** How thick the ring is drawn, in the drawing's own units. */
108
124
  private get thickness();
109
125
  /** The ring's radius, which follows its thickness so the outer edge holds. */
@@ -161,10 +177,10 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
161
177
  * turn, so a growing slice would pop partway through the transition it was
162
178
  * meant to smooth. Both animations stay on the dash and this path follows it.
163
179
  *
164
- * The turn to twelve o'clock is arithmetic here rather than the rotation the
165
- * stylesheet gives the circles. That rule uses `transform-box: fill-box`, so
166
- * it spins each element about its own bounding box, which is the ring's center
167
- * for a circle and is not for a sector.
180
+ * The turn to twelve o'clock, or to nine for a half, is `origin` here rather
181
+ * than the rotation the stylesheet gives the circles. That rule uses
182
+ * `transform-box: fill-box`, so it spins each element about its own bounding
183
+ * box, which is the ring's center for a circle and is not for a sector.
168
184
  */
169
185
  protected renderEdge(share: {
170
186
  fraction: number;
@@ -26,6 +26,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
26
26
  get span() {
27
27
  return this.sweep === 'half' ? 0.5 : 1;
28
28
  }
29
+ get origin() {
30
+ return this.sweep === 'half' ? Math.PI : -Math.PI / 2;
31
+ }
29
32
  get thickness() {
30
33
  return THICKNESS[this.hole ?? 'medium'] ?? THICKNESS.medium ?? 0;
31
34
  }
@@ -61,7 +64,11 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
61
64
  part="plot"
62
65
  style="--donut-chart-stroke: ${this.thickness}"
63
66
  >
64
- <svg viewBox=${this.frame} xmlns="http://www.w3.org/2000/svg">
67
+ <svg
68
+ data-mirror=${this.sweep === 'half' ? '' : nothing}
69
+ viewBox=${this.frame}
70
+ xmlns="http://www.w3.org/2000/svg"
71
+ >
65
72
  <circle
66
73
  cx=${CENTER}
67
74
  cy=${CENTER}
@@ -104,8 +111,8 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
104
111
  }
105
112
  renderEdge(share, index) {
106
113
  const turn = 2 * Math.PI * this.span;
107
- const from = share.start * turn - Math.PI / 2;
108
- const to = (share.start + share.fraction) * turn - Math.PI / 2;
114
+ const from = share.start * turn + this.origin;
115
+ const to = (share.start + share.fraction) * turn + this.origin;
109
116
  const outer = EDGE;
110
117
  const inner = EDGE - this.thickness;
111
118
  const at = (radius, angle) => `${(CENTER + Math.cos(angle) * radius).toFixed(3)} ${(CENTER + Math.sin(angle) * radius).toFixed(3)}`;
@@ -139,13 +146,18 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
139
146
  if (!share) {
140
147
  return drawTooltip(this.sourceRows, at, this.tag('tooltip'));
141
148
  }
142
- const angle = (share.start + share.fraction / 2) * 2 * Math.PI - Math.PI / 2;
149
+ const angle = (share.start + share.fraction / 2) * 2 * Math.PI * this.span + this.origin;
143
150
  const edge = EDGE;
144
151
  const x = CENTER + Math.cos(angle) * edge;
145
- const y = CENTER + Math.sin(angle) * edge;
152
+ const top = this.sweep === 'half' ? CENTER - EDGE : 0;
153
+ const tall = this.sweep === 'half' ? EDGE + this.thickness / 2 : BOX;
154
+ const y = ((CENTER + Math.sin(angle) * edge - top) / tall) * 100;
155
+ const turned = this.sweep === 'half' && this.pointer.mirrored;
156
+ const across = Math.cos(angle) > 0 !== turned;
146
157
  return drawTooltip(this.sourceRows, at, this.tag('tooltip'), {
158
+ fixed: this.sweep !== 'half',
147
159
  placement: Math.abs(Math.cos(angle)) > Math.abs(Math.sin(angle))
148
- ? Math.cos(angle) > 0
160
+ ? across
149
161
  ? 'right'
150
162
  : 'left'
151
163
  : Math.sin(angle) > 0
@@ -63,7 +63,7 @@ let HelixHeadlessDrilldownItem = class HelixHeadlessDrilldownItem extends HelixE
63
63
  <span part="label"><slot></slot></span>
64
64
  <slot name="end"></slot>
65
65
  ${this.page
66
- ? html `<svg part="mark" fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
66
+ ? html `<svg part="mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
67
67
  ${unsafeSVG(caretRight.content)}
68
68
  </svg>`
69
69
  : nothing}
@@ -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, DrilldownController, HelixElement, hostAria, MixinCollection, } from '@fusion.dev/helix-core';
7
+ import { customElement, DrilldownController, HelixElement, hostAria, inlineStep, MixinCollection, } from '@fusion.dev/helix-core';
8
8
  import { caretLeft } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -53,14 +53,15 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
53
53
  (event.key === 'Home' ? items[0] : items[items.length - 1])?.focusItem();
54
54
  return;
55
55
  }
56
- if (event.key === 'ArrowLeft' || event.key === 'Escape') {
56
+ const along = inlineStep(this, event.key);
57
+ if (along === -1 || event.key === 'Escape') {
57
58
  if (this.back()) {
58
59
  event.preventDefault();
59
60
  event.stopPropagation();
60
61
  }
61
62
  return;
62
63
  }
63
- if (event.key === 'ArrowRight' && current !== -1) {
64
+ if (along === 1 && current !== -1) {
64
65
  const item = items[current];
65
66
  if (item && this.drilldown.hasPage(item)) {
66
67
  event.preventDefault();
@@ -144,7 +145,7 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
144
145
  ? ''
145
146
  : html `<div part="header">
146
147
  <button part="back" type="button" aria-label=${this.backLabel} @click=${() => this.back()}>
147
- <svg part="back-mark" fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
148
+ <svg part="back-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
148
149
  ${unsafeSVG(caretLeft.content)}
149
150
  </svg>
150
151
  </button>
@@ -50,9 +50,17 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
50
50
  * @csspart tooltip - The bubble, forwarded from `Tooltip`.
51
51
  * @csspart tooltip-anchor - The `Tooltip` element itself.
52
52
  * @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
53
+ * @csspart tooltip-arrow-bottom - The point while the bubble is below the reading, so on its top edge, beside `tooltip-arrow`.
54
+ * @csspart tooltip-arrow-left - The point while the bubble is left of the reading, so on its right edge, beside `tooltip-arrow`.
55
+ * @csspart tooltip-arrow-right - The point while the bubble is right of the reading, so on its left edge, beside `tooltip-arrow`.
56
+ * @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
57
+ * @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
53
58
  * @csspart tooltip-cell - One column's name and value inside the tooltip.
54
59
  * @csspart tooltip-label - The reading's own name inside the tooltip.
60
+ * @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
55
61
  * @csspart tooltip-name - A column's name inside the tooltip.
62
+ * @csspart tooltip-right - The bubble while it is right of the reading, beside `tooltip`.
63
+ * @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
56
64
  * @csspart tooltip-value - A column's value inside the tooltip.
57
65
  *
58
66
  * @cssproperty --heatmap-cell-height - How tall a cell is. A row of a tall thin cell is what a status page draws.
@@ -110,8 +118,9 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
110
118
  *
111
119
  * `1` is a status strip and `7` is a calendar week, which are the two readings
112
120
  * this covers. Cells fill down the column and then across, which is what a
113
- * calendar heatmap does: a week is a column, so the strip reads left to right
114
- * in weeks and top to bottom in days.
121
+ * calendar heatmap does: a week is a column, so the strip reads along the
122
+ * line in weeks, from the right on a right-to-left page, and top to bottom in
123
+ * days.
115
124
  */
116
125
  rows: number;
117
126
  /**
@@ -40,6 +40,14 @@ export declare class HelixHeadlessIcon extends HelixElement {
40
40
  * Accessible name, for an icon that is not decorative.
41
41
  */
42
42
  label: string;
43
+ /**
44
+ * Turns the glyph round on a right-to-left page, for an arrow meaning forward or back.
45
+ *
46
+ * Asked for rather than inferred from the name. The names are physical, and
47
+ * `arrow-left` drawn pointing right on an Arabic page would be the icon
48
+ * disagreeing with its own name for every reader who meant the left.
49
+ */
50
+ mirror: boolean;
43
51
  /**
44
52
  * Name of the icon in the Helix set.
45
53
  */
@@ -13,6 +13,7 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
13
13
  constructor() {
14
14
  super(...arguments);
15
15
  this.label = '';
16
+ this.mirror = false;
16
17
  this.name = '';
17
18
  }
18
19
  render() {
@@ -23,6 +24,7 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
23
24
  const labeled = this.label.length > 0;
24
25
  return html `<svg
25
26
  part="svg"
27
+ ?data-mirror=${this.mirror}
26
28
  fill="currentColor"
27
29
  viewBox=${icon.viewBox}
28
30
  role=${labeled ? 'img' : nothing}
@@ -36,6 +38,9 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
36
38
  __decorate([
37
39
  property()
38
40
  ], HelixHeadlessIcon.prototype, "label", void 0);
41
+ __decorate([
42
+ property({ type: Boolean })
43
+ ], HelixHeadlessIcon.prototype, "mirror", void 0);
39
44
  __decorate([
40
45
  property()
41
46
  ], HelixHeadlessIcon.prototype, "name", void 0);
@@ -56,9 +56,17 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
56
56
  * @csspart tooltip - The bubble, forwarded from `Tooltip`.
57
57
  * @csspart tooltip-anchor - The `Tooltip` element itself.
58
58
  * @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
59
+ * @csspart tooltip-arrow-bottom - The point while the bubble is below the reading, so on its top edge, beside `tooltip-arrow`.
60
+ * @csspart tooltip-arrow-left - The point while the bubble is left of the reading, so on its right edge, beside `tooltip-arrow`.
61
+ * @csspart tooltip-arrow-right - The point while the bubble is right of the reading, so on its left edge, beside `tooltip-arrow`.
62
+ * @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
63
+ * @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
59
64
  * @csspart tooltip-cell - One column's name and value inside the tooltip.
60
65
  * @csspart tooltip-label - The reading's own name inside the tooltip.
66
+ * @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
61
67
  * @csspart tooltip-name - A column's name inside the tooltip.
68
+ * @csspart tooltip-right - The bubble while it is right of the reading, beside `tooltip`.
69
+ * @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
62
70
  * @csspart tooltip-value - A column's value inside the tooltip.
63
71
  */
64
72
  export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base {
@@ -127,7 +135,7 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
127
135
  * property with a default writes its attribute onto a host the consumer
128
136
  * rendered, which React reports as a hydration mismatch.
129
137
  *
130
- * **One per series, in a column at the right edge**, because every series here
138
+ * **One per series, in a column at the far edge**, because every series here
131
139
  * shares an x-axis and therefore ends at the same reading. That column is the
132
140
  * useful thing: it is where a reader looks for "and what is it now", which is
133
141
  * the question a sparkline's single mark answers too.
@@ -69,6 +69,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
69
69
  style=${holes ? `--_line-chart-holes: ${holes}` : nothing}
70
70
  >
71
71
  <svg part="svg"
72
+ data-mirror
72
73
  preserveAspectRatio="none"
73
74
  viewBox="0 0 ${WIDTH} ${HEIGHT}"
74
75
  xmlns="http://www.w3.org/2000/svg"
@@ -106,7 +106,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
106
106
  ${submenu
107
107
  ? html `<svg
108
108
  part="mark"
109
- data-submenu
109
+ data-mirror
110
110
  fill="currentColor"
111
111
  viewBox=${caretRight.viewBox}
112
112
  aria-hidden="true"
@@ -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 { anchorElement, customElement, DrilldownController, HelixElement, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, tellDisclosure, } from '@fusion.dev/helix-core';
7
+ import { anchorElement, customElement, DrilldownController, HelixElement, inlineStep, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, tellDisclosure, } from '@fusion.dev/helix-core';
8
8
  import { caretLeft } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
@@ -63,14 +63,15 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
63
63
  this.handleKeydown = (event) => {
64
64
  const items = this.items;
65
65
  const at = items.indexOf(document.activeElement);
66
+ const along = inlineStep(this, event.key);
66
67
  if (event.key === 'Escape') {
67
68
  event.stopPropagation();
68
69
  this.leave();
69
70
  }
70
- else if (event.key === 'ArrowRight' && items[at]?.hasSubmenu) {
71
+ else if (along === 1 && items[at]?.hasSubmenu) {
71
72
  this.enter(items[at]);
72
73
  }
73
- else if (event.key === 'ArrowLeft') {
74
+ else if (along === -1) {
74
75
  this.leave();
75
76
  }
76
77
  else if (event.key === 'Tab') {
@@ -195,7 +196,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
195
196
  aria-label=${this.backLabel}
196
197
  @click=${() => this.leave()}
197
198
  >
198
- <svg part="back-mark" fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
199
+ <svg part="back-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
199
200
  ${unsafeSVG(caretLeft.content)}
200
201
  </svg>
201
202
  </button>
@@ -69,6 +69,14 @@ interface Row {
69
69
  * @csspart copy-mark - The clipboard glyph, and the confirmation that replaces it.
70
70
  * @csspart copy-tooltip - The bubble, forwarded from the tooltip inside.
71
71
  * @csspart copy-tooltip-arrow - The point, resting against the trigger.
72
+ * @csspart copy-tooltip-arrow-bottom - The point while the bubble is below the copy button, so on its top edge, beside `copy-tooltip-arrow`.
73
+ * @csspart copy-tooltip-arrow-left - The point while the bubble is left of the copy button, so on its right edge, beside `copy-tooltip-arrow`.
74
+ * @csspart copy-tooltip-arrow-right - The point while the bubble is right of the copy button, so on its left edge, beside `copy-tooltip-arrow`.
75
+ * @csspart copy-tooltip-arrow-top - The point while the bubble is above the copy button, so on its bottom edge, beside `copy-tooltip-arrow`.
76
+ * @csspart copy-tooltip-bottom - The bubble while it is below the copy button, beside `copy-tooltip`.
77
+ * @csspart copy-tooltip-left - The bubble while it is left of the copy button, beside `copy-tooltip`.
78
+ * @csspart copy-tooltip-right - The bubble while it is right of the copy button, beside `copy-tooltip`.
79
+ * @csspart copy-tooltip-top - The bubble while it is above the copy button, beside `copy-tooltip`.
72
80
  * @csspart count - How many entries a branch holds.
73
81
  * @csspart frame - The tree and the copy button beside it.
74
82
  * @csspart header - The bar carrying the label, where there is one.
@@ -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, scrollItemIntoView, VirtualizeController, } from '@fusion.dev/helix-core';
7
+ import { CopyController, customElement, HelixElement, inlineStep, 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';
@@ -64,15 +64,16 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
64
64
  this.move(rows.length - 1);
65
65
  break;
66
66
  case 'ArrowRight':
67
- if (row.branch && !row.open) {
68
- this.toggle(row, true);
67
+ case 'ArrowLeft':
68
+ if (inlineStep(this, event.key) === 1) {
69
+ if (row.branch && !row.open) {
70
+ this.toggle(row, true);
71
+ }
72
+ else if (row.open) {
73
+ this.move(this.active + 1);
74
+ }
69
75
  }
70
76
  else if (row.open) {
71
- this.move(this.active + 1);
72
- }
73
- break;
74
- case 'ArrowLeft':
75
- if (row.open) {
76
77
  this.toggle(row, false);
77
78
  }
78
79
  else {
@@ -238,21 +239,21 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
238
239
  const array = Array.isArray(value);
239
240
  const noun = array ? (count === 1 ? 'item' : 'items') : count === 1 ? 'key' : 'keys';
240
241
  return html `<span part="summary">${array ? '[…]' : '{…}'}</span>
241
- <span part="count">${`${count} ${noun}`}</span>`;
242
+ <span part="count" dir="auto">${`${count} ${noun}`}</span>`;
242
243
  }
243
244
  if (typeof value === 'string') {
244
- return html `<span part="string">${JSON.stringify(value)}</span>`;
245
+ return html `<span part="string" dir="ltr">${JSON.stringify(value)}</span>`;
245
246
  }
246
247
  if (typeof value === 'number') {
247
- return html `<span part="number">${String(value)}</span>`;
248
+ return html `<span part="number" dir="ltr">${String(value)}</span>`;
248
249
  }
249
250
  if (typeof value === 'boolean') {
250
- return html `<span part="boolean">${String(value)}</span>`;
251
+ return html `<span part="boolean" dir="ltr">${String(value)}</span>`;
251
252
  }
252
253
  if (value === null) {
253
- return html `<span part="null">null</span>`;
254
+ return html `<span part="null" dir="ltr">null</span>`;
254
255
  }
255
- return html `<span part="string">${String(value)}</span>`;
256
+ return html `<span part="string" dir="ltr">${String(value)}</span>`;
256
257
  }
257
258
  renderRow(row, index) {
258
259
  const active = index === this.active;
@@ -272,6 +273,7 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
272
273
  ${row.branch
273
274
  ? html `<svg
274
275
  part="toggle"
276
+ ?data-mirror=${!row.open}
275
277
  fill="currentColor"
276
278
  viewBox=${(row.open ? caretDown : caretRight).viewBox}
277
279
  aria-hidden="true"
@@ -285,7 +287,10 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
285
287
  return staticHtml `<${this.tag('copy-button')}
286
288
  part="copy"
287
289
  exportparts="button: copy-button, mark: copy-mark, tooltip: copy-tooltip,
288
- tooltip-arrow: copy-tooltip-arrow"
290
+ tooltip-arrow: copy-tooltip-arrow, tooltip-arrow-bottom: copy-tooltip-arrow-bottom,
291
+ tooltip-arrow-left: copy-tooltip-arrow-left, tooltip-arrow-right: copy-tooltip-arrow-right,
292
+ tooltip-arrow-top: copy-tooltip-arrow-top, tooltip-bottom: copy-tooltip-bottom,
293
+ tooltip-left: copy-tooltip-left, tooltip-right: copy-tooltip-right, tooltip-top: copy-tooltip-top"
289
294
  label=${row?.key === undefined ? 'Copy value' : `Copy ${row.key}`}
290
295
  .value=${this.copyable(row)}
291
296
  ></${this.tag('copy-button')}>`;
@@ -180,7 +180,7 @@ let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement
180
180
  return {
181
181
  address: spent ? nothing : fill(this.href, to, this.count),
182
182
  click: (event) => this.go(to, event),
183
- glyph: html `<svg part="mark" fill="currentColor" viewBox=${icon.viewBox} aria-hidden="true">
183
+ glyph: html `<svg part="mark" data-mirror fill="currentColor" viewBox=${icon.viewBox} aria-hidden="true">
184
184
  ${unsafeSVG(icon.content)}
185
185
  </svg>`,
186
186
  name,
@@ -27,6 +27,12 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
27
27
  * the field as a whole, and repeating it on six boxes offers a browser six
28
28
  * places to put one code.
29
29
  *
30
+ * **Left to right on every page.** A code is read the way a phone number is,
31
+ * one character after another from the left, in Arabic and Hebrew as in
32
+ * English, so the row carries `dir="ltr"`: the first box is the leftmost, a
33
+ * paste fills rightward and the right arrow moves on. The label, the hint and
34
+ * the feedback are words and keep the page's direction.
35
+ *
30
36
  * @since 0.1.0
31
37
  * @status stable
32
38
  * @category forms
@@ -40,7 +46,7 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
40
46
  *
41
47
  * @csspart cell - One box.
42
48
  * @csspart feedback - What is wrong with it.
43
- * @csspart field - The row of boxes.
49
+ * @csspart field - The row of boxes, left to right on every page.
44
50
  * @csspart hint - Help under the boxes, while nothing is wrong.
45
51
  * @csspart label - The question, over the boxes.
46
52
  *
@@ -56,6 +56,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
56
56
  if (at === -1 || this.isDisabled || this.readOnly) {
57
57
  return;
58
58
  }
59
+ const to = at + (event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0);
59
60
  if (event.key === 'Backspace' && cell.value === '' && at > 0) {
60
61
  const characters = this.characters;
61
62
  characters[at - 1] = '';
@@ -65,13 +66,9 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
65
66
  this.cells[at - 1]?.focus();
66
67
  });
67
68
  }
68
- else if (event.key === 'ArrowLeft' && at > 0) {
69
- this.cells[at - 1]?.focus();
70
- this.cells[at - 1]?.select();
71
- }
72
- else if (event.key === 'ArrowRight' && at < this.count - 1) {
73
- this.cells[at + 1]?.focus();
74
- this.cells[at + 1]?.select();
69
+ else if (to !== at && to >= 0 && to < this.count) {
70
+ this.cells[to]?.focus();
71
+ this.cells[to]?.select();
75
72
  }
76
73
  else {
77
74
  return;
@@ -203,6 +200,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
203
200
  const characters = this.characters;
204
201
  return html `${this.renderGroupLabel()}
205
202
  <div
203
+ dir="ltr"
206
204
  part="field"
207
205
  role="group"
208
206
  aria-describedby=${this.describedBy ?? nothing}
@@ -46,6 +46,17 @@ declare const HelixHeadlessScatterChart_base: typeof HelixElement & (new (...arg
46
46
  * a `<span>` placed by percentage over it, which is how `LineChart` draws its
47
47
  * termini and for the same reason.
48
48
  *
49
+ * **Left to right on every page, the one chart here that is.** A bar or a line
50
+ * chart's across is the order its readings are named in, which follows the
51
+ * line of text and turns with it. Here it is a measure, and a measure has a
52
+ * direction of its own: more is to the right in every script, as a number line
53
+ * is. So the plot, its axes and the names at their ends sit in a `plane` part
54
+ * that carries `dir="ltr"`, which holds the y axis on the left and the points,
55
+ * rules, ticks, pointer and tooltip mark where a left-to-right page puts them,
56
+ * with no stylesheet asked to know. The names carry `dir="auto"`, so one written
57
+ * in Arabic or Hebrew still reads its own way; the summary is outside the plane
58
+ * and the bubble is told the page's direction, both being words.
59
+ *
49
60
  * @since 0.1.0
50
61
  * @status experimental
51
62
  * @category charts
@@ -54,6 +65,7 @@ declare const HelixHeadlessScatterChart_base: typeof HelixElement & (new (...arg
54
65
  *
55
66
  * @csspart gridline - One rule across the plot, under `gridlines`.
56
67
  * @csspart mark - The invisible point the tooltip is anchored to.
68
+ * @csspart plane - The plot, both axes and their names, left to right on every page. The grid they are laid out in.
57
69
  * @csspart plot - The drawing.
58
70
  * @csspart point - One row, as a point.
59
71
  * @csspart point-active - A point of the row a pointer is asking about, beside `point`.
@@ -62,9 +74,17 @@ declare const HelixHeadlessScatterChart_base: typeof HelixElement & (new (...arg
62
74
  * @csspart tooltip - The bubble, forwarded from `Tooltip`.
63
75
  * @csspart tooltip-anchor - The `Tooltip` element itself.
64
76
  * @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
77
+ * @csspart tooltip-arrow-bottom - The point while the bubble is below the reading, so on its top edge, beside `tooltip-arrow`.
78
+ * @csspart tooltip-arrow-left - The point while the bubble is left of the reading, so on its right edge, beside `tooltip-arrow`.
79
+ * @csspart tooltip-arrow-right - The point while the bubble is right of the reading, so on its left edge, beside `tooltip-arrow`.
80
+ * @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
81
+ * @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
65
82
  * @csspart tooltip-cell - One column's name and value inside the tooltip.
66
83
  * @csspart tooltip-label - The row's own name inside the tooltip.
84
+ * @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
67
85
  * @csspart tooltip-name - A column's name inside the tooltip.
86
+ * @csspart tooltip-right - The bubble while it is right of the reading, beside `tooltip`.
87
+ * @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
68
88
  * @csspart tooltip-value - A column's value inside the tooltip.
69
89
  * @csspart x-axis - The levels measured across, under the plot.
70
90
  * @csspart x-name - What is measured across.
@@ -124,20 +124,24 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
124
124
  const field = this.field;
125
125
  this.drawn = field.points;
126
126
  if (field.points.length === 0) {
127
- return html `<div id="helix-chart-plot" part="plot"></div>`;
127
+ return html `<div dir="ltr" part="plane">
128
+ <div id="helix-chart-plot" part="plot"></div>
129
+ </div>`;
128
130
  }
129
131
  const format = formatNumbers('');
130
132
  const along = linear(field.x, [0, WIDTH]);
131
133
  const up = linear(field.y, [HEIGHT, 0]);
132
- return html `${this.renderPlot(field, along, up)}
133
- <div aria-hidden="true" part="x-axis">
134
- ${ticks(field.x).map((level) => html `<span part="x-tick" style="--chart-tick: ${along(level)}%">${format(level)}</span>`)}
134
+ return html `<div dir="ltr" part="plane">
135
+ ${this.renderPlot(field, along, up)}
136
+ <div aria-hidden="true" part="x-axis">
137
+ ${ticks(field.x).map((level) => html `<span part="x-tick" style="--chart-tick: ${along(level)}%">${format(level)}</span>`)}
138
+ </div>
139
+ <div aria-hidden="true" part="y-axis">
140
+ ${ticks(field.y).map((level) => html `<span part="y-tick" style="--chart-tick: ${up(level)}%">${format(level)}</span>`)}
141
+ </div>
142
+ <span aria-hidden="true" dir="auto" part="x-name">${field.xName}</span>
143
+ <span aria-hidden="true" dir="auto" part="y-name">${field.yNames.join(', ')}</span>
135
144
  </div>
136
- <div aria-hidden="true" part="y-axis">
137
- ${ticks(field.y).map((level) => html `<span part="y-tick" style="--chart-tick: ${up(level)}%">${format(level)}</span>`)}
138
- </div>
139
- <span aria-hidden="true" part="x-name">${field.xName}</span>
140
- <span aria-hidden="true" part="y-name">${field.yNames.join(', ')}</span>
141
145
  ${this.renderSummary(field)}`;
142
146
  }
143
147
  renderPlot(field, along, up) {
@@ -184,6 +188,8 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
184
188
  return drawTooltip(this.sourceRows, -1, this.tag('tooltip'));
185
189
  }
186
190
  return drawTooltip(this.sourceRows, at, this.tag('tooltip'), {
191
+ dir: getComputedStyle(this).direction === 'rtl' ? 'rtl' : 'ltr',
192
+ fixed: true,
187
193
  placement: 'top',
188
194
  x: `${point.x}%`,
189
195
  y: `${point.y}%`,
@@ -27,10 +27,11 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
27
27
  if (box.scrollTop + box.clientHeight < box.scrollHeight - slack) {
28
28
  found.push('block-end');
29
29
  }
30
- if (box.scrollLeft > slack) {
30
+ const along = Math.abs(box.scrollLeft);
31
+ if (along > slack) {
31
32
  found.push('inline-start');
32
33
  }
33
- if (box.scrollLeft + box.clientWidth < box.scrollWidth - slack) {
34
+ if (along + box.clientWidth < box.scrollWidth - slack) {
34
35
  found.push('inline-end');
35
36
  }
36
37
  this.more = found;