@fusion.dev/helix-headless 0.39.0 → 0.41.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.
@@ -15,7 +15,7 @@ declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("
15
15
  * `display` has overridden the first.
16
16
  *
17
17
  * @since 0.1.0
18
- * @status experimental
18
+ * @status stable
19
19
  * @aliases Collapsible, Expander, Disclosure
20
20
  * @documentation https://fusion.dev/helix/components/accordion
21
21
  *
@@ -25,7 +25,7 @@ import { HelixHeadlessAccordionItem } from '../item/accordion-item.js';
25
25
  * to hear.
26
26
  *
27
27
  * @since 0.1.0
28
- * @status experimental
28
+ * @status stable
29
29
  * @category layout
30
30
  * @aliases Collapse, Expander group
31
31
  * @documentation https://fusion.dev/helix/components/accordion
@@ -34,12 +34,28 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
34
34
  * else draws every part in proportion to nothing. `LineChart` measures from its
35
35
  * own range because a line claims a position; a band claims an amount.
36
36
  *
37
+ * **And so it is not a streamgraph**, which is the near neighbor to name.
38
+ * A streamgraph moves its baseline to center the bands and reads as a river; it
39
+ * is a real form and it is the one thing the rule above refuses, so this
40
+ * carries no alias for it. What it has instead is `share`, which answers the
41
+ * question a streamgraph is usually reached for, how the composition changed,
42
+ * without giving up a floor a reader can measure against.
43
+ *
37
44
  * **Straight between readings unless asked otherwise.** A band's top edge is a
38
45
  * sum, and a curve fitted through one sum can pass under the curve fitted
39
46
  * through the sum beneath it, so a smoothed stack can draw a part as less than
40
47
  * nothing between two readings. Straight segments between ordered points stay
41
48
  * ordered. `curve="smooth"` is there for a stack that is read as a shape.
42
49
  *
50
+ * `curve="step"` falls on the safe side of that argument rather than being
51
+ * unanswered by it, and it is worth saying which side because a reader cannot
52
+ * tell from the argument alone. A step takes no value the readings do not have:
53
+ * it holds one, jumps at the midpoint, and holds the next. So two stepped edges
54
+ * that are ordered at every reading are ordered everywhere between them, which
55
+ * is what `straight` is chosen for. It is the curve for a quantity that changes
56
+ * at a moment rather than across an interval, a headcount or a price, where a
57
+ * sloped edge claims a gradual change nothing measured.
58
+ *
43
59
  * **`share` draws each reading as a hundred percent**, so the bands are the
44
60
  * parts' shares and the top edge is flat. It answers "which part grew" where
45
61
  * the default answers "did the whole grow".
@@ -56,9 +72,9 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
56
72
  * nothing, and a band that folded under its neighbor would say it was.
57
73
  *
58
74
  * @since 0.1.0
59
- * @status experimental
75
+ * @status stable
60
76
  * @category charts
61
- * @aliases Stacked Area Chart, Composition Chart, Stream Chart
77
+ * @aliases Stacked Area Chart, Composition Chart, Banded Chart
62
78
  * @documentation https://fusion.dev/helix/components/area-chart
63
79
  *
64
80
  * @csspart area - One part's band.
@@ -92,9 +108,13 @@ export declare class HelixHeadlessAreaChart extends HelixHeadlessAreaChart_base
92
108
  /**
93
109
  * How a band's edge gets from one reading to the next.
94
110
  *
95
- * Absent is `straight`, for the reason the class doc gives, and absent rather
96
- * than defaulted because a reflecting property with a default writes its
97
- * attribute onto every host, including the ones nobody configured.
111
+ * Three values, and the class doc argues for each: `straight` is absent and
112
+ * is the default, `smooth` is for a stack read as a shape and is the one that
113
+ * can draw a part as less than nothing, `step` is for a quantity that changes
114
+ * at a moment and is ordered the way `straight` is.
115
+ *
116
+ * Absent rather than defaulted because a reflecting property with a default
117
+ * writes its attribute onto every host, including the ones nobody configured.
98
118
  */
99
119
  curve?: Curve;
100
120
  /**
@@ -26,8 +26,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
26
26
  }
27
27
  get stack() {
28
28
  const rows = this.sourceRows;
29
- const width = Math.max(0, ...rows.map((row) => row.cells.length));
30
- const columns = Array.from({ length: width }, (_, column) => column).filter((column) => rows.some((row) => row.cells[column]?.value !== undefined));
29
+ const columns = this.plottedColumns;
31
30
  const values = columns.map((column) => rows.map((row) => {
32
31
  const value = row.cells[column]?.value ?? 0;
33
32
  if (value < 0) {
@@ -185,7 +184,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
185
184
  placement: 'top',
186
185
  x: `${at * slot + slot / 2}%`,
187
186
  y: `${y(stack.layers.at(-1)?.[at] ?? 0)}%`,
188
- });
187
+ }, (cell) => this.seriesOf(cell));
189
188
  }
190
189
  };
191
190
  __decorate([
@@ -28,7 +28,7 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
28
28
  * computed and CSS cannot.
29
29
  *
30
30
  * @since 0.1.0
31
- * @status experimental
31
+ * @status stable
32
32
  * @category charts
33
33
  * @aliases Column Chart, Categorical Chart
34
34
  * @documentation https://fusion.dev/helix/components/bar-chart
@@ -65,7 +65,7 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
65
65
  * @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
66
66
  * @csspart tooltip-value - A column's value inside the tooltip.
67
67
  *
68
- * @cssproperty --bar-chart-axis - The color of a single-series axis, taken from that series.
68
+ * @cssproperty --bar-chart-axis - How wide an axis column is drawn, in `ch`, from the widest number on it. Written on the axis itself, and only where the categories run along the bottom: turned sideways an axis is a row and takes a line's height instead.
69
69
  * @cssproperty --bar-chart-secondary - The color of the secondary axis when one series owns it. It resolves a `--helix-color-series-*` token, so on the headless tier alone it names something that is not there. #138.
70
70
  * @cssproperty --chart-bar-wash - The gradient a bar would take, named per bar so the
71
71
  * styled tier can point `fill` at it. Drawn whatever the treatment and used only where
@@ -105,30 +105,40 @@ export declare class HelixHeadlessBarChart extends HelixHeadlessBarChart_base {
105
105
  /**
106
106
  * Which series are drawn as a line instead of as columns, by name.
107
107
  *
108
- * Space separated, matched against the column headings the table gives, so a
109
- * chart says `lines="Margin"` rather than counting columns. Names because
110
- * they are what the table already carries and what the legend already shows:
111
- * an index is a fourth place the column order is written down and the first
112
- * one to go stale when somebody moves a column.
108
+ * Separated by whitespace or commas and matched against the column headings
109
+ * the table gives, so a chart says `lines="Margin"` rather than counting
110
+ * columns. Names because they are what the table already carries and what the
111
+ * legend already shows: an index is a fourth place the column order is
112
+ * written down and the first one to go stale when somebody moves a column.
113
113
  *
114
- * **A combination chart is one scale, and that is the honest half of it.**
115
- * Both marks are measured against the same domain, so a line here says
116
- * something comparable to the columns beside it. The usual reason to reach
117
- * for a combination chart is the other thing, a count against a percentage on
118
- * a second axis, and that is deliberately not this: two scales on one frame
119
- * let the author put any two shapes in any relation by choosing the ranges,
120
- * and the reader has no way to see it happening.
114
+ * **This says which mark a series takes and nothing about which scale it is
115
+ * measured on.** Named here alone, a line shares the columns' domain, so it
116
+ * says something comparable to the columns beside it.
121
117
  *
122
- * A line among columns still measures from zero, because the columns do and
123
- * they share the axis.
118
+ * The other half of a combination chart, a count against a percentage on a
119
+ * scale of its own, is `secondary`, which is a separate property because it
120
+ * is a separate question and because the two compose: `with-a-second-axis`
121
+ * ships naming one series in both. The argument for why a second scale is opt
122
+ * in, and why setting it labels both axes, is written there.
123
+ *
124
+ * A line among columns measures from zero, because the columns do and they
125
+ * share the axis. So does a line on the second scale, which is that scale's
126
+ * own rule rather than this one's.
124
127
  */
125
128
  lines?: string;
126
129
  /**
127
130
  * Which series are measured against a scale of their own, by name.
128
131
  *
129
- * Space separated and matched the way `lines` is, against the column headings
130
- * the table gives. Opt in: absent, every series shares one domain, which is
131
- * what makes a chart comparable and is the right default.
132
+ * Separated and matched the way `lines` is, against the column headings the
133
+ * table gives. Opt in: absent, every series shares one domain, which is what
134
+ * makes a chart comparable and is the right default.
135
+ *
136
+ * **The scale, and `lines` is the mark.** The two are separate properties
137
+ * because they answer separate questions and a series usually wants both:
138
+ * a percentage beside a count is drawn as a line *and* measured on its own
139
+ * axis, which is what `with-a-second-axis` writes out. Neither implies the
140
+ * other, so a series can be a line on the shared scale and a column can have
141
+ * a scale to itself.
132
142
  *
133
143
  * **Two scales on one frame let an author put any two shapes in any relation
134
144
  * by choosing the ranges, and a reader cannot see it happening.** That is not
@@ -4,23 +4,17 @@ 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 { CHART_PLOT, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, seriesIndex, ticks, } from '@fusion.dev/helix-core';
7
+ import { CHART_PLOT, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, seriesIndex, seriesNames, ticks, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing, svg } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import '../../tooltip/index.js';
11
11
  const HEIGHT = 100;
12
12
  let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource(HelixElement) {
13
13
  get scaled() {
14
- return new Set((this.secondary ?? '')
15
- .split(/\s+/)
16
- .map((name) => name.trim().toLowerCase())
17
- .filter(Boolean));
14
+ return new Set(seriesNames(this.secondary));
18
15
  }
19
16
  get lined() {
20
- return new Set((this.lines ?? '')
21
- .split(/\s+/)
22
- .map((name) => name.trim().toLowerCase())
23
- .filter(Boolean));
17
+ return new Set(seriesNames(this.lines));
24
18
  }
25
19
  get rulesValue() {
26
20
  return this.gridlines !== undefined && this.gridlines !== 'category';
@@ -223,7 +217,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
223
217
  placement: sideways ? (this.pointer.mirrored ? 'left' : 'right') : 'top',
224
218
  x: sideways ? `${far}%` : `${across}%`,
225
219
  y: sideways ? `${across}%` : `${far}%`,
226
- });
220
+ }, (cell) => this.seriesOf(cell));
227
221
  }
228
222
  };
229
223
  __decorate([
@@ -17,7 +17,7 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
17
17
  * dropped. Those rows are skipped and the total is of what is left.
18
18
  *
19
19
  * @since 0.1.0
20
- * @status experimental
20
+ * @status stable
21
21
  * @category charts
22
22
  * @aliases Pie Chart, Ring Chart, Share Chart
23
23
  * @documentation https://fusion.dev/helix/components/donut-chart
@@ -84,6 +84,14 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
84
84
  * `getComputedStyle`, which is client-only: a server would draw a different
85
85
  * ring than the client. A plot's proportions are markup for the same reason
86
86
  * `curve` is.
87
+ *
88
+ * **And so it does not reflect**, which is the same argument read forward. No
89
+ * selector on either tier asks about it and none can want to: everything the
90
+ * thickness decides is arithmetic done here and published as
91
+ * `--donut-chart-stroke`, which is a number a rule can do sums with where the
92
+ * word is not. Reflected, it wrote a value onto every host a script had set
93
+ * it on for nothing to read. `sweep` beside it is the converse and reflects,
94
+ * because three rules select on it.
87
95
  */
88
96
  hole?: 'large' | 'none' | 'small';
89
97
  /**
@@ -165,11 +165,11 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
165
165
  : 'top',
166
166
  x: `${x}%`,
167
167
  y: `${y}%`,
168
- });
168
+ }, () => seriesIndex(at));
169
169
  }
170
170
  };
171
171
  __decorate([
172
- property({ reflect: true })
172
+ property()
173
173
  ], HelixHeadlessDonutChart.prototype, "hole", void 0);
174
174
  __decorate([
175
175
  property({ reflect: true })
@@ -11,7 +11,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
11
11
  * `entries` picks which way to read that table. `series` is one entry per data
12
12
  * column, named by the header row, which is a line or a bar chart.
13
13
  * `categories` is one entry per body row, which is a donut: its slices are the
14
- * rows and it has no axis to write their names along.
14
+ * rows and it has no axis to write their names along. `measures` drops the
15
+ * first data column, which is a scatter.
15
16
  *
16
17
  * **The table is resolved on the client and there is no server pass.**
17
18
  *
@@ -32,8 +33,21 @@ export declare class HelixHeadlessLegend extends HelixElement {
32
33
  *
33
34
  * Absent is `series`, one entry per data column. `categories` reads one entry
34
35
  * per body row instead, for a donut, whose slices are the rows.
36
+ *
37
+ * **`measures` is `series` without the first column, and it is for a
38
+ * scatter.** That chart reads its first numeric column as the measure
39
+ * *across*, so its first plotted series is the table's second and everything
40
+ * a legend beside it named was one color out: the across column wearing the
41
+ * color of the first series drawn, and each real series wearing the next
42
+ * one's. The across gets no entry rather than a shifted one, because it is an
43
+ * axis and a scatter already writes its name at the end of the scale under
44
+ * the plot.
45
+ *
46
+ * A legend cannot ask the chart which of these it is, `for` naming the table
47
+ * they share and not each other, so the consumer says it. That is the same
48
+ * shape `categories` already has.
35
49
  */
36
- entries?: 'categories' | 'series';
50
+ entries?: 'categories' | 'measures' | 'series';
37
51
  /**
38
52
  * The id of the table to take the names from.
39
53
  *
@@ -20,9 +20,10 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
20
20
  }
21
21
  names() {
22
22
  const series = this.source.series;
23
- return this.entries === 'categories'
24
- ? (series[0]?.points.map((point) => point.label) ?? [])
25
- : series.map((one) => one.name);
23
+ if (this.entries === 'categories') {
24
+ return series[0]?.points.map((point) => point.label) ?? [];
25
+ }
26
+ return (this.entries === 'measures' ? series.slice(1) : series).map((one) => one.name);
26
27
  }
27
28
  render() {
28
29
  return html `<ul part="list" role="list">
@@ -36,7 +36,7 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
36
36
  * A reader who wants the numbers gets the numbers, not a described picture.
37
37
  *
38
38
  * @since 0.1.0
39
- * @status experimental
39
+ * @status stable
40
40
  * @category charts
41
41
  * @aliases Time Series, Trend Chart, Multi-line Chart
42
42
  * @documentation https://fusion.dev/helix/components/line-chart
@@ -68,6 +68,9 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
68
68
  * @csspart tooltip-right - The bubble while it is right of the reading, beside `tooltip`.
69
69
  * @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
70
70
  * @csspart tooltip-value - A column's value inside the tooltip.
71
+ *
72
+ * @cssproperty --chart-terminus-x - Where a series' last reading sits horizontally, as a percentage. Written by the component.
73
+ * @cssproperty --chart-terminus-y - Where a series' last reading sits vertically, as a percentage. Written by the component.
71
74
  */
72
75
  export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base {
73
76
  /**
@@ -141,9 +144,20 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
141
144
  * the question a sparkline's single mark answers too.
142
145
  *
143
146
  * `none` lets the lines stop on their own, which suits a chart read for its
144
- * shape rather than for where it finished. The shapes come from
147
+ * shape rather than for where it finished. `square` is the same mark with its
148
+ * corners, for a drawing whose neighbors are square, the columns of a table
149
+ * beside it for instance. `ring` lets the ground through, for a chart drawn
150
+ * over something busy. `triangle` points along the axis and reads as "and
151
+ * onward" rather than as a second claim about the data.
152
+ *
153
+ * The shapes come from
145
154
  * `helix/styled/src/shared/chart/terminus.css`, the same sheet `Sparkline` takes, so
146
- * the set is identical wherever one appears.
155
+ * the set is identical wherever one appears. **Which is why every value is
156
+ * named here.** `Sparkline` shipped `square` implemented, drawn, asserted and
157
+ * undocumented until the cohort before this one; this family reads the same
158
+ * four out of the same sheet and had left two of them unwritten, so the
159
+ * finding arrived twice. A shared vocabulary wants naming at each door into
160
+ * it, because a reader arrives at one door and not at the set.
147
161
  *
148
162
  * `ring` is the one that asks something of the drawing. It leaves a hole and a
149
163
  * line ends at the reading, which is the hole's center, so the `<svg>` is
@@ -170,7 +170,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
170
170
  placement: 'top',
171
171
  x: `${at * slot + slot / 2}%`,
172
172
  y: `${tops.length > 0 ? Math.min(...tops) : 0}%`,
173
- });
173
+ }, (cell) => this.seriesOf(cell));
174
174
  }
175
175
  };
176
176
  __decorate([
@@ -21,7 +21,7 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
21
21
  * upgrades is a hydration mismatch waiting to happen.
22
22
  *
23
23
  * @since 0.1.0
24
- * @status experimental
24
+ * @status stable
25
25
  * @aliases Menu option, Menu row
26
26
  * @documentation https://fusion.dev/helix/components/menu
27
27
  *
@@ -23,7 +23,7 @@ declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.d
23
23
  * upgrades is a hydration mismatch waiting to happen.
24
24
  *
25
25
  * @since 0.1.0
26
- * @status experimental
26
+ * @status stable
27
27
  * @category overlays
28
28
  * @aliases Dropdown, Action menu
29
29
  * @documentation https://fusion.dev/helix/components/menu
@@ -21,7 +21,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
21
21
  * marker in the right place.
22
22
  *
23
23
  * @since 0.1.0
24
- * @status experimental
24
+ * @status stable
25
25
  * @category navigation
26
26
  * @aliases Nav, NavList, Tabs
27
27
  * @documentation https://fusion.dev/helix/components/navigation
@@ -34,7 +34,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
34
34
  * slot can only offer one place: at one end of one row, in one order.
35
35
  *
36
36
  * @since 0.1.0
37
- * @status experimental
37
+ * @status stable
38
38
  * @category navigation
39
39
  * @aliases Pager, Page nav
40
40
  * @documentation https://fusion.dev/helix/components/pagination
@@ -33,7 +33,7 @@ import '../../select/index.js';
33
33
  * position should survive it.
34
34
  *
35
35
  * @since 0.1.0
36
- * @status experimental
36
+ * @status stable
37
37
  * @aliases Page size, Rows per page
38
38
  * @documentation https://fusion.dev/helix/components/pagination
39
39
  *
@@ -19,7 +19,7 @@ import { type TemplateResult } from 'lit';
19
19
  * does not call it.
20
20
  *
21
21
  * @since 0.1.0
22
- * @status experimental
22
+ * @status stable
23
23
  * @aliases Result count, Range
24
24
  * @documentation https://fusion.dev/helix/components/pagination
25
25
  */
@@ -58,7 +58,7 @@ declare const HelixHeadlessScatterChart_base: typeof HelixElement & (new (...arg
58
58
  * and the bubble is told the page's direction, both being words.
59
59
  *
60
60
  * @since 0.1.0
61
- * @status experimental
61
+ * @status stable
62
62
  * @category charts
63
63
  * @aliases Scatter Plot, XY Chart, Correlation Chart, Dot Plot
64
64
  * @documentation https://fusion.dev/helix/components/scatter-chart
@@ -121,6 +121,22 @@ export declare class HelixHeadlessScatterChart extends HelixHeadlessScatterChart
121
121
  private nearest;
122
122
  connectedCallback(): void;
123
123
  disconnectedCallback(): void;
124
+ /**
125
+ * The palette slot a cell of a row is drawn in, which here is shifted by one.
126
+ *
127
+ * **A scatter's first plotted series is the table's *second* numeric
128
+ * column**, the first having been split off as the measure across. So the
129
+ * mixin's answer, which is right for a chart whose columns are its series in
130
+ * order, is one too high on every column here and names a color for the
131
+ * across, which is drawn in none. Left at that, the bubble painted the across
132
+ * column in series one, the color the points themselves are drawn in, and
133
+ * gave the series actually plotted series two.
134
+ *
135
+ * The across gets no dot at all rather than a shifted one. It is an axis and
136
+ * not a series: it has a scale under the plot with its name at the end of it,
137
+ * which is where a reader is told what it is.
138
+ */
139
+ seriesOf(cell: number): number | undefined;
124
140
  /** Whether the levels across are ruled. */
125
141
  protected get rulesX(): boolean;
126
142
  /** Whether the levels up are ruled. */
@@ -89,6 +89,10 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
89
89
  this.removeEventListener('pointermove', this.handleMove);
90
90
  this.removeEventListener('pointerleave', this.handleLeave);
91
91
  }
92
+ seriesOf(cell) {
93
+ const depth = this.plottedColumns.indexOf(cell);
94
+ return depth < 1 ? undefined : seriesIndex(depth - 1);
95
+ }
92
96
  get rulesX() {
93
97
  return this.gridlines !== undefined && this.gridlines !== 'y';
94
98
  }
@@ -97,8 +101,7 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
97
101
  }
98
102
  get field() {
99
103
  const rows = this.sourceRows;
100
- const width = Math.max(0, ...rows.map((row) => row.cells.length));
101
- const columns = Array.from({ length: width }, (_, column) => column).filter((column) => rows.some((row) => row.cells[column]?.value !== undefined));
104
+ const columns = this.plottedColumns;
102
105
  const [across, ...ups] = columns;
103
106
  const name = (column) => column === undefined ? '' : (rows.find((row) => row.cells[column])?.cells[column]?.name ?? '');
104
107
  const pairs = ups.map((column) => rows.flatMap((row, index) => {
@@ -193,7 +196,7 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
193
196
  placement: 'top',
194
197
  x: `${point.x}%`,
195
198
  y: `${point.y}%`,
196
- });
199
+ }, (cell) => this.seriesOf(cell));
197
200
  }
198
201
  };
199
202
  __decorate([
@@ -17,7 +17,7 @@ declare const HelixHeadlessSteps_base: (new (...args: any[]) => import("@fusion.
17
17
  * count.
18
18
  *
19
19
  * @since 0.1.0
20
- * @status experimental
20
+ * @status stable
21
21
  * @category navigation
22
22
  * @aliases Stepper, Wizard, Progress steps
23
23
  * @documentation https://fusion.dev/helix/components/steps
@@ -22,12 +22,12 @@ import '../../button/index.js';
22
22
  * that are not there.
23
23
  *
24
24
  * @since 0.1.0
25
- * @status experimental
25
+ * @status stable
26
26
  * @aliases Stage
27
27
  * @documentation https://fusion.dev/helix/components/steps
28
28
  *
29
29
  * @slot - The step's name.
30
- * @slot content - What the stage holds, shown while it is the current one.
30
+ * @slot content - What the stage holds. Always rendered here, a tier with no stylesheet having nothing to fold it with; the styled tier opens it on the current step down a column, and a row has no space under a step to open it into.
31
31
  * @slot description - A line under the name, for what the stage is for.
32
32
  * @slot marker - Replaces the number, or the check a complete step shows.
33
33
  *
@@ -21,8 +21,8 @@ declare const HelixHeadlessTabs_base: (new (...args: any[]) => import("@fusion.d
21
21
  * @aliases TabList, Segmented control
22
22
  * @documentation https://fusion.dev/helix/components/tabs
23
23
  *
24
- * @slot - The tabs.
25
- * @slot panels - The panels.
24
+ * @slot - The tabs, which are this element's own children.
25
+ * @slot panels - The panels, which are this element's own children. A wrapper around them is assigned to the slot and pairs with nothing, since the pairing walks these children rather than the slot's tree.
26
26
  *
27
27
  * @event {HelixActivateEvent} helix-activate - Fired once the current one has moved, so the element already holds it.
28
28
  * @event {HelixBeforeActivateEvent} helix-before-activate - Fired before the current tab moves, and cancelable. The only way to refuse one.
@@ -41,7 +41,8 @@ let HelixHeadlessTabs = class HelixHeadlessTabs extends MixinControllerActive(He
41
41
  }
42
42
  sync() {
43
43
  const tabs = this.tabs;
44
- const value = this.resolveActive(tabs)?.value ?? '';
44
+ const declared = this.active === '' ? tabs.find((tab) => tab.selected) : undefined;
45
+ const value = (declared ?? this.resolveActive(tabs))?.value ?? '';
45
46
  for (const tab of tabs) {
46
47
  tab.selected = tab.value === value;
47
48
  }
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.39.0",
4
+ "version": "0.41.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.39.0",
50
- "@fusion.dev/helix-icons": "0.39.0",
49
+ "@fusion.dev/helix-core": "0.41.0",
50
+ "@fusion.dev/helix-icons": "0.41.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.39.0",
56
- "@fusion.dev/helix-testing": "0.39.0",
55
+ "@fusion.dev/helix-cem": "0.41.0",
56
+ "@fusion.dev/helix-testing": "0.41.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",