@fusion.dev/helix-headless 0.52.1 → 0.53.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.
- package/custom-elements.json +691 -273
- package/dist/announcement/root/announcement-root.js +2 -5
- package/dist/area-chart/root/area-chart-root.js +10 -12
- package/dist/bar-chart/root/bar-chart-root.js +4 -5
- package/dist/blockquote/root/blockquote-root.js +2 -5
- package/dist/chat/composer/chat-composer.js +2 -5
- package/dist/chat/message/chat-message.js +4 -11
- package/dist/chat/root/chat-root.js +1 -1
- package/dist/checkbox/root/checkbox-root.js +1 -1
- package/dist/checkbox-group/root/checkbox-group-root.js +1 -1
- package/dist/color-input/root/color-input-root.js +1 -1
- package/dist/combobox/root/combobox-root.d.ts +16 -0
- package/dist/combobox/root/combobox-root.js +5 -2
- package/dist/data-table/root/data-table-root.d.ts +23 -10
- package/dist/data-table/root/data-table-root.js +12 -13
- package/dist/date-input/root/date-input-root.js +1 -1
- package/dist/divider/root/divider-root.js +2 -5
- package/dist/donut-chart/root/donut-chart-root.js +5 -6
- package/dist/drilldown/item/drilldown-item.d.ts +18 -0
- package/dist/drilldown/item/drilldown-item.js +3 -0
- package/dist/drilldown/root/drilldown-root.d.ts +20 -1
- package/dist/drilldown/root/drilldown-root.js +6 -13
- package/dist/file-input/root/file-input-root.js +2 -2
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/heatmap/root/buckets.d.ts +2 -2
- package/dist/heatmap/root/buckets.js +3 -4
- package/dist/heatmap/root/heatmap-root.d.ts +0 -10
- package/dist/heatmap/root/heatmap-root.js +2 -8
- package/dist/input/root/input-root.js +1 -1
- package/dist/line-chart/root/line-chart-root.js +15 -17
- package/dist/listbox/root/listbox-root.js +1 -1
- package/dist/menu/item/menu-item.js +2 -2
- package/dist/notifications/notification/notification.d.ts +3 -9
- package/dist/notifications/notification/notification.js +3 -11
- package/dist/notifications/root/notifications-root.d.ts +0 -10
- package/dist/notifications/root/notifications-root.js +3 -9
- package/dist/number-input/root/number-input-root.js +2 -2
- package/dist/radio/root/radio-root.d.ts +10 -32
- package/dist/radio/root/radio-root.js +6 -27
- package/dist/scatter-chart/root/scatter-chart-root.js +10 -11
- package/dist/select/root/select-root.d.ts +24 -0
- package/dist/select/root/select-root.js +5 -2
- package/dist/slider/root/slider-root.js +1 -1
- package/dist/sparkline/root/sparkline-root.js +10 -12
- package/dist/switch/root/switch-root.js +3 -6
- package/dist/tabs/root/tabs-root.js +11 -4
- package/dist/tabs/tab/tab.d.ts +11 -30
- package/dist/tabs/tab/tab.js +7 -28
- package/dist/textarea/root/textarea-root.js +1 -1
- package/dist/time-input/root/time-input-root.js +1 -1
- package/dist/toggle/root/toggle-root.d.ts +10 -36
- package/dist/toggle/root/toggle-root.js +6 -27
- package/dist/tree/item/tree-item.js +6 -5
- package/dist/tree/root/tree-root.js +8 -4
- package/dist/video/root/video-root.js +7 -14
- package/package.json +5 -5
- package/types/jsx.d.ts +192 -74
- package/types/vue.d.ts +36 -16
|
@@ -29,9 +29,9 @@ export interface Reading {
|
|
|
29
29
|
* painting it as the lowest bucket claims a reading that does not exist.
|
|
30
30
|
*/
|
|
31
31
|
export declare const toneOf: (reading: Reading, thresholds: readonly number[], tones: readonly string[]) => string | undefined;
|
|
32
|
-
/** A
|
|
32
|
+
/** A consumer's list of numbers, in the order written, with the rest dropped. */
|
|
33
33
|
export declare const numbers: (source: string) => number[];
|
|
34
|
-
/** A
|
|
34
|
+
/** A consumer's list of names, in the order written. */
|
|
35
35
|
export declare const words: (source: string) => string[];
|
|
36
36
|
/**
|
|
37
37
|
* How many readings fit across a given width, and which ones they are.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { writtenList } from '@fusion.dev/helix-core';
|
|
1
2
|
export const toneOf = (reading, thresholds, tones) => {
|
|
2
3
|
if (reading.tone) {
|
|
3
4
|
return reading.tone;
|
|
@@ -13,12 +14,10 @@ export const toneOf = (reading, thresholds, tones) => {
|
|
|
13
14
|
}
|
|
14
15
|
return chosen;
|
|
15
16
|
};
|
|
16
|
-
export const numbers = (source) => source
|
|
17
|
-
.split(/[\s,]+/)
|
|
18
|
-
.filter((one) => one !== '')
|
|
17
|
+
export const numbers = (source) => writtenList(source)
|
|
19
18
|
.map(Number)
|
|
20
19
|
.filter((one) => Number.isFinite(one));
|
|
21
|
-
export const words = (source) => source
|
|
20
|
+
export const words = (source) => writtenList(source);
|
|
22
21
|
export const fits = (total, width, minimum, gap, rows = 1) => {
|
|
23
22
|
if (!Number.isFinite(width) || width <= 0 || minimum <= 0) {
|
|
24
23
|
return total;
|
|
@@ -277,16 +277,6 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
277
277
|
* than the fill, and is false either way. Both verified in a browser.
|
|
278
278
|
*/
|
|
279
279
|
private markEmpty;
|
|
280
|
-
/**
|
|
281
|
-
* One region, hidden when its slot holds nothing and nothing of ours fills it.
|
|
282
|
-
*
|
|
283
|
-
* `hidden` beside the `data-empty` mirror: `data-empty` is the hook the styled
|
|
284
|
-
* sheet reads, and this tier ships no sheet, so an empty region left in the box
|
|
285
|
-
* tree would be a gap a headless consumer cannot close without knowing to look
|
|
286
|
-
* for it. The styled rule stays too, because that sheet sets `display` on these
|
|
287
|
-
* parts and therefore outranks the UA's `[hidden]` one.
|
|
288
|
-
*/
|
|
289
|
-
private markRegion;
|
|
290
280
|
protected updated(changed: PropertyValues): void;
|
|
291
281
|
protected render(): TemplateResult;
|
|
292
282
|
/**
|
|
@@ -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 { CHART_PLOT, customElement, drawTooltip, HelixElement, HelixResizeEvent, hostAria, MixinChartSource,
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, HelixElement, HelixResizeEvent, hostAria, MixinChartSource, markRegion, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import '../../tooltip/index.js';
|
|
@@ -102,13 +102,7 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
|
|
|
102
102
|
hostAria(this.internals, { label: this.label || 'Heatmap', role: 'img' });
|
|
103
103
|
}
|
|
104
104
|
markEmpty() {
|
|
105
|
-
this.
|
|
106
|
-
}
|
|
107
|
-
markRegion(part, slots, occupied) {
|
|
108
|
-
const region = this.renderRoot?.querySelector(`[part="${part}"]`);
|
|
109
|
-
const empty = !slots.some((name) => slotFilled(this.renderRoot?.querySelector(`slot[name="${name}"]`))) && !(occupied && this.renderRoot?.querySelector(occupied));
|
|
110
|
-
region?.toggleAttribute('data-empty', empty);
|
|
111
|
-
region?.toggleAttribute('hidden', empty);
|
|
105
|
+
markRegion(this.renderRoot, 'footer', ['start', 'summary', 'end']);
|
|
112
106
|
}
|
|
113
107
|
updated(changed) {
|
|
114
108
|
super.updated(changed);
|
|
@@ -125,7 +125,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
|
|
|
125
125
|
<slot name="start"></slot>
|
|
126
126
|
<input
|
|
127
127
|
part="control"
|
|
128
|
-
id
|
|
128
|
+
id=${this.controlId}
|
|
129
129
|
.value=${this.value}
|
|
130
130
|
type=${this.effectiveType}
|
|
131
131
|
name=${this.name || nothing}
|
|
@@ -4,12 +4,10 @@ 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, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, 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
|
-
const WIDTH = 100;
|
|
12
|
-
const HEIGHT = 100;
|
|
13
11
|
let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSource(HelixElement) {
|
|
14
12
|
constructor() {
|
|
15
13
|
super(...arguments);
|
|
@@ -36,8 +34,8 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
36
34
|
return [
|
|
37
35
|
{
|
|
38
36
|
index: seriesIndex(depth),
|
|
39
|
-
x: (x(one.points.length - 1) /
|
|
40
|
-
y: (y(last.value) /
|
|
37
|
+
x: (x(one.points.length - 1) / PLOT_WIDTH) * 100,
|
|
38
|
+
y: (y(last.value) / PLOT_HEIGHT) * 100,
|
|
41
39
|
},
|
|
42
40
|
];
|
|
43
41
|
});
|
|
@@ -49,9 +47,9 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
49
47
|
return html `<div id=${CHART_PLOT} part="plot"></div>`;
|
|
50
48
|
}
|
|
51
49
|
const domain = this.range(series);
|
|
52
|
-
const y = linear(domain, [
|
|
53
|
-
const slot =
|
|
54
|
-
const x = linear([0, Math.max(readings.length - 1, 1)], [slot / 2,
|
|
50
|
+
const y = linear(domain, [PLOT_HEIGHT, 0]);
|
|
51
|
+
const slot = PLOT_WIDTH / readings.length;
|
|
52
|
+
const x = linear([0, Math.max(readings.length - 1, 1)], [slot / 2, PLOT_WIDTH - slot / 2]);
|
|
55
53
|
return html `${this.renderPlot(series, x, y, domain)} ${this.renderLabels(readings)}`;
|
|
56
54
|
}
|
|
57
55
|
renderPlot(series, x, y, domain) {
|
|
@@ -71,13 +69,13 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
71
69
|
<svg part="svg"
|
|
72
70
|
data-mirror
|
|
73
71
|
preserveAspectRatio="none"
|
|
74
|
-
viewBox="0 0 ${
|
|
72
|
+
viewBox="0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}"
|
|
75
73
|
xmlns="http://www.w3.org/2000/svg"
|
|
76
74
|
>
|
|
77
75
|
${this.renderGridlines(x, y, domain, series[0]?.points.length ?? 0)}
|
|
78
76
|
${floor === undefined
|
|
79
77
|
? nothing
|
|
80
|
-
: svg `<line part="baseline" x1="0" x2=${
|
|
78
|
+
: svg `<line part="baseline" x1="0" x2=${PLOT_WIDTH} y1=${floor} y2=${floor} />`}
|
|
81
79
|
${this.renderBand(series[0]?.points.length ?? 0)}
|
|
82
80
|
${this.renderGuide(x)}
|
|
83
81
|
${series.map((one, depth) => this.renderSeries(one, depth, x, y))}
|
|
@@ -91,10 +89,10 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
91
89
|
return nothing;
|
|
92
90
|
}
|
|
93
91
|
const down = this.rulesCategory
|
|
94
|
-
? Array.from({ length: count }, (_, index) => svg `<line part="gridline" x1=${x(index)} x2=${x(index)} y1="0" y2=${
|
|
92
|
+
? Array.from({ length: count }, (_, index) => svg `<line part="gridline" x1=${x(index)} x2=${x(index)} y1="0" y2=${PLOT_HEIGHT} />`)
|
|
95
93
|
: [];
|
|
96
94
|
const across = this.rulesValue
|
|
97
|
-
? ticks(domain).map((level) => svg `<line part="gridline" x1="0" x2=${
|
|
95
|
+
? ticks(domain).map((level) => svg `<line part="gridline" x1="0" x2=${PLOT_WIDTH} y1=${y(level)} y2=${y(level)} />`)
|
|
98
96
|
: [];
|
|
99
97
|
return svg `${down}${across}`;
|
|
100
98
|
}
|
|
@@ -103,15 +101,15 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
103
101
|
if (at < 0 || count === 0) {
|
|
104
102
|
return nothing;
|
|
105
103
|
}
|
|
106
|
-
const slot =
|
|
107
|
-
return svg `<rect height=${
|
|
104
|
+
const slot = PLOT_WIDTH / count;
|
|
105
|
+
return svg `<rect height=${PLOT_HEIGHT} part="band" width=${slot} x=${at * slot} y="0" />`;
|
|
108
106
|
}
|
|
109
107
|
renderGuide(x) {
|
|
110
108
|
const at = this.pointer.at;
|
|
111
109
|
if (at < 0) {
|
|
112
110
|
return nothing;
|
|
113
111
|
}
|
|
114
|
-
return svg `<line part="guide" x1=${x(at)} x2=${x(at)} y1="0" y2=${
|
|
112
|
+
return svg `<line part="guide" x1=${x(at)} x2=${x(at)} y1="0" y2=${PLOT_HEIGHT} />`;
|
|
115
113
|
}
|
|
116
114
|
renderTermini(ends) {
|
|
117
115
|
if (ends.length === 0) {
|
|
@@ -132,7 +130,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
132
130
|
const index = seriesIndex(depth);
|
|
133
131
|
const first = points[0];
|
|
134
132
|
const last = points.at(-1);
|
|
135
|
-
const wash = `${path}L${last[0]},${
|
|
133
|
+
const wash = `${path}L${last[0]},${PLOT_HEIGHT}L${first[0]},${PLOT_HEIGHT}Z`;
|
|
136
134
|
return svg `${this.area
|
|
137
135
|
? svg `<path
|
|
138
136
|
d=${wash}
|
|
@@ -160,7 +158,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
160
158
|
return drawTooltip(this.sourceRows, at, this.tag('tooltip'));
|
|
161
159
|
}
|
|
162
160
|
const domain = this.range(series);
|
|
163
|
-
const scale = linear(domain, [
|
|
161
|
+
const scale = linear(domain, [PLOT_HEIGHT, 0]);
|
|
164
162
|
const tops = series
|
|
165
163
|
.map((one) => one.points[at]?.value)
|
|
166
164
|
.filter((one) => one !== undefined)
|
|
@@ -305,7 +305,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
305
305
|
super.willUpdate(changed);
|
|
306
306
|
hostAria(this.internals, { label: this.label, role: 'listbox' });
|
|
307
307
|
this.internals.ariaMultiSelectable = this.multiple ? 'true' : null;
|
|
308
|
-
if (this.
|
|
308
|
+
if (this.childrenKnown) {
|
|
309
309
|
this.place();
|
|
310
310
|
}
|
|
311
311
|
}
|
|
@@ -58,10 +58,10 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
58
58
|
}
|
|
59
59
|
willUpdate(changed) {
|
|
60
60
|
super.willUpdate(changed);
|
|
61
|
-
if (this.
|
|
61
|
+
if (!this.childrenKnown) {
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
|
-
const named = (name) =>
|
|
64
|
+
const named = (name) => this.knownChildren.some((child) => child.slot === name);
|
|
65
65
|
this.submenu = named('submenu');
|
|
66
66
|
this.start = named('start');
|
|
67
67
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import '../../format-date/index.js';
|
|
4
|
+
declare const HelixHeadlessNotification_base: (new (...args: any[]) => import("@fusion.dev/helix-core").DismissibleElement) & typeof HelixElement;
|
|
4
5
|
/**
|
|
5
6
|
* @summary One thing that happened, which a reader may not have seen yet.
|
|
6
7
|
*
|
|
@@ -66,7 +67,7 @@ import '../../format-date/index.js';
|
|
|
66
67
|
* @cssstate controls - While it can be dismissed, so the time makes way for the control under a pointer.
|
|
67
68
|
* @cssstate read - While it has been read.
|
|
68
69
|
*/
|
|
69
|
-
export declare class HelixHeadlessNotification extends
|
|
70
|
+
export declare class HelixHeadlessNotification extends HelixHeadlessNotification_base {
|
|
70
71
|
/**
|
|
71
72
|
* When it happened, as anything `Date` parses.
|
|
72
73
|
*
|
|
@@ -97,14 +98,6 @@ export declare class HelixHeadlessNotification extends HelixElement {
|
|
|
97
98
|
* State to open with, where nothing declared one.
|
|
98
99
|
*/
|
|
99
100
|
defaultRead: boolean;
|
|
100
|
-
/**
|
|
101
|
-
* Whether a reader may remove it.
|
|
102
|
-
*/
|
|
103
|
-
dismissible: boolean;
|
|
104
|
-
/**
|
|
105
|
-
* Accessible name for the dismiss control.
|
|
106
|
-
*/
|
|
107
|
-
dismissLabel: string;
|
|
108
101
|
/**
|
|
109
102
|
* Locale for the timestamp.
|
|
110
103
|
*
|
|
@@ -212,3 +205,4 @@ declare global {
|
|
|
212
205
|
'helix-headless-notification': HelixHeadlessNotification;
|
|
213
206
|
}
|
|
214
207
|
}
|
|
208
|
+
export {};
|
|
@@ -4,20 +4,18 @@ 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,
|
|
7
|
+
import { customElement, HelixElement, HelixReadEvent, hostAria, MixinDismissible, requestChange, slotFilled, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { x } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
import { html } from 'lit/static-html.js';
|
|
13
13
|
import '../../format-date/index.js';
|
|
14
|
-
let HelixHeadlessNotification = class HelixHeadlessNotification extends HelixElement {
|
|
14
|
+
let HelixHeadlessNotification = class HelixHeadlessNotification extends MixinDismissible(HelixElement) {
|
|
15
15
|
constructor() {
|
|
16
16
|
super(...arguments);
|
|
17
17
|
this.at = '';
|
|
18
18
|
this.defaultRead = false;
|
|
19
|
-
this.dismissible = false;
|
|
20
|
-
this.dismissLabel = 'Dismiss';
|
|
21
19
|
this.locale = '';
|
|
22
20
|
this.isNotification = true;
|
|
23
21
|
this.readState = undefined;
|
|
@@ -26,7 +24,7 @@ let HelixHeadlessNotification = class HelixHeadlessNotification extends HelixEle
|
|
|
26
24
|
};
|
|
27
25
|
this.handleDismiss = (event) => {
|
|
28
26
|
event.stopPropagation();
|
|
29
|
-
if (this.
|
|
27
|
+
if (this.dismiss()) {
|
|
30
28
|
this.remove();
|
|
31
29
|
}
|
|
32
30
|
};
|
|
@@ -128,12 +126,6 @@ __decorate([
|
|
|
128
126
|
__decorate([
|
|
129
127
|
property({ attribute: 'default-read', type: Boolean })
|
|
130
128
|
], HelixHeadlessNotification.prototype, "defaultRead", void 0);
|
|
131
|
-
__decorate([
|
|
132
|
-
property({ type: Boolean })
|
|
133
|
-
], HelixHeadlessNotification.prototype, "dismissible", void 0);
|
|
134
|
-
__decorate([
|
|
135
|
-
property({ attribute: 'dismiss-label' })
|
|
136
|
-
], HelixHeadlessNotification.prototype, "dismissLabel", void 0);
|
|
137
129
|
__decorate([
|
|
138
130
|
property()
|
|
139
131
|
], HelixHeadlessNotification.prototype, "locale", void 0);
|
|
@@ -201,16 +201,6 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
|
|
|
201
201
|
* which React reports on hydration and does not patch up.
|
|
202
202
|
*/
|
|
203
203
|
private markEmpty;
|
|
204
|
-
/**
|
|
205
|
-
* One region, hidden when its slot holds nothing and nothing of ours fills it.
|
|
206
|
-
*
|
|
207
|
-
* `hidden` beside the `data-empty` mirror: `data-empty` is the hook the styled
|
|
208
|
-
* sheet reads, and this tier ships no sheet, so an empty region left in the box
|
|
209
|
-
* tree would be a gap a headless consumer cannot close without knowing to look
|
|
210
|
-
* for it. The styled rule stays too, because that sheet sets `display` on these
|
|
211
|
-
* parts and therefore outranks the UA's `[hidden]` one.
|
|
212
|
-
*/
|
|
213
|
-
private markRegion;
|
|
214
204
|
protected updated(changed: PropertyValues): void;
|
|
215
205
|
protected render(): TemplateResult;
|
|
216
206
|
private readonly handleMarkAll;
|
|
@@ -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, HelixReadEvent, hostAria, MixinCollection,
|
|
7
|
+
import { customElement, HelixElement, HelixReadEvent, hostAria, MixinCollection, markRegion, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinCollection(HelixElement) {
|
|
@@ -107,14 +107,8 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
107
107
|
this.toggleState('media', this.items.some((item) => item.querySelector(':scope > [slot="media"]') !== null));
|
|
108
108
|
}
|
|
109
109
|
markEmpty() {
|
|
110
|
-
this.
|
|
111
|
-
this.
|
|
112
|
-
}
|
|
113
|
-
markRegion(part, slots, occupied) {
|
|
114
|
-
const region = this.renderRoot?.querySelector(`[part="${part}"]`);
|
|
115
|
-
const empty = !slots.some((name) => slotFilled(this.renderRoot?.querySelector(`slot[name="${name}"]`))) && !(occupied && this.renderRoot?.querySelector(occupied));
|
|
116
|
-
region?.toggleAttribute('data-empty', empty);
|
|
117
|
-
region?.toggleAttribute('hidden', empty);
|
|
110
|
+
markRegion(this.renderRoot, 'header', ['header'], { occupied: '[part="mark-all"]' });
|
|
111
|
+
markRegion(this.renderRoot, 'footer', ['footer']);
|
|
118
112
|
}
|
|
119
113
|
updated(changed) {
|
|
120
114
|
super.updated(changed);
|
|
@@ -177,7 +177,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
177
177
|
}
|
|
178
178
|
return html `<label
|
|
179
179
|
part="label"
|
|
180
|
-
for
|
|
180
|
+
for=${this.controlId}
|
|
181
181
|
?data-hidden=${hidden !== null}
|
|
182
182
|
@pointercancel=${this.handleScrubEnd}
|
|
183
183
|
@pointerdown=${this.handleScrubDown}
|
|
@@ -254,7 +254,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
254
254
|
${''}
|
|
255
255
|
<input
|
|
256
256
|
part="control"
|
|
257
|
-
id
|
|
257
|
+
id=${this.controlId}
|
|
258
258
|
.value=${this.value}
|
|
259
259
|
type="text"
|
|
260
260
|
role="spinbutton"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
declare const HelixHeadlessRadio_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinSelectableItemInterface) & typeof HelixElement;
|
|
3
4
|
/**
|
|
4
5
|
* @summary One choice in a radio group.
|
|
5
6
|
*
|
|
@@ -41,11 +42,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
41
42
|
*
|
|
42
43
|
* @cssstate selected - While it is the one chosen.
|
|
43
44
|
*/
|
|
44
|
-
export declare class HelixHeadlessRadio extends
|
|
45
|
-
/**
|
|
46
|
-
* Whether this choice can be made.
|
|
47
|
-
*/
|
|
48
|
-
disabled: boolean;
|
|
45
|
+
export declare class HelixHeadlessRadio extends HelixHeadlessRadio_base {
|
|
49
46
|
/**
|
|
50
47
|
* Whether the markup declared this one chosen, which is what a reset returns to.
|
|
51
48
|
*
|
|
@@ -93,35 +90,15 @@ export declare class HelixHeadlessRadio extends HelixElement {
|
|
|
93
90
|
*/
|
|
94
91
|
focusable: boolean;
|
|
95
92
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* Written by the group.
|
|
99
|
-
*/
|
|
100
|
-
selected: boolean;
|
|
101
|
-
/**
|
|
102
|
-
* Identifies this choice to the group, and is what the form submits.
|
|
103
|
-
*/
|
|
104
|
-
value: string;
|
|
105
|
-
/** Moves focus to this choice, for the group's arrow keys. */
|
|
106
|
-
focusItem(): void;
|
|
107
|
-
/** Makes this choice and announces it. */
|
|
108
|
-
select(): void;
|
|
109
|
-
/**
|
|
110
|
-
* Mirrors the chosen state where a stylesheet can select on it.
|
|
111
|
-
*
|
|
112
|
-
* **A custom state rather than the `selected` attribute.** The parent writes
|
|
113
|
-
* this: a listbox choosing a row, a tab strip moving the tab, a radio group
|
|
114
|
-
* answering for its set. Reflected, that puts the element's own bookkeeping
|
|
115
|
-
* onto markup a consumer wrote and a consumer's server never sent, which
|
|
116
|
-
* React reconciles and reports as a mismatch, and which a serialized element
|
|
117
|
-
* pasted back declares as a choice nobody made. `ElementInternals` holds it
|
|
118
|
-
* instead, where it is not in the DOM at all.
|
|
93
|
+
* Asks for the render that follows a hydration, so the stop stops being every
|
|
94
|
+
* choice's.
|
|
119
95
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
96
|
+
* `tabindex` reads `childrenKnown` and a hydrating render is one where that is
|
|
97
|
+
* false, which is what keeps the hydrating render the server's. Nothing else
|
|
98
|
+
* would ask: the group writes an already-false `focusable` onto every choice
|
|
99
|
+
* but one, which changes nothing and so re-renders nothing.
|
|
123
100
|
*/
|
|
124
|
-
protected
|
|
101
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
125
102
|
protected render(): TemplateResult;
|
|
126
103
|
}
|
|
127
104
|
declare global {
|
|
@@ -129,3 +106,4 @@ declare global {
|
|
|
129
106
|
'helix-headless-radio': HelixHeadlessRadio;
|
|
130
107
|
}
|
|
131
108
|
}
|
|
109
|
+
export {};
|
|
@@ -4,16 +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 { customElement, HelixElement,
|
|
7
|
+
import { customElement, HelixElement, MixinSelectableItem } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
-
let HelixHeadlessRadio = class HelixHeadlessRadio extends HelixElement {
|
|
10
|
+
let HelixHeadlessRadio = class HelixHeadlessRadio extends MixinSelectableItem(HelixElement) {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
|
-
this.disabled = false;
|
|
14
13
|
this.focusable = false;
|
|
15
|
-
this.selected = false;
|
|
16
|
-
this.value = '';
|
|
17
14
|
}
|
|
18
15
|
get defaultSelected() {
|
|
19
16
|
return this.hasAttribute('selected');
|
|
@@ -21,18 +18,9 @@ let HelixHeadlessRadio = class HelixHeadlessRadio extends HelixElement {
|
|
|
21
18
|
set defaultSelected(next) {
|
|
22
19
|
this.toggleAttribute('selected', next);
|
|
23
20
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
select() {
|
|
28
|
-
if (this.disabled) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
|
|
32
|
-
}
|
|
33
|
-
willUpdate(changed) {
|
|
34
|
-
super.willUpdate(changed);
|
|
35
|
-
this.toggleState('selected', this.selected);
|
|
21
|
+
firstUpdated(changed) {
|
|
22
|
+
super.firstUpdated(changed);
|
|
23
|
+
this.finishHydration();
|
|
36
24
|
}
|
|
37
25
|
render() {
|
|
38
26
|
return html `<button
|
|
@@ -41,7 +29,7 @@ let HelixHeadlessRadio = class HelixHeadlessRadio extends HelixElement {
|
|
|
41
29
|
role="radio"
|
|
42
30
|
aria-checked=${this.selected ? 'true' : 'false'}
|
|
43
31
|
?disabled=${this.disabled}
|
|
44
|
-
tabindex=${this.selected || this.focusable ? '0' : '-1'}
|
|
32
|
+
tabindex=${this.selected || this.focusable || !this.childrenKnown ? '0' : '-1'}
|
|
45
33
|
@click=${() => this.select()}
|
|
46
34
|
>
|
|
47
35
|
<span part="box"><span part="mark" aria-hidden="true"></span></span>
|
|
@@ -50,18 +38,9 @@ let HelixHeadlessRadio = class HelixHeadlessRadio extends HelixElement {
|
|
|
50
38
|
</button>`;
|
|
51
39
|
}
|
|
52
40
|
};
|
|
53
|
-
__decorate([
|
|
54
|
-
property({ reflect: true, type: Boolean })
|
|
55
|
-
], HelixHeadlessRadio.prototype, "disabled", void 0);
|
|
56
41
|
__decorate([
|
|
57
42
|
property({ attribute: false })
|
|
58
43
|
], HelixHeadlessRadio.prototype, "focusable", void 0);
|
|
59
|
-
__decorate([
|
|
60
|
-
property({ type: Boolean })
|
|
61
|
-
], HelixHeadlessRadio.prototype, "selected", void 0);
|
|
62
|
-
__decorate([
|
|
63
|
-
property()
|
|
64
|
-
], HelixHeadlessRadio.prototype, "value", void 0);
|
|
65
44
|
HelixHeadlessRadio = __decorate([
|
|
66
45
|
customElement('helix-headless-radio')
|
|
67
46
|
], HelixHeadlessRadio);
|
|
@@ -4,12 +4,10 @@ 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, formatNumbers, HelixElement, linear, MixinChartSource, seriesIndex, ticks, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, HelixElement, linear, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, 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
|
-
const WIDTH = 100;
|
|
12
|
-
const HEIGHT = 100;
|
|
13
11
|
const REACH = 24;
|
|
14
12
|
const coefficient = new Intl.NumberFormat(undefined, {
|
|
15
13
|
maximumFractionDigits: 2,
|
|
@@ -62,7 +60,8 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
62
60
|
let found;
|
|
63
61
|
let best = REACH ** 2;
|
|
64
62
|
for (const point of this.drawn) {
|
|
65
|
-
const distance = ((point.x /
|
|
63
|
+
const distance = ((point.x / PLOT_WIDTH) * box.width - across) ** 2 +
|
|
64
|
+
((point.y / PLOT_HEIGHT) * box.height - up) ** 2;
|
|
66
65
|
if (distance <= best) {
|
|
67
66
|
best = distance;
|
|
68
67
|
found = point;
|
|
@@ -112,8 +111,8 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
112
111
|
const all = pairs.flat();
|
|
113
112
|
const x = nice(extent(all.length > 0 ? all.map(([one]) => one) : [0]));
|
|
114
113
|
const y = nice(extent(all.length > 0 ? all.map(([, one]) => one) : [0]));
|
|
115
|
-
const along = linear(x, [0,
|
|
116
|
-
const up = linear(y, [
|
|
114
|
+
const along = linear(x, [0, PLOT_WIDTH]);
|
|
115
|
+
const up = linear(y, [PLOT_HEIGHT, 0]);
|
|
117
116
|
return {
|
|
118
117
|
pairs: pairs.map((series) => series.map(([one, two]) => [one, two])),
|
|
119
118
|
points: pairs.flatMap((series, depth) => series.map(([one, two, row]) => ({ depth, row, x: along(one), y: up(two) }))),
|
|
@@ -132,8 +131,8 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
132
131
|
</div>`;
|
|
133
132
|
}
|
|
134
133
|
const format = formatNumbers('');
|
|
135
|
-
const along = linear(field.x, [0,
|
|
136
|
-
const up = linear(field.y, [
|
|
134
|
+
const along = linear(field.x, [0, PLOT_WIDTH]);
|
|
135
|
+
const up = linear(field.y, [PLOT_HEIGHT, 0]);
|
|
137
136
|
return html `<div dir="ltr" part="plane">
|
|
138
137
|
${this.renderPlot(field, along, up)}
|
|
139
138
|
<div aria-hidden="true" part="x-axis">
|
|
@@ -152,14 +151,14 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
152
151
|
return html `<div aria-hidden="true" id=${CHART_PLOT} part="plot">
|
|
153
152
|
<svg part="svg"
|
|
154
153
|
preserveAspectRatio="none"
|
|
155
|
-
viewBox="0 0 ${
|
|
154
|
+
viewBox="0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}"
|
|
156
155
|
xmlns="http://www.w3.org/2000/svg"
|
|
157
156
|
>
|
|
158
157
|
${this.rulesX
|
|
159
|
-
? ticks(field.x).map((level) => svg `<line part="gridline" x1=${along(level)} x2=${along(level)} y1="0" y2=${
|
|
158
|
+
? ticks(field.x).map((level) => svg `<line part="gridline" x1=${along(level)} x2=${along(level)} y1="0" y2=${PLOT_HEIGHT} />`)
|
|
160
159
|
: nothing}
|
|
161
160
|
${this.rulesY
|
|
162
|
-
? ticks(field.y).map((level) => svg `<line part="gridline" x1="0" x2=${
|
|
161
|
+
? ticks(field.y).map((level) => svg `<line part="gridline" x1="0" x2=${PLOT_WIDTH} y1=${up(level)} y2=${up(level)} />`)
|
|
163
162
|
: nothing}
|
|
164
163
|
</svg>
|
|
165
164
|
${field.points.map((point) => {
|
|
@@ -134,6 +134,30 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
|
|
|
134
134
|
* `slotchange`, which a declarative shadow root fires before anything listens,
|
|
135
135
|
* so a hydrated select kept "Choose" for good. Nothing on a server or while
|
|
136
136
|
* hydrating what one sent, which drew the placeholder too.
|
|
137
|
+
*
|
|
138
|
+
* **And the placeholder is a statement, so a render that cannot read the
|
|
139
|
+
* words does not make it.** "Choose" means nothing is chosen. `value` is an
|
|
140
|
+
* attribute and a server has it, the words are the children's and a server
|
|
141
|
+
* has none, so a `<helix-select default-value="two">` served "Choose" over an
|
|
142
|
+
* answer the consumer had already given: false to a reader, and false to a
|
|
143
|
+
* crawler, on every select in the library's own examples. Where a value is
|
|
144
|
+
* declared and the word for it cannot be read, the trigger says nothing and
|
|
145
|
+
* keeps its box, which is the answer this library reaches for everywhere it
|
|
146
|
+
* cannot tell empty from unknown. `firstUpdated` asks for the render that
|
|
147
|
+
* fills it in.
|
|
148
|
+
*
|
|
149
|
+
* The placeholder still stands where there is genuinely no value, which is
|
|
150
|
+
* what it is for and the one case a server can be sure of.
|
|
151
|
+
*
|
|
152
|
+
* **`nothing` and never `''`, which is the difference between a word that
|
|
153
|
+
* arrives and one that never does.** Lit's hydration primes a child part with
|
|
154
|
+
* whatever the render computed, and `''` is a primitive, so `_commitText`
|
|
155
|
+
* takes the branch that assumes the server left a text node to overwrite.
|
|
156
|
+
* There is none, the write lands on the closing part marker's comment data,
|
|
157
|
+
* and the trigger stays empty for the life of the page: measured by
|
|
158
|
+
* `check:spec:dsd`, which caught all nine of these and showed a blank select
|
|
159
|
+
* beside a client's "Option Two". `nothing` primes the sentinel instead, so
|
|
160
|
+
* the commit creates the text node it needs.
|
|
137
161
|
*/
|
|
138
162
|
private get display();
|
|
139
163
|
/** Closes the list and puts focus back where it came from. */
|
|
@@ -74,7 +74,10 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
|
|
|
74
74
|
const words = optionsAmong(this.knownChildren)
|
|
75
75
|
.filter((option) => chosen.has(option.value))
|
|
76
76
|
.map((option) => option.text);
|
|
77
|
-
|
|
77
|
+
if (words.length > 0) {
|
|
78
|
+
return words.join(', ');
|
|
79
|
+
}
|
|
80
|
+
return chosen.size > 0 && !this.childrenKnown ? nothing : this.placeholder;
|
|
78
81
|
}
|
|
79
82
|
close() {
|
|
80
83
|
if (!this.open) {
|
|
@@ -142,7 +145,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
|
|
|
142
145
|
return html `${this.renderLabel()}
|
|
143
146
|
<button
|
|
144
147
|
part="trigger"
|
|
145
|
-
id
|
|
148
|
+
id=${this.controlId}
|
|
146
149
|
type="button"
|
|
147
150
|
aria-haspopup="listbox"
|
|
148
151
|
aria-expanded=${this.open ? 'true' : 'false'}
|
|
@@ -146,7 +146,7 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
|
|
|
146
146
|
? nothing
|
|
147
147
|
: html `<input
|
|
148
148
|
part="control"
|
|
149
|
-
id
|
|
149
|
+
id=${this.controlId}
|
|
150
150
|
type="range"
|
|
151
151
|
style="--slider-fraction: ${this.fraction}"
|
|
152
152
|
min=${this.min}
|