@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
|
@@ -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, hostAria, MixinDismissible,
|
|
7
|
+
import { customElement, HelixElement, hostAria, MixinDismissible, markRegion, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { x } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
@@ -20,10 +20,7 @@ let HelixHeadlessAnnouncement = class HelixHeadlessAnnouncement extends MixinDis
|
|
|
20
20
|
this.markEmpty();
|
|
21
21
|
}
|
|
22
22
|
markEmpty() {
|
|
23
|
-
|
|
24
|
-
const empty = !slotFilled(this.renderRoot?.querySelector('slot[name="actions"]'));
|
|
25
|
-
region?.toggleAttribute('data-empty', empty);
|
|
26
|
-
region?.toggleAttribute('hidden', empty);
|
|
23
|
+
markRegion(this.renderRoot, 'actions', ['actions']);
|
|
27
24
|
}
|
|
28
25
|
renderDismissIcon() {
|
|
29
26
|
return html `<slot name="icon">
|
|
@@ -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, formatNumbers, HelixElement, linear, linePath, MixinChartSource, seriesIndex, ticks, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, formatNumbers, 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
|
const percent = new Intl.NumberFormat(undefined, { maximumFractionDigits: 0, style: 'percent' });
|
|
14
12
|
let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSource(HelixElement) {
|
|
15
13
|
constructor() {
|
|
@@ -73,9 +71,9 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
73
71
|
}
|
|
74
72
|
const top = this.share ? 1 : Math.max(0, ...stack.totals);
|
|
75
73
|
const domain = [0, top > 0 ? top : 1];
|
|
76
|
-
const y = linear(domain, [
|
|
77
|
-
const slot =
|
|
78
|
-
const x = linear([0, Math.max(rows.length - 1, 1)], [slot / 2,
|
|
74
|
+
const y = linear(domain, [PLOT_HEIGHT, 0]);
|
|
75
|
+
const slot = PLOT_WIDTH / rows.length;
|
|
76
|
+
const x = linear([0, Math.max(rows.length - 1, 1)], [slot / 2, PLOT_WIDTH - slot / 2]);
|
|
79
77
|
return html `${this.renderPlot(stack, rows.length, x, y, domain)}
|
|
80
78
|
${this.renderLabels(rows.map((row) => row.label))} ${this.renderSummary(stack, rows)}`;
|
|
81
79
|
}
|
|
@@ -85,12 +83,12 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
85
83
|
<svg part="svg"
|
|
86
84
|
data-mirror
|
|
87
85
|
preserveAspectRatio="none"
|
|
88
|
-
viewBox="0 0 ${
|
|
86
|
+
viewBox="0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}"
|
|
89
87
|
xmlns="http://www.w3.org/2000/svg"
|
|
90
88
|
>
|
|
91
89
|
${order.map((depth) => this.renderLayer(stack.layers[depth] ?? [], depth, x, y))}
|
|
92
90
|
${this.renderGridlines(x, y, domain, count)}
|
|
93
|
-
<line part="baseline" x1="0" x2=${
|
|
91
|
+
<line part="baseline" x1="0" x2=${PLOT_WIDTH} y1=${PLOT_HEIGHT} y2=${PLOT_HEIGHT} />
|
|
94
92
|
${this.renderGuide(x)}
|
|
95
93
|
</svg>
|
|
96
94
|
${this.renderTooltip(stack, y)}
|
|
@@ -105,7 +103,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
105
103
|
const index = seriesIndex(depth);
|
|
106
104
|
const first = points[0];
|
|
107
105
|
const last = points.at(-1);
|
|
108
|
-
const wash = `${path}L${last[0]},${
|
|
106
|
+
const wash = `${path}L${last[0]},${PLOT_HEIGHT}L${first[0]},${PLOT_HEIGHT}Z`;
|
|
109
107
|
return svg `<path
|
|
110
108
|
d=${wash}
|
|
111
109
|
data-series=${index}
|
|
@@ -124,12 +122,12 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
124
122
|
return nothing;
|
|
125
123
|
}
|
|
126
124
|
const down = this.rulesCategory
|
|
127
|
-
? Array.from({ length: count }, (_, index) => svg `<line part="gridline" x1=${x(index)} x2=${x(index)} y1="0" y2=${
|
|
125
|
+
? Array.from({ length: count }, (_, index) => svg `<line part="gridline" x1=${x(index)} x2=${x(index)} y1="0" y2=${PLOT_HEIGHT} />`)
|
|
128
126
|
: [];
|
|
129
127
|
const across = this.rulesValue
|
|
130
128
|
? ticks(domain)
|
|
131
129
|
.filter((level) => level > domain[0])
|
|
132
|
-
.map((level) => svg `<line part="gridline" x1="0" x2=${
|
|
130
|
+
.map((level) => svg `<line part="gridline" x1="0" x2=${PLOT_WIDTH} y1=${y(level)} y2=${y(level)} />`)
|
|
133
131
|
: [];
|
|
134
132
|
return svg `${down}${across}`;
|
|
135
133
|
}
|
|
@@ -138,7 +136,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
138
136
|
if (at < 0) {
|
|
139
137
|
return nothing;
|
|
140
138
|
}
|
|
141
|
-
return svg `<line part="guide" x1=${x(at)} x2=${x(at)} y1="0" y2=${
|
|
139
|
+
return svg `<line part="guide" x1=${x(at)} x2=${x(at)} y1="0" y2=${PLOT_HEIGHT} />`;
|
|
142
140
|
}
|
|
143
141
|
renderLabels(readings) {
|
|
144
142
|
return html `<div aria-hidden="true" part="labels">
|
|
@@ -4,11 +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, seriesNames, ticks, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, 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
|
-
const HEIGHT = 100;
|
|
12
11
|
let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource(HelixElement) {
|
|
13
12
|
get scaled() {
|
|
14
13
|
return new Set(seriesNames(this.secondary));
|
|
@@ -41,7 +40,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
41
40
|
};
|
|
42
41
|
const [low, high] = extent(scaled.size === 0 ? on(() => true) : on((one) => !own(one)));
|
|
43
42
|
const domain = [Math.min(0, low), Math.max(0, high)];
|
|
44
|
-
const range = this.direction === 'horizontal' ? [0,
|
|
43
|
+
const range = this.direction === 'horizontal' ? [0, PLOT_HEIGHT] : [PLOT_HEIGHT, 0];
|
|
45
44
|
const y = linear(domain, range);
|
|
46
45
|
const floor = y(0);
|
|
47
46
|
const sideways = this.direction === 'horizontal';
|
|
@@ -103,7 +102,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
103
102
|
<svg part="svg"
|
|
104
103
|
data-mirror
|
|
105
104
|
preserveAspectRatio="none"
|
|
106
|
-
viewBox="0 0
|
|
105
|
+
viewBox="0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}"
|
|
107
106
|
xmlns="http://www.w3.org/2000/svg"
|
|
108
107
|
>
|
|
109
108
|
${svg `<defs>
|
|
@@ -208,7 +207,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
208
207
|
const [low, high] = extent(all.length > 0 ? all : [0]);
|
|
209
208
|
const domain = [Math.min(0, low), Math.max(0, high)];
|
|
210
209
|
const sideways = this.direction === 'horizontal';
|
|
211
|
-
const scale = sideways ? linear(domain, [0,
|
|
210
|
+
const scale = sideways ? linear(domain, [0, PLOT_HEIGHT]) : linear(domain, [PLOT_HEIGHT, 0]);
|
|
212
211
|
const ends = values.map((one) => scale(one));
|
|
213
212
|
const far = sideways ? Math.max(...ends) : Math.min(...ends);
|
|
214
213
|
const slot = 100 / this.readings;
|
|
@@ -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,
|
|
7
|
+
import { customElement, HelixElement, markRegion } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessBlockquote = class HelixHeadlessBlockquote extends HelixElement {
|
|
@@ -13,10 +13,7 @@ let HelixHeadlessBlockquote = class HelixHeadlessBlockquote extends HelixElement
|
|
|
13
13
|
this.cite = '';
|
|
14
14
|
}
|
|
15
15
|
markEmpty() {
|
|
16
|
-
|
|
17
|
-
const empty = !slotFilled(this.renderRoot?.querySelector('slot[name="attribution"]'));
|
|
18
|
-
footer?.toggleAttribute('data-empty', empty);
|
|
19
|
-
footer?.toggleAttribute('hidden', empty);
|
|
16
|
+
markRegion(this.renderRoot, 'attribution', ['attribution']);
|
|
20
17
|
}
|
|
21
18
|
updated(changed) {
|
|
22
19
|
super.updated(changed);
|
|
@@ -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, HelixSendEvent, hostAria,
|
|
7
|
+
import { customElement, HelixElement, HelixSendEvent, hostAria, markRegion, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { arrowElbowDownLeft } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -56,10 +56,7 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixEle
|
|
|
56
56
|
}
|
|
57
57
|
markEmpty() {
|
|
58
58
|
for (const name of ['start', 'end']) {
|
|
59
|
-
|
|
60
|
-
const empty = !slotFilled(this.renderRoot?.querySelector(`slot[name="${name}"]`));
|
|
61
|
-
region?.toggleAttribute('data-empty', empty);
|
|
62
|
-
region?.toggleAttribute('hidden', empty);
|
|
59
|
+
markRegion(this.renderRoot, name, [name]);
|
|
63
60
|
}
|
|
64
61
|
}
|
|
65
62
|
updated(changed) {
|
|
@@ -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, HelixSendEvent, hostAria, relativeTime, requestChange,
|
|
7
|
+
import { customElement, HelixElement, HelixSendEvent, hostAria, markRegion, relativeTime, requestChange, TONE_MARKS, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
@@ -85,16 +85,9 @@ let HelixHeadlessChatMessage = class HelixHeadlessChatMessage extends HelixEleme
|
|
|
85
85
|
</span>`;
|
|
86
86
|
}
|
|
87
87
|
markEmpty() {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
? this.renderRoot?.querySelector('slot:not([name])')
|
|
92
|
-
: this.renderRoot?.querySelector(`slot[name="${name}"]`);
|
|
93
|
-
const empty = !slotFilled(slot);
|
|
94
|
-
region?.toggleAttribute('data-empty', empty);
|
|
95
|
-
if (name !== 'content') {
|
|
96
|
-
region?.toggleAttribute('hidden', empty);
|
|
97
|
-
}
|
|
88
|
+
markRegion(this.renderRoot, 'content', [''], { hide: false });
|
|
89
|
+
for (const name of ['sources', 'actions']) {
|
|
90
|
+
markRegion(this.renderRoot, name, [name]);
|
|
98
91
|
}
|
|
99
92
|
}
|
|
100
93
|
updated(changed) {
|
|
@@ -208,7 +208,7 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
208
208
|
return [...(this.children ?? [])].filter((child) => child.getAttribute('slot') === name);
|
|
209
209
|
}
|
|
210
210
|
countRegions() {
|
|
211
|
-
if (this.
|
|
211
|
+
if (!this.childrenKnown) {
|
|
212
212
|
return;
|
|
213
213
|
}
|
|
214
214
|
const filled = new Set(REGIONS.filter((name) => this.given(name).length > 0));
|
|
@@ -61,7 +61,7 @@ let HelixHeadlessCheckbox = class HelixHeadlessCheckbox extends MixinControllerC
|
|
|
61
61
|
<input
|
|
62
62
|
part="control"
|
|
63
63
|
type="checkbox"
|
|
64
|
-
.checked=${this.checked}
|
|
64
|
+
.checked=${this.checked || nothing}
|
|
65
65
|
.indeterminate=${this.indeterminate}
|
|
66
66
|
?disabled=${this.isDisabled}
|
|
67
67
|
?required=${this.required}
|
|
@@ -81,7 +81,7 @@ let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinF
|
|
|
81
81
|
super.willUpdate(changed);
|
|
82
82
|
hostAria(this.internals, { label: this.label, role: 'group' });
|
|
83
83
|
this.internals.ariaRequired = this.required ? 'true' : null;
|
|
84
|
-
if (!this.seeded && this.
|
|
84
|
+
if (!this.seeded && this.childrenKnown) {
|
|
85
85
|
this.seeded = true;
|
|
86
86
|
if (this.value === '') {
|
|
87
87
|
this.seed();
|
|
@@ -208,6 +208,22 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
|
|
|
208
208
|
* so a tag does not move out from under the pointer about to remove it.
|
|
209
209
|
*/
|
|
210
210
|
private get chosen();
|
|
211
|
+
/**
|
|
212
|
+
* Whether a value is declared and this render cannot say what it is.
|
|
213
|
+
*
|
|
214
|
+
* **A placeholder is a statement, so a render that cannot read the words does
|
|
215
|
+
* not make it.** `value` is an attribute and a server has it; the words are
|
|
216
|
+
* the options' and the options are light-DOM children a server has none of.
|
|
217
|
+
* The field then came out empty with "Search owners" over it, which says
|
|
218
|
+
* nothing is chosen where the consumer had already said what is. Blank, it
|
|
219
|
+
* says nothing, keeps its box, and is filled in by the render after
|
|
220
|
+
* hydration, which is the answer `Select.Root.display` reaches for in the same
|
|
221
|
+
* position and for the same reason.
|
|
222
|
+
*
|
|
223
|
+
* The placeholder still stands where there is genuinely no value, which is
|
|
224
|
+
* what it is for and the one case a server can be sure of.
|
|
225
|
+
*/
|
|
226
|
+
private get unresolved();
|
|
211
227
|
/**
|
|
212
228
|
* Whether the filter has left anything to choose.
|
|
213
229
|
*
|
|
@@ -147,6 +147,9 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
147
147
|
.filter((value) => known || words.has(value))
|
|
148
148
|
.map((value) => ({ text: words.get(value) ?? value, value }));
|
|
149
149
|
}
|
|
150
|
+
get unresolved() {
|
|
151
|
+
return this.values.length > 0 && !this.childrenKnown;
|
|
152
|
+
}
|
|
150
153
|
get showing() {
|
|
151
154
|
return (this.listbox?.options ?? []).some((option) => !option.hidden);
|
|
152
155
|
}
|
|
@@ -295,7 +298,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
295
298
|
: nothing}
|
|
296
299
|
<input
|
|
297
300
|
part="control"
|
|
298
|
-
id
|
|
301
|
+
id=${this.controlId}
|
|
299
302
|
type="text"
|
|
300
303
|
role="combobox"
|
|
301
304
|
autocomplete=${this.autocomplete || nothing}
|
|
@@ -304,7 +307,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
304
307
|
aria-autocomplete=${this.suggest ? 'both' : 'list'}
|
|
305
308
|
aria-expanded=${this.open ? 'true' : 'false'}
|
|
306
309
|
aria-describedby=${this.describedBy ?? nothing}
|
|
307
|
-
placeholder=${(this.chosen.length > 0 ? '' : this.placeholder) || nothing}
|
|
310
|
+
placeholder=${(this.chosen.length > 0 || this.unresolved ? '' : this.placeholder) || nothing}
|
|
308
311
|
?disabled=${this.isDisabled}
|
|
309
312
|
.value=${this.multiple || this.open ? this.suggestion || this.typed : this.word}
|
|
310
313
|
@input=${this.handleInput}
|
|
@@ -473,8 +473,31 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
473
473
|
* The mixin's own answer counts children with no `slot`, which for this
|
|
474
474
|
* element is the columns. Left in place, a table with columns and no data
|
|
475
475
|
* would call itself full.
|
|
476
|
+
*
|
|
477
|
+
* **`sourceKnown` is the half the mixin was keeping**, and overriding without
|
|
478
|
+
* it is what put "Nothing to show" over eight rows of files on every server
|
|
479
|
+
* render of this family's own preview. `MixinCollection.hasRows` answers true
|
|
480
|
+
* until the rows have been counted for exactly that reason, and a count is
|
|
481
|
+
* what this replaced.
|
|
476
482
|
*/
|
|
477
483
|
protected get hasRows(): boolean;
|
|
484
|
+
/**
|
|
485
|
+
* Whether this render can tell a result with no rows from one not yet handed
|
|
486
|
+
* over.
|
|
487
|
+
*
|
|
488
|
+
* **Unknown is not empty, which is what an empty state must never say.** The
|
|
489
|
+
* rows are a property, and a property is set by whoever holds the element: a
|
|
490
|
+
* consumer binding it in a template has it on the server, and a consumer
|
|
491
|
+
* assigning it from a script has it only once that script has run, which is
|
|
492
|
+
* after the parse a server's markup ends at. A render that cannot see a
|
|
493
|
+
* document cannot tell the two apart, and a hydrating render must not look,
|
|
494
|
+
* its output having to be the server's.
|
|
495
|
+
*
|
|
496
|
+
* The same shape as `Heatmap.sourceKnown`, asked of a property rather than of
|
|
497
|
+
* a document, and `childrenKnown` is already both halves of the question: a
|
|
498
|
+
* server has no tree and a hydrating render may not read one.
|
|
499
|
+
*/
|
|
500
|
+
private get sourceKnown();
|
|
478
501
|
/**
|
|
479
502
|
* Asks for a different order, and reports whether the request stood.
|
|
480
503
|
*
|
|
@@ -569,16 +592,6 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
569
592
|
* assigned nodes are not a slot's DOM children. Both verified in a browser.
|
|
570
593
|
*/
|
|
571
594
|
private markEmpty;
|
|
572
|
-
/**
|
|
573
|
-
* One region, hidden when its slot holds nothing and nothing of ours fills it.
|
|
574
|
-
*
|
|
575
|
-
* `hidden` beside the `data-empty` mirror: `data-empty` is the hook the styled
|
|
576
|
-
* sheet reads, and this tier ships no sheet, so an empty region left in the box
|
|
577
|
-
* tree would be a gap a headless consumer cannot close without knowing to look
|
|
578
|
-
* for it. The styled rule stays too, because that sheet sets `display` on these
|
|
579
|
-
* parts and therefore outranks the UA's `[hidden]` one.
|
|
580
|
-
*/
|
|
581
|
-
private markRegion;
|
|
582
595
|
protected updated(changed: PropertyValues): void;
|
|
583
596
|
/**
|
|
584
597
|
* Tells each column which way it is ordered, if it is the one.
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
var HelixHeadlessDataTable_1;
|
|
8
|
-
import { customElement, HelixElement, HelixFilterEvent, HelixNavigateEvent, HelixReorderEvent, HelixSelectEvent, HelixSortEvent, hostAria, inlineStep, MixinCollection,
|
|
8
|
+
import { customElement, HelixElement, HelixFilterEvent, HelixNavigateEvent, HelixReorderEvent, HelixSelectEvent, HelixSortEvent, hostAria, inlineStep, MixinCollection, markRegion, requestChange, VirtualizeController, writtenList, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { repeat } from 'lit/directives/repeat.js';
|
|
@@ -262,7 +262,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
262
262
|
}
|
|
263
263
|
get orderedColumns() {
|
|
264
264
|
const columns = this.tableColumns;
|
|
265
|
-
const wanted = this.dragOrder ?? this.order
|
|
265
|
+
const wanted = this.dragOrder ?? writtenList(this.order);
|
|
266
266
|
if (wanted.length === 0) {
|
|
267
267
|
return columns;
|
|
268
268
|
}
|
|
@@ -353,7 +353,10 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
353
353
|
})).length;
|
|
354
354
|
}
|
|
355
355
|
get hasRows() {
|
|
356
|
-
return this.view.available > 0;
|
|
356
|
+
return this.view.available > 0 || !this.sourceKnown;
|
|
357
|
+
}
|
|
358
|
+
get sourceKnown() {
|
|
359
|
+
return this.childrenKnown;
|
|
357
360
|
}
|
|
358
361
|
requestSort(next) {
|
|
359
362
|
return requestChange({
|
|
@@ -516,14 +519,8 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
516
519
|
}
|
|
517
520
|
}
|
|
518
521
|
markEmpty() {
|
|
519
|
-
this.
|
|
520
|
-
this.
|
|
521
|
-
}
|
|
522
|
-
markRegion(part, slots, occupied) {
|
|
523
|
-
const region = this.renderRoot?.querySelector(`[part="${part}"]`);
|
|
524
|
-
const empty = !slots.some((name) => slotFilled(this.renderRoot?.querySelector(`slot[name="${name}"]`))) && !(occupied && this.renderRoot?.querySelector(occupied));
|
|
525
|
-
region?.toggleAttribute('data-empty', empty);
|
|
526
|
-
region?.toggleAttribute('hidden', empty);
|
|
522
|
+
markRegion(this.renderRoot, 'toolbar', ['toolbar']);
|
|
523
|
+
markRegion(this.renderRoot, 'footer', ['footer'], { occupied: '[part="pagination"]' });
|
|
527
524
|
}
|
|
528
525
|
updated(changed) {
|
|
529
526
|
super.updated(changed);
|
|
@@ -624,12 +621,14 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
624
621
|
const template = this.template;
|
|
625
622
|
const columns = this.shownColumns;
|
|
626
623
|
const pagination = this.tag('pagination');
|
|
624
|
+
const counted = this.mode === 'server' ? Math.max(this.total, available) : matched;
|
|
625
|
+
const countKnown = counted > 0 || this.sourceKnown;
|
|
627
626
|
return html `<div part="toolbar"><slot name="toolbar"></slot></div>
|
|
628
627
|
<div
|
|
629
628
|
part="table"
|
|
630
629
|
role="rowgroup"
|
|
631
630
|
aria-busy=${this.loading ? 'true' : nothing}
|
|
632
|
-
aria-rowcount=${
|
|
631
|
+
aria-rowcount=${countKnown ? counted + 1 : nothing}
|
|
633
632
|
aria-colcount=${columns.length ? columns.length + (this.selectable ? 1 : 0) : nothing}
|
|
634
633
|
style=${template ? `--data-table-template: ${template}` : nothing}
|
|
635
634
|
@scroll=${this.handleScroll}
|
|
@@ -654,7 +653,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
654
653
|
status: pagination-status"
|
|
655
654
|
page=${this.page}
|
|
656
655
|
page-size=${this.pageSize || 1}
|
|
657
|
-
total=${matched}
|
|
656
|
+
total=${countKnown ? matched : nothing}
|
|
658
657
|
@helix-navigate=${this.handleNavigate}
|
|
659
658
|
></${pagination}>`
|
|
660
659
|
: 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, HelixElement,
|
|
7
|
+
import { customElement, HelixElement, markRegion } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
|
|
@@ -13,10 +13,7 @@ let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
|
|
|
13
13
|
this.announced = false;
|
|
14
14
|
}
|
|
15
15
|
markEmpty() {
|
|
16
|
-
|
|
17
|
-
const empty = !slotFilled(this.renderRoot?.querySelector('slot'));
|
|
18
|
-
region?.toggleAttribute('data-empty', empty);
|
|
19
|
-
region?.toggleAttribute('hidden', empty);
|
|
16
|
+
markRegion(this.renderRoot, 'content', ['']);
|
|
20
17
|
}
|
|
21
18
|
updated(changed) {
|
|
22
19
|
super.updated(changed);
|
|
@@ -4,12 +4,11 @@ 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, MixinChartSource, seriesIndex, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, HelixElement, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, } 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
|
|
12
|
-
const CENTER = BOX / 2;
|
|
11
|
+
const CENTER = PLOT_WIDTH / 2;
|
|
13
12
|
const EDGE = 40;
|
|
14
13
|
const GAP = 9999;
|
|
15
14
|
const THICKNESS = {
|
|
@@ -86,9 +85,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
|
|
|
86
85
|
}
|
|
87
86
|
get frame() {
|
|
88
87
|
if (this.sweep !== 'half') {
|
|
89
|
-
return `0 0 ${
|
|
88
|
+
return `0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}`;
|
|
90
89
|
}
|
|
91
|
-
return `0 ${CENTER - EDGE} ${
|
|
90
|
+
return `0 ${CENTER - EDGE} ${PLOT_WIDTH} ${EDGE + this.thickness / 2}`;
|
|
92
91
|
}
|
|
93
92
|
renderSegment(share, index) {
|
|
94
93
|
const circumference = 2 * Math.PI * this.radius;
|
|
@@ -150,7 +149,7 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
|
|
|
150
149
|
const edge = EDGE;
|
|
151
150
|
const x = CENTER + Math.cos(angle) * edge;
|
|
152
151
|
const top = this.sweep === 'half' ? CENTER - EDGE : 0;
|
|
153
|
-
const tall = this.sweep === 'half' ? EDGE + this.thickness / 2 :
|
|
152
|
+
const tall = this.sweep === 'half' ? EDGE + this.thickness / 2 : PLOT_HEIGHT;
|
|
154
153
|
const y = ((CENTER + Math.sin(angle) * edge - top) / tall) * 100;
|
|
155
154
|
const turned = this.sweep === 'half' && this.pointer.mirrored;
|
|
156
155
|
const across = Math.cos(angle) > 0 !== turned;
|
|
@@ -111,6 +111,24 @@ export declare class HelixHeadlessDrilldownItem extends HelixElement {
|
|
|
111
111
|
private readonly readPage;
|
|
112
112
|
/** Moves focus onto the row itself. */
|
|
113
113
|
focusItem(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Whether this is the row the set is on, which in a drill-down is where focus
|
|
116
|
+
* is.
|
|
117
|
+
*
|
|
118
|
+
* A radio group's selection is an answer it holds; a page of rows has no
|
|
119
|
+
* answer, only the row a reader has walked to, so focus is the whole of what
|
|
120
|
+
* "the current one" can mean here. This is `Menu.Item`'s reading word for
|
|
121
|
+
* word, and the two are one pattern: a menu that drills and a drill-down are
|
|
122
|
+
* the same rows through the same controller.
|
|
123
|
+
*
|
|
124
|
+
* Asked of the document rather than of the shadow root. `focusItem` puts
|
|
125
|
+
* focus on the control inside this row and the platform retargets it, so from
|
|
126
|
+
* outside the shadow tree `activeElement` is this element already and nothing
|
|
127
|
+
* has to walk a tree. `ShadowRoot.activeElement` is also the reading that does
|
|
128
|
+
* not survive happy-dom, which climbs `getRootNode()` to the top and then
|
|
129
|
+
* dereferences what it ran out of.
|
|
130
|
+
*/
|
|
131
|
+
get selected(): boolean;
|
|
114
132
|
/** Announces that this row was chosen. */
|
|
115
133
|
select(): void;
|
|
116
134
|
protected render(): TemplateResult | typeof nothing;
|
|
@@ -37,6 +37,9 @@ let HelixHeadlessDrilldownItem = class HelixHeadlessDrilldownItem extends HelixE
|
|
|
37
37
|
focusItem() {
|
|
38
38
|
this.partNamed('item')?.focus();
|
|
39
39
|
}
|
|
40
|
+
get selected() {
|
|
41
|
+
return this.ownerDocument.activeElement === this;
|
|
42
|
+
}
|
|
40
43
|
select() {
|
|
41
44
|
if (this.disabled) {
|
|
42
45
|
return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HelixElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { HelixElement, KeyboardNavigationController } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
declare const HelixHeadlessDrilldown_base: (new (...args: any[]) => import("@fusion.dev/helix-core").CollectionElement) & typeof HelixElement;
|
|
4
4
|
/**
|
|
@@ -73,6 +73,25 @@ export declare class HelixHeadlessDrilldown extends HelixHeadlessDrilldown_base
|
|
|
73
73
|
private readonly drilldown;
|
|
74
74
|
/** The rows on the page showing, which is what the keys move over. */
|
|
75
75
|
private get items();
|
|
76
|
+
/**
|
|
77
|
+
* Moving between rows, which is `Menu`'s arrangement and not a second one.
|
|
78
|
+
*
|
|
79
|
+
* The horizontal pair is reserved rather than released: in a drill-down they
|
|
80
|
+
* are the platform's own bindings for drilling, along the line to go in and
|
|
81
|
+
* back along it to come out, so they are spoken for here rather than
|
|
82
|
+
* unhandled. `handleKeydown` below owes them a binding, which is what
|
|
83
|
+
* reserving one means, and it has them.
|
|
84
|
+
*
|
|
85
|
+
* `selects` false, because arriving at a row must not follow it. Moving and
|
|
86
|
+
* choosing are one act in a radio group and two here, which is the same
|
|
87
|
+
* reading `Menu` takes over the same rows.
|
|
88
|
+
*
|
|
89
|
+
* The origin is the selection, which for these rows is where focus is. `focus`
|
|
90
|
+
* is the wrong reading however right it looks: it also carries a rule that a
|
|
91
|
+
* press which did not come from the set moves nothing, and Down on a page a
|
|
92
|
+
* reader has just tabbed to is how they get onto the first row at all.
|
|
93
|
+
*/
|
|
94
|
+
protected readonly keys: KeyboardNavigationController;
|
|
76
95
|
/**
|
|
77
96
|
* Puts the region's one tab stop on the first row of the page showing.
|
|
78
97
|
*
|
|
@@ -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, inlineStep, MixinCollection, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, DrilldownController, HelixElement, hostAria, inlineStep, KeyboardNavigationController, 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';
|
|
@@ -20,6 +20,11 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
|
|
|
20
20
|
root: () => [...this.children],
|
|
21
21
|
slot: 'page',
|
|
22
22
|
});
|
|
23
|
+
this.keys = new KeyboardNavigationController(this, {
|
|
24
|
+
items: () => this.items,
|
|
25
|
+
reserved: () => ['ArrowLeft', 'ArrowRight'],
|
|
26
|
+
selects: () => false,
|
|
27
|
+
});
|
|
23
28
|
this.handleFocusIn = (event) => {
|
|
24
29
|
const item = this.drilldown.rows.find((row) => row.contains(event.target));
|
|
25
30
|
if (item && !item.disabled) {
|
|
@@ -45,18 +50,6 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
|
|
|
45
50
|
this.handleKeydown = (event) => {
|
|
46
51
|
const items = this.items;
|
|
47
52
|
const current = items.findIndex((item) => item.matches(':focus-within'));
|
|
48
|
-
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
49
|
-
event.preventDefault();
|
|
50
|
-
const step = event.key === 'ArrowDown' ? 1 : -1;
|
|
51
|
-
const next = (current + step + items.length) % Math.max(items.length, 1);
|
|
52
|
-
items[current === -1 ? 0 : next]?.focusItem();
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (event.key === 'Home' || event.key === 'End') {
|
|
56
|
-
event.preventDefault();
|
|
57
|
-
(event.key === 'Home' ? items[0] : items[items.length - 1])?.focusItem();
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
53
|
const along = inlineStep(this, event.key);
|
|
61
54
|
if (along === -1 || event.key === 'Escape') {
|
|
62
55
|
if (this.back()) {
|
|
@@ -179,7 +179,7 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
|
|
|
179
179
|
>
|
|
180
180
|
<input
|
|
181
181
|
part="control"
|
|
182
|
-
id
|
|
182
|
+
id=${this.controlId}
|
|
183
183
|
type="file"
|
|
184
184
|
accept=${this.accept || nothing}
|
|
185
185
|
capture=${this.capture ?? nothing}
|
|
@@ -191,7 +191,7 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
|
|
|
191
191
|
@change=${this.handleChange}
|
|
192
192
|
@input=${this.stopInner}
|
|
193
193
|
/>
|
|
194
|
-
<label part="trigger" for
|
|
194
|
+
<label part="trigger" for=${this.controlId}>
|
|
195
195
|
<slot name="trigger">${this.triggerLabel}</slot>
|
|
196
196
|
</label>
|
|
197
197
|
</div>
|
|
@@ -334,7 +334,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
334
334
|
${this.renderTokenRow(html `<slot name="tags" @slotchange=${this.handleTokens}></slot>`, this.over)}
|
|
335
335
|
<input
|
|
336
336
|
part="control"
|
|
337
|
-
id
|
|
337
|
+
id=${this.controlId}
|
|
338
338
|
type="text"
|
|
339
339
|
.value=${this.value}
|
|
340
340
|
name=${this.name || nothing}
|