@fusion.dev/helix-headless 0.144.0 → 0.145.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.
- package/custom-elements.json +8312 -881
- package/dist/accordion/item/accordion-item.d.ts +48 -12
- package/dist/accordion/item/accordion-item.js +26 -5
- package/dist/accordion/root/accordion-root.d.ts +6 -0
- package/dist/accordion/root/accordion-root.js +7 -1
- package/dist/announcement/root/announcement-root.d.ts +21 -1
- package/dist/announcement/root/announcement-root.js +36 -1
- package/dist/app-header/root/app-header-root.d.ts +7 -0
- package/dist/app-header/root/app-header-root.js +5 -1
- package/dist/app-header/sectioning.d.ts +7 -0
- package/dist/app-header/sectioning.js +26 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +32 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +25 -2
- package/dist/canvas/root/canvas-root.d.ts +38 -3
- package/dist/canvas/root/canvas-root.js +121 -40
- package/dist/carousel/root/carousel-root.d.ts +90 -0
- package/dist/carousel/root/carousel-root.js +134 -12
- package/dist/chat/composer/chat-composer.d.ts +38 -6
- package/dist/chat/composer/chat-composer.js +42 -9
- package/dist/chat/message/chat-message.d.ts +32 -1
- package/dist/chat/message/chat-message.js +25 -9
- package/dist/chat/naming.d.ts +22 -0
- package/dist/chat/naming.js +12 -0
- package/dist/chat/relative-clock.d.ts +39 -0
- package/dist/chat/relative-clock.js +31 -0
- package/dist/chat/root/chat-root.d.ts +36 -0
- package/dist/chat/root/chat-root.js +24 -1
- package/dist/code-block/root/code-block-root.d.ts +8 -1
- package/dist/code-block/root/code-block-root.js +5 -5
- package/dist/copy-button/root/copy-button-root.d.ts +21 -1
- package/dist/copy-button/root/copy-button-root.js +2 -2
- package/dist/data-table/root/data-table-root.d.ts +150 -2
- package/dist/data-table/root/data-table-root.js +303 -29
- package/dist/data-table/tree.d.ts +40 -0
- package/dist/data-table/tree.js +55 -0
- package/dist/description-list/item/description-list-item.d.ts +17 -2
- package/dist/description-list/item/description-list-item.js +15 -2
- package/dist/description-list/root/description-list-root.d.ts +27 -1
- package/dist/description-list/root/description-list-root.js +26 -1
- package/dist/drilldown/item/drilldown-item.d.ts +11 -6
- package/dist/drilldown/item/drilldown-item.js +8 -5
- package/dist/drilldown/root/drilldown-root.d.ts +11 -0
- package/dist/drilldown/root/drilldown-root.js +8 -3
- package/dist/element-events.generated.js +53 -8
- package/dist/filter-input/menu/filter-menu.d.ts +3 -0
- package/dist/filter-input/menu/filter-menu.js +8 -4
- package/dist/image/root/image-root.js +9 -1
- package/dist/input/root/input-root.d.ts +1 -1
- package/dist/input/root/input-root.js +2 -2
- package/dist/list/item/list-item.d.ts +68 -1
- package/dist/list/item/list-item.js +66 -4
- package/dist/list/numbering.d.ts +14 -0
- package/dist/list/numbering.js +8 -0
- package/dist/list/root/list-root.d.ts +106 -9
- package/dist/list/root/list-root.js +189 -4
- package/dist/list/selection.d.ts +19 -0
- package/dist/list/selection.js +21 -0
- package/dist/listbox/root/listbox-root.js +1 -2
- package/dist/map/root/map-root.d.ts +6 -2
- package/dist/map/root/map-root.js +5 -2
- package/dist/megamenu/root/megamenu-root.d.ts +21 -0
- package/dist/megamenu/root/megamenu-root.js +16 -2
- package/dist/menu/index.d.ts +1 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/item/menu-item.d.ts +38 -11
- package/dist/menu/item/menu-item.js +33 -1
- package/dist/menu/root/menu-root.d.ts +25 -1
- package/dist/menu/root/menu-root.js +63 -6
- package/dist/menu/section/menu-section.d.ts +55 -0
- package/dist/menu/section/menu-section.js +60 -0
- package/dist/navigation/root/navigation-root.d.ts +16 -1
- package/dist/navigation/root/navigation-root.js +27 -1
- package/dist/notifications/root/notifications-root.d.ts +18 -0
- package/dist/notifications/root/notifications-root.js +17 -1
- package/dist/object-inspector/root/object-inspector-root.d.ts +97 -16
- package/dist/object-inspector/root/object-inspector-root.js +179 -79
- package/dist/object-inspector/rows.d.ts +57 -0
- package/dist/object-inspector/rows.js +86 -0
- package/dist/outline/levels.d.ts +31 -0
- package/dist/outline/levels.js +23 -0
- package/dist/outline/root/outline-root.d.ts +68 -3
- package/dist/outline/root/outline-root.js +73 -8
- package/dist/pagination/size/pagination-size.d.ts +11 -2
- package/dist/pagination/size/pagination-size.js +19 -4
- package/dist/radio/group/radio-group.d.ts +4 -10
- package/dist/radio/group/radio-group.js +5 -10
- package/dist/rating/root/rating-root.d.ts +1 -1
- package/dist/rating/root/rating-root.js +2 -2
- package/dist/scroll-area/root/scroll-area-root.d.ts +113 -0
- package/dist/scroll-area/root/scroll-area-root.js +218 -3
- package/dist/scroll-area/scrollbar.d.ts +65 -0
- package/dist/scroll-area/scrollbar.js +24 -0
- package/dist/select/root/select-root.js +1 -1
- package/dist/splitter/root/splitter-root.d.ts +13 -0
- package/dist/splitter/root/splitter-root.js +20 -2
- package/dist/splitter/snap.d.ts +9 -0
- package/dist/splitter/snap.js +12 -0
- package/dist/steps/reach.d.ts +15 -0
- package/dist/steps/reach.js +12 -0
- package/dist/steps/root/steps-root.d.ts +30 -0
- package/dist/steps/root/steps-root.js +53 -0
- package/dist/steps/step/step.d.ts +38 -2
- package/dist/steps/step/step.js +28 -6
- package/dist/table/column/table-column.d.ts +11 -0
- package/dist/table/column/table-column.js +6 -1
- package/dist/table/root/table-root.d.ts +101 -0
- package/dist/table/root/table-root.js +166 -5
- package/dist/table/row/table-row.d.ts +47 -1
- package/dist/table/row/table-row.js +39 -2
- package/dist/tabs/panel/tab-panel.d.ts +9 -5
- package/dist/tabs/panel/tab-panel.js +3 -4
- package/dist/tabs/root/tabs-root.d.ts +25 -1
- package/dist/tabs/root/tabs-root.js +21 -3
- package/dist/tabs/tab/tab.d.ts +36 -4
- package/dist/tabs/tab/tab.js +46 -3
- package/dist/timeline/group/timeline-group.d.ts +46 -0
- package/dist/timeline/group/timeline-group.js +37 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/index.js +1 -0
- package/dist/timeline/root/timeline-root.d.ts +10 -3
- package/dist/toast/item/toast-item.d.ts +10 -17
- package/dist/toast/item/toast-item.js +15 -36
- package/dist/toolbar/root/toolbar-root.d.ts +13 -0
- package/dist/toolbar/root/toolbar-root.js +15 -5
- package/dist/tree/item/tree-item.d.ts +54 -1
- package/dist/tree/item/tree-item.js +89 -20
- package/dist/tree/root/tree-root.d.ts +37 -0
- package/dist/tree/root/tree-root.js +51 -6
- package/dist/tree/selection.d.ts +24 -0
- package/dist/tree/selection.js +26 -0
- package/dist/video/media-events.d.ts +49 -0
- package/dist/video/media-events.js +39 -0
- package/dist/video/root/video-root.d.ts +99 -13
- package/dist/video/root/video-root.js +84 -47
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +3 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/order.d.ts +41 -0
- package/dist/video-playlist/order.js +34 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +70 -2
- package/dist/video-playlist/root/video-playlist-root.js +60 -16
- package/dist/virtual-list/controls.d.ts +4 -0
- package/dist/virtual-list/controls.js +30 -0
- package/dist/virtual-list/fill.d.ts +30 -0
- package/dist/virtual-list/fill.js +39 -0
- package/dist/virtual-list/keys.d.ts +15 -0
- package/dist/virtual-list/keys.js +24 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +155 -23
- package/dist/virtual-list/root/virtual-list-root.js +175 -34
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +3778 -801
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +782 -215
- package/dist/listbox/range.d.ts +0 -17
- package/dist/listbox/range.js +0 -5
|
@@ -4,9 +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 { AriaForwardController, customElement, fillTemplate, HelixElement, HelixSortEvent, MixinCollection, requestChange, splitValues, } from '@fusion.dev/helix-core';
|
|
8
|
-
import {
|
|
7
|
+
import { AriaForwardController, commaList, customElement, fillTemplate, HelixElement, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, MixinCollection, reflectElements, requestChange, splitValues, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
import { html } from 'lit/static-html.js';
|
|
11
|
+
import '../../checkbox/index.js';
|
|
10
12
|
import { cycle, format, parse, sort } from '../../data-table/root/order.js';
|
|
11
13
|
import { edgeOf } from '../column/table-column.js';
|
|
12
14
|
const tracksOf = (list, wanted) => {
|
|
@@ -47,17 +49,61 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
47
49
|
super(...arguments);
|
|
48
50
|
this.ascendingLabel = 'ascending';
|
|
49
51
|
this.columns = '';
|
|
52
|
+
this.defaultSelected = '';
|
|
50
53
|
this.defaultSort = '';
|
|
51
54
|
this.descendingLabel = 'descending';
|
|
52
55
|
this.label = '';
|
|
56
|
+
this.selectable = false;
|
|
57
|
+
this.selectAllLabel = 'Select every row';
|
|
58
|
+
this.selectedLabel = '{count} selected';
|
|
59
|
+
this.selectRowLabel = 'Select {row}';
|
|
53
60
|
this.sortedLabel = 'Sorted by {column}, {order}';
|
|
54
61
|
this.unsortedLabel = 'Not sorted';
|
|
55
62
|
this.sortState = undefined;
|
|
63
|
+
this.selectedState = undefined;
|
|
64
|
+
this.headed = false;
|
|
56
65
|
this.aria = new AriaForwardController(this, {
|
|
57
66
|
label: true,
|
|
58
67
|
target: () => this.partNamed('table'),
|
|
59
68
|
});
|
|
60
69
|
this.heardSort = undefined;
|
|
70
|
+
this.heardSortBefore = undefined;
|
|
71
|
+
this.heardSelected = undefined;
|
|
72
|
+
this.handleToggle = (event) => {
|
|
73
|
+
const origin = event.composedPath()[0];
|
|
74
|
+
if (!(origin instanceof Element) || origin.getAttribute('part') !== 'checkbox') {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const root = origin.getRootNode();
|
|
78
|
+
const keys = this.chosen;
|
|
79
|
+
if (root === this.renderRoot) {
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
const every = this.keyed.map(({ key }) => key);
|
|
82
|
+
const all = every.length > 0 && every.every((key) => keys.has(key));
|
|
83
|
+
for (const key of every) {
|
|
84
|
+
if (all) {
|
|
85
|
+
keys.delete(key);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
keys.add(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.requestSelected(keys);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const found = this.keyed.find(({ row }) => row.shadowRoot === root);
|
|
95
|
+
if (!found) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
if (event.detail.checked) {
|
|
100
|
+
keys.add(found.key);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
keys.delete(found.key);
|
|
104
|
+
}
|
|
105
|
+
this.requestSelected(keys);
|
|
106
|
+
};
|
|
61
107
|
this.handleHeadClick = (event) => {
|
|
62
108
|
const path = event.composedPath();
|
|
63
109
|
if (!path.some((node) => node instanceof Element && node.getAttribute('part') === 'sort')) {
|
|
@@ -76,6 +122,14 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
76
122
|
this.alignment = undefined;
|
|
77
123
|
this.aligned = '';
|
|
78
124
|
}
|
|
125
|
+
get selected() {
|
|
126
|
+
return this.selectedState ?? this.defaultSelected;
|
|
127
|
+
}
|
|
128
|
+
set selected(next) {
|
|
129
|
+
const previous = this.selected;
|
|
130
|
+
this.selectedState = next;
|
|
131
|
+
this.requestUpdate('selected', previous);
|
|
132
|
+
}
|
|
79
133
|
get sort() {
|
|
80
134
|
return this.sortState ?? this.defaultSort;
|
|
81
135
|
}
|
|
@@ -90,6 +144,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
90
144
|
const previous = this.sort;
|
|
91
145
|
this.sortState = value;
|
|
92
146
|
this.requestUpdate('sort', previous);
|
|
147
|
+
this.dispatchEvent(new HelixSortedEvent({ value }));
|
|
93
148
|
},
|
|
94
149
|
event: (value) => new HelixSortEvent({ value }),
|
|
95
150
|
host: this,
|
|
@@ -133,8 +188,57 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
133
188
|
: this.unsortedLabel;
|
|
134
189
|
}
|
|
135
190
|
this.heardSort = current;
|
|
191
|
+
const selected = this.selectable ? this.selected : '';
|
|
192
|
+
if (this.hasUpdated && current === this.heardSortBefore && selected !== this.heardSelected) {
|
|
193
|
+
said = fillTemplate(this.selectedLabel, { count: this.chosen.size });
|
|
194
|
+
}
|
|
195
|
+
this.heardSortBefore = current;
|
|
196
|
+
this.heardSelected = selected;
|
|
136
197
|
return said;
|
|
137
198
|
}
|
|
199
|
+
get keyed() {
|
|
200
|
+
return this.slotted.map((row, index) => ({
|
|
201
|
+
key: row.value || String(index),
|
|
202
|
+
row: row,
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
get chosen() {
|
|
206
|
+
return new Set(commaList(this.selected));
|
|
207
|
+
}
|
|
208
|
+
requestSelected(keys) {
|
|
209
|
+
return requestChange({
|
|
210
|
+
apply: (value) => {
|
|
211
|
+
const previous = this.selected;
|
|
212
|
+
this.selectedState = value;
|
|
213
|
+
this.requestUpdate('selected', previous);
|
|
214
|
+
this.dispatchEvent(new HelixSelectedEvent({ value }));
|
|
215
|
+
},
|
|
216
|
+
event: (value) => new HelixSelectEvent({ value }),
|
|
217
|
+
host: this,
|
|
218
|
+
next: [...keys].join(','),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
markSelected() {
|
|
222
|
+
const keys = this.chosen;
|
|
223
|
+
for (const { key, row } of this.keyed) {
|
|
224
|
+
if (!row.isTableRow) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
const label = fillTemplate(this.selectRowLabel, { row: textOf(row.children[0]) || key });
|
|
228
|
+
whenHydrated(row, () => {
|
|
229
|
+
row.selectable = this.selectable;
|
|
230
|
+
row.selected = keys.has(key);
|
|
231
|
+
row.selectLabel = label;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
nameByHeading() {
|
|
236
|
+
const named = this.hasAttribute('aria-label') || this.hasAttribute('aria-labelledby');
|
|
237
|
+
this.headed = reflectElements(this.partNamed('table'), 'ariaLabelledByElements', named ? [] : this.headings, this.headed);
|
|
238
|
+
}
|
|
239
|
+
get headings() {
|
|
240
|
+
return [...(this.children ?? [])].filter((child) => child.getAttribute('slot') === 'heading');
|
|
241
|
+
}
|
|
138
242
|
markSorted() {
|
|
139
243
|
const current = parse(this.sort);
|
|
140
244
|
for (const column of this.tableColumns) {
|
|
@@ -150,6 +254,10 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
150
254
|
return this.knownChildren.filter((child) => 'isTableColumn' in child && child.isTableColumn === true);
|
|
151
255
|
}
|
|
152
256
|
get template() {
|
|
257
|
+
const tracks = this.tracks;
|
|
258
|
+
return this.selectable && tracks ? `max-content ${tracks}` : tracks;
|
|
259
|
+
}
|
|
260
|
+
get tracks() {
|
|
153
261
|
const declared = this.tableColumns;
|
|
154
262
|
if (declared.length === 0) {
|
|
155
263
|
return this.columns;
|
|
@@ -187,17 +295,23 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
187
295
|
: 'max-content';
|
|
188
296
|
});
|
|
189
297
|
}
|
|
298
|
+
firstUpdated(changed) {
|
|
299
|
+
super.firstUpdated(changed);
|
|
300
|
+
this.finishHydration();
|
|
301
|
+
}
|
|
190
302
|
connectedCallback() {
|
|
191
303
|
super.connectedCallback();
|
|
192
304
|
this.watcher = new MutationObserver(() => this.requestUpdate());
|
|
193
305
|
this.watcher.observe(this, { characterData: true, childList: true, subtree: true });
|
|
194
306
|
this.addEventListener('click', this.handleHeadClick);
|
|
307
|
+
this.addEventListener('helix-before-toggle', this.handleToggle);
|
|
195
308
|
}
|
|
196
309
|
disconnectedCallback() {
|
|
197
310
|
super.disconnectedCallback();
|
|
198
311
|
this.watcher?.disconnect();
|
|
199
312
|
this.watcher = undefined;
|
|
200
313
|
this.removeEventListener('click', this.handleHeadClick);
|
|
314
|
+
this.removeEventListener('helix-before-toggle', this.handleToggle);
|
|
201
315
|
}
|
|
202
316
|
static { this.shadowRootOptions = {
|
|
203
317
|
...HelixElement.shadowRootOptions,
|
|
@@ -205,7 +319,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
205
319
|
}; }
|
|
206
320
|
get slotted() {
|
|
207
321
|
const columns = new Set(this.tableColumns);
|
|
208
|
-
return [...(this.children ?? [])].filter((child) => !columns.has(child));
|
|
322
|
+
return [...(this.children ?? [])].filter((child) => !columns.has(child) && child.getAttribute('slot') !== 'heading');
|
|
209
323
|
}
|
|
210
324
|
assign() {
|
|
211
325
|
if (this.assignsByName) {
|
|
@@ -221,6 +335,9 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
221
335
|
}
|
|
222
336
|
head.assign(...this.tableColumns);
|
|
223
337
|
body.assign(...this.arrangedRows);
|
|
338
|
+
this.renderRoot
|
|
339
|
+
?.querySelector('slot[name="heading"]')
|
|
340
|
+
?.assign(...this.headings);
|
|
224
341
|
}
|
|
225
342
|
alignCells() {
|
|
226
343
|
if (typeof CSSStyleSheet === 'undefined' || !('replaceSync' in CSSStyleSheet.prototype)) {
|
|
@@ -252,17 +369,40 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
252
369
|
this.assign();
|
|
253
370
|
this.alignCells();
|
|
254
371
|
this.markSorted();
|
|
372
|
+
this.markSelected();
|
|
373
|
+
this.nameByHeading();
|
|
374
|
+
}
|
|
375
|
+
renderSelectAll() {
|
|
376
|
+
if (!this.selectable) {
|
|
377
|
+
return nothing;
|
|
378
|
+
}
|
|
379
|
+
const every = this.childrenKnown ? this.keyed.map(({ key }) => key) : [];
|
|
380
|
+
const keys = this.chosen;
|
|
381
|
+
const count = every.filter((key) => keys.has(key)).length;
|
|
382
|
+
const checkbox = this.tag('checkbox');
|
|
383
|
+
return html `<span part="select-all" role="columnheader"
|
|
384
|
+
><${checkbox}
|
|
385
|
+
part="checkbox"
|
|
386
|
+
exportparts="box: checkbox-box, control: checkbox-control, feedback: checkbox-feedback,
|
|
387
|
+
field: checkbox-field, hint: checkbox-hint, label: checkbox-label, mark: checkbox-mark,
|
|
388
|
+
mark-checked: checkbox-mark-checked, mark-dash: checkbox-mark-dash,
|
|
389
|
+
mark-indeterminate: checkbox-mark-indeterminate"
|
|
390
|
+
aria-label=${this.selectAllLabel}
|
|
391
|
+
.checked=${every.length > 0 && count === every.length}
|
|
392
|
+
.indeterminate=${count > 0 && count < every.length}
|
|
393
|
+
></${checkbox}
|
|
394
|
+
></span>`;
|
|
255
395
|
}
|
|
256
396
|
render() {
|
|
257
397
|
const template = this.template;
|
|
258
|
-
return html `<div
|
|
398
|
+
return html `<slot name="heading"></slot><div
|
|
259
399
|
part="table"
|
|
260
400
|
role="table"
|
|
261
401
|
aria-busy=${this.loading ? 'true' : nothing}
|
|
262
402
|
aria-label=${this.label || 'Table'}
|
|
263
403
|
style=${template ? `--table-template: ${template}` : ''}
|
|
264
404
|
>
|
|
265
|
-
<div part="head" role="row"
|
|
405
|
+
<div part="head" role="row">${this.renderSelectAll()}<slot name="columns"></slot></div>
|
|
266
406
|
<slot
|
|
267
407
|
@slotchange=${(event) => {
|
|
268
408
|
this.countRows(event);
|
|
@@ -279,6 +419,9 @@ __decorate([
|
|
|
279
419
|
__decorate([
|
|
280
420
|
property()
|
|
281
421
|
], HelixHeadlessTable.prototype, "columns", void 0);
|
|
422
|
+
__decorate([
|
|
423
|
+
property({ attribute: 'default-selected' })
|
|
424
|
+
], HelixHeadlessTable.prototype, "defaultSelected", void 0);
|
|
282
425
|
__decorate([
|
|
283
426
|
property({ attribute: 'default-sort' })
|
|
284
427
|
], HelixHeadlessTable.prototype, "defaultSort", void 0);
|
|
@@ -288,6 +431,21 @@ __decorate([
|
|
|
288
431
|
__decorate([
|
|
289
432
|
property()
|
|
290
433
|
], HelixHeadlessTable.prototype, "label", void 0);
|
|
434
|
+
__decorate([
|
|
435
|
+
property({ type: Boolean })
|
|
436
|
+
], HelixHeadlessTable.prototype, "selectable", void 0);
|
|
437
|
+
__decorate([
|
|
438
|
+
property({ attribute: 'select-all-label' })
|
|
439
|
+
], HelixHeadlessTable.prototype, "selectAllLabel", void 0);
|
|
440
|
+
__decorate([
|
|
441
|
+
property()
|
|
442
|
+
], HelixHeadlessTable.prototype, "selected", null);
|
|
443
|
+
__decorate([
|
|
444
|
+
property({ attribute: 'selected-label' })
|
|
445
|
+
], HelixHeadlessTable.prototype, "selectedLabel", void 0);
|
|
446
|
+
__decorate([
|
|
447
|
+
property({ attribute: 'select-row-label' })
|
|
448
|
+
], HelixHeadlessTable.prototype, "selectRowLabel", void 0);
|
|
291
449
|
__decorate([
|
|
292
450
|
property()
|
|
293
451
|
], HelixHeadlessTable.prototype, "sort", null);
|
|
@@ -300,6 +458,9 @@ __decorate([
|
|
|
300
458
|
__decorate([
|
|
301
459
|
state()
|
|
302
460
|
], HelixHeadlessTable.prototype, "sortState", void 0);
|
|
461
|
+
__decorate([
|
|
462
|
+
state()
|
|
463
|
+
], HelixHeadlessTable.prototype, "selectedState", void 0);
|
|
303
464
|
HelixHeadlessTable = __decorate([
|
|
304
465
|
customElement('helix-headless-table')
|
|
305
466
|
], HelixHeadlessTable);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
import '../../checkbox/index.js';
|
|
3
4
|
/**
|
|
4
5
|
* @summary One row of a table.
|
|
5
6
|
*
|
|
@@ -9,12 +10,31 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
9
10
|
* across rows. The row still exists as an element, so you can style it, hide
|
|
10
11
|
* it, or make it interactive.
|
|
11
12
|
*
|
|
13
|
+
* In a `selectable` table the row draws a checkbox cell before its own cells,
|
|
14
|
+
* and `value` is the key the table's `selected` lists it by.
|
|
15
|
+
*
|
|
12
16
|
* @since 0.1.0
|
|
13
17
|
* @status stable
|
|
14
18
|
* @aliases Row, TableRow
|
|
15
19
|
* @documentation https://fusion.dev/helix/components/table
|
|
16
20
|
*
|
|
17
21
|
* @slot - The row's cells.
|
|
22
|
+
*
|
|
23
|
+
* @csspart checkbox - The row's checkbox, in a `selectable` table.
|
|
24
|
+
* @csspart checkbox-box - The box drawn for the checkbox's input.
|
|
25
|
+
* @csspart checkbox-control - The checkbox's input.
|
|
26
|
+
* @csspart checkbox-feedback - Forwarded from the checkbox. Not shown in the table.
|
|
27
|
+
* @csspart checkbox-field - The row that holds the checkbox's box.
|
|
28
|
+
* @csspart checkbox-hint - Forwarded from the checkbox. Not shown in the table.
|
|
29
|
+
* @csspart checkbox-label - Forwarded from the checkbox. The label is read by screen readers only.
|
|
30
|
+
* @csspart checkbox-mark - The check mark.
|
|
31
|
+
* @csspart checkbox-mark-checked - Added to `checkbox-mark` while its box is checked.
|
|
32
|
+
* @csspart checkbox-mark-dash - Added to `checkbox-mark` while it draws the dash, which it keeps until its box is checked.
|
|
33
|
+
* @csspart checkbox-mark-indeterminate - Added to `checkbox-mark` while only some rows are selected.
|
|
34
|
+
* @csspart select - The cell that holds the row's checkbox, in a `selectable` table.
|
|
35
|
+
* @csspart select-selected - Added to `select` while the row is selected.
|
|
36
|
+
*
|
|
37
|
+
* @cssstate selected - While the row is selected, in a `selectable` table.
|
|
18
38
|
*/
|
|
19
39
|
export declare class HelixHeadlessTableRow extends HelixElement {
|
|
20
40
|
/**
|
|
@@ -22,6 +42,23 @@ export declare class HelixHeadlessTableRow extends HelixElement {
|
|
|
22
42
|
* finds its columns. Not a consumer's to read or set.
|
|
23
43
|
*/
|
|
24
44
|
readonly isTableRow = true;
|
|
45
|
+
/**
|
|
46
|
+
* The key the table's `selected` lists this row by. Left empty, the row is
|
|
47
|
+
* known by its place among the rows as written.
|
|
48
|
+
*/
|
|
49
|
+
value: string;
|
|
50
|
+
/**
|
|
51
|
+
* @internal Whether the table this row sits in is `selectable`, written by
|
|
52
|
+
* that table. Not a consumer's to set: the selection is the table's.
|
|
53
|
+
*/
|
|
54
|
+
selectable: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* @internal Whether the row is selected, written by the table that owns the
|
|
57
|
+
* selection. Not a consumer's to set: write the table's `selected`.
|
|
58
|
+
*/
|
|
59
|
+
selected: boolean;
|
|
60
|
+
/** @internal The name of the row's checkbox, written by the table. Not a consumer's to set. */
|
|
61
|
+
selectLabel: string;
|
|
25
62
|
/** The table's rules this row holds, so the next ones replace them rather than pile up. */
|
|
26
63
|
private columnRules;
|
|
27
64
|
/**
|
|
@@ -39,6 +76,15 @@ export declare class HelixHeadlessTableRow extends HelixElement {
|
|
|
39
76
|
* upgrades while its row is still being parsed has no value beside it yet.
|
|
40
77
|
*/
|
|
41
78
|
private readonly handleSlotChange;
|
|
79
|
+
/**
|
|
80
|
+
* The checkbox cell, in a `selectable` table.
|
|
81
|
+
*
|
|
82
|
+
* A cell of the row's own, before the consumer's cells, so the table's grid
|
|
83
|
+
* gives it the first track. The table hears its `helix-before-toggle`,
|
|
84
|
+
* refuses it and asks for the new selection, so the box shows only what the
|
|
85
|
+
* table's `selected` says.
|
|
86
|
+
*/
|
|
87
|
+
protected renderSelect(): TemplateResult | typeof nothing;
|
|
42
88
|
protected render(): TemplateResult;
|
|
43
89
|
}
|
|
44
90
|
declare global {
|
|
@@ -5,11 +5,18 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
|
|
8
|
-
import {
|
|
8
|
+
import { nothing } from 'lit';
|
|
9
|
+
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
import { html } from 'lit/static-html.js';
|
|
11
|
+
import '../../checkbox/index.js';
|
|
9
12
|
let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
|
|
10
13
|
constructor() {
|
|
11
14
|
super(...arguments);
|
|
12
15
|
this.isTableRow = true;
|
|
16
|
+
this.value = '';
|
|
17
|
+
this.selectable = false;
|
|
18
|
+
this.selected = false;
|
|
19
|
+
this.selectLabel = '';
|
|
13
20
|
this.columnRules = undefined;
|
|
14
21
|
this.handleSlotChange = () => {
|
|
15
22
|
for (const cell of this.children) {
|
|
@@ -34,11 +41,41 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
|
|
|
34
41
|
willUpdate(changed) {
|
|
35
42
|
super.willUpdate(changed);
|
|
36
43
|
hostAria(this.internals, { role: 'row' });
|
|
44
|
+
this.toggleState('selected', this.selectable && this.selected);
|
|
45
|
+
}
|
|
46
|
+
renderSelect() {
|
|
47
|
+
if (!this.selectable) {
|
|
48
|
+
return nothing;
|
|
49
|
+
}
|
|
50
|
+
const checkbox = this.tag('checkbox');
|
|
51
|
+
return html `<span part="select${this.selected ? ' select-selected' : ''}" role="cell"
|
|
52
|
+
><${checkbox}
|
|
53
|
+
part="checkbox"
|
|
54
|
+
exportparts="box: checkbox-box, control: checkbox-control, feedback: checkbox-feedback,
|
|
55
|
+
field: checkbox-field, hint: checkbox-hint, label: checkbox-label, mark: checkbox-mark,
|
|
56
|
+
mark-checked: checkbox-mark-checked, mark-dash: checkbox-mark-dash,
|
|
57
|
+
mark-indeterminate: checkbox-mark-indeterminate"
|
|
58
|
+
aria-label=${this.selectLabel}
|
|
59
|
+
.checked=${this.selected}
|
|
60
|
+
></${checkbox}
|
|
61
|
+
></span>`;
|
|
37
62
|
}
|
|
38
63
|
render() {
|
|
39
|
-
return html
|
|
64
|
+
return html `${this.renderSelect()}<slot @slotchange=${this.handleSlotChange}></slot>`;
|
|
40
65
|
}
|
|
41
66
|
};
|
|
67
|
+
__decorate([
|
|
68
|
+
property()
|
|
69
|
+
], HelixHeadlessTableRow.prototype, "value", void 0);
|
|
70
|
+
__decorate([
|
|
71
|
+
state()
|
|
72
|
+
], HelixHeadlessTableRow.prototype, "selectable", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
state()
|
|
75
|
+
], HelixHeadlessTableRow.prototype, "selected", void 0);
|
|
76
|
+
__decorate([
|
|
77
|
+
state()
|
|
78
|
+
], HelixHeadlessTableRow.prototype, "selectLabel", void 0);
|
|
42
79
|
HelixHeadlessTableRow = __decorate([
|
|
43
80
|
customElement('helix-headless-table-row')
|
|
44
81
|
], HelixHeadlessTableRow);
|
|
@@ -8,6 +8,11 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
8
8
|
* still there when the person comes back, and the content of every panel is in
|
|
9
9
|
* the server-rendered markup for crawlers, whichever tab is open.
|
|
10
10
|
*
|
|
11
|
+
* The host is the `tabpanel` while its tab is selected, through
|
|
12
|
+
* `ElementInternals`, so the tab's `aria-controls` can reach it from the tab's
|
|
13
|
+
* shadow root. The box inside takes the focus, for a panel with nothing
|
|
14
|
+
* focusable in it.
|
|
15
|
+
*
|
|
11
16
|
* @since 0.1.0
|
|
12
17
|
* @status stable
|
|
13
18
|
* @aliases TabPanel
|
|
@@ -15,7 +20,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
15
20
|
*
|
|
16
21
|
* @slot - The panel's content.
|
|
17
22
|
*
|
|
18
|
-
* @csspart panel - The panel container.
|
|
23
|
+
* @csspart panel - The panel container, which takes the focus.
|
|
19
24
|
*
|
|
20
25
|
* @cssstate selected - While its tab is the one selected.
|
|
21
26
|
*/
|
|
@@ -28,10 +33,9 @@ export declare class HelixHeadlessTabPanel extends HelixElement {
|
|
|
28
33
|
* writes: the tab already says it.
|
|
29
34
|
*
|
|
30
35
|
* A string and not a reference: an IDREF resolves only in the tree it is
|
|
31
|
-
* written in, and
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* anyway.
|
|
36
|
+
* written in, and the tab's control is inside the tab's shadow root, which no
|
|
37
|
+
* reference from the light DOM can reach. `aria-label` on a `tabpanel` is how
|
|
38
|
+
* the pattern names one anyway.
|
|
35
39
|
*/
|
|
36
40
|
label: string;
|
|
37
41
|
/**
|
|
@@ -4,8 +4,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, HelixElement } from '@fusion.dev/helix-core';
|
|
8
|
-
import { html
|
|
7
|
+
import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessTabPanel = class HelixHeadlessTabPanel extends HelixElement {
|
|
11
11
|
constructor() {
|
|
@@ -17,12 +17,11 @@ let HelixHeadlessTabPanel = class HelixHeadlessTabPanel extends HelixElement {
|
|
|
17
17
|
willUpdate(changed) {
|
|
18
18
|
super.willUpdate(changed);
|
|
19
19
|
this.toggleState('selected', this.selected);
|
|
20
|
+
hostAria(this.internals, { label: this.label, role: this.selected ? 'tabpanel' : '' });
|
|
20
21
|
}
|
|
21
22
|
render() {
|
|
22
23
|
return html `<div
|
|
23
24
|
part="panel"
|
|
24
|
-
role="tabpanel"
|
|
25
|
-
aria-label=${this.label || nothing}
|
|
26
25
|
?hidden=${!this.selected}
|
|
27
26
|
tabindex="0"
|
|
28
27
|
>
|
|
@@ -16,6 +16,18 @@ declare const HelixHeadlessTabs_base: (new (...args: any[]) => import("@fusion.d
|
|
|
16
16
|
* panel is cheap. Set `manual` when showing a panel is expensive, so focus can
|
|
17
17
|
* move without selecting.
|
|
18
18
|
*
|
|
19
|
+
* `orientation="vertical"` sets the tabs in a column beside the panels, and the
|
|
20
|
+
* tab list says `aria-orientation="vertical"`. The arrow keys of both axes move
|
|
21
|
+
* between tabs either way.
|
|
22
|
+
*
|
|
23
|
+
* A tab with an `href` is a link, for tabs that are pages of a site. Pressing
|
|
24
|
+
* it follows the link, and the arrow keys move focus without choosing, so
|
|
25
|
+
* arrowing past a tab never leaves the page. Mark the tab of the page you are
|
|
26
|
+
* on with `selected`, or set `active` to its value.
|
|
27
|
+
*
|
|
28
|
+
* Each tab says which panel it controls through `aria-controls`, set as an
|
|
29
|
+
* element reference to the panel's host, where the engine has reflection.
|
|
30
|
+
*
|
|
19
31
|
* @since 0.1.0
|
|
20
32
|
* @status stable
|
|
21
33
|
* @category navigation
|
|
@@ -29,7 +41,10 @@ declare const HelixHeadlessTabs_base: (new (...args: any[]) => import("@fusion.d
|
|
|
29
41
|
* @event {HelixBeforeActivateEvent} helix-before-activate - Fired before the active tab changes, and cancelable. Canceling it is the only way to block a change.
|
|
30
42
|
* @event {HelixSelectEvent} helix-select - Fired when a tab is chosen. The tab sends it and the root handles it, so you can listen on the root. Cancelable: canceling it stops the change and leaves the decision to you.
|
|
31
43
|
*
|
|
32
|
-
* @csspart indicator - The marker that moves to the selected tab.
|
|
44
|
+
* @csspart indicator - The marker that moves to the selected tab. It carries the selected tab's
|
|
45
|
+
* place and size as `--indicator-x`, `--indicator-y`, `--indicator-inline-size` and
|
|
46
|
+
* `--indicator-block-size`, and `data-placed` once it has been placed, for a mark you draw
|
|
47
|
+
* and animate yourself.
|
|
33
48
|
* @csspart panels - The panel container.
|
|
34
49
|
* @csspart tabs - The tab list.
|
|
35
50
|
*/
|
|
@@ -54,6 +69,13 @@ export declare class HelixHeadlessTabs extends HelixHeadlessTabs_base {
|
|
|
54
69
|
* panels on the way.
|
|
55
70
|
*/
|
|
56
71
|
manual: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* The direction the tabs run. `vertical` sets them in a column beside the
|
|
74
|
+
* panels and tells a screen reader the list is vertical.
|
|
75
|
+
*
|
|
76
|
+
* Optional, so the resting row writes no attribute onto the host.
|
|
77
|
+
*/
|
|
78
|
+
orientation?: 'horizontal' | 'vertical';
|
|
57
79
|
/**
|
|
58
80
|
* How the row of tabs is drawn.
|
|
59
81
|
*
|
|
@@ -80,6 +102,8 @@ export declare class HelixHeadlessTabs extends HelixHeadlessTabs_base {
|
|
|
80
102
|
*/
|
|
81
103
|
variant?: 'segmented' | 'underlined';
|
|
82
104
|
private get tabs();
|
|
105
|
+
/** Whether any tab is a link, so arriving on one chooses nothing. */
|
|
106
|
+
private get linked();
|
|
83
107
|
private get panels();
|
|
84
108
|
private readonly handleSelection;
|
|
85
109
|
/** Pushes the current value down to whichever tab and panel own it. */
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { AriaForwardController, customElement, HelixElement, IndicatorController, KeyboardNavigationController, MixinControllerActive, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
-
import { html } from 'lit';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessTabPanel } from '../panel/tab-panel.js';
|
|
11
11
|
import { HelixHeadlessTab } from '../tab/tab.js';
|
|
@@ -15,7 +15,7 @@ let HelixHeadlessTabs = class HelixHeadlessTabs extends MixinControllerActive(He
|
|
|
15
15
|
this.keys = new KeyboardNavigationController(this, {
|
|
16
16
|
items: () => this.tabs,
|
|
17
17
|
origin: 'focus',
|
|
18
|
-
selects: () => !this.manual,
|
|
18
|
+
selects: () => !this.manual && !this.linked,
|
|
19
19
|
});
|
|
20
20
|
this.indicator = new IndicatorController(this, {
|
|
21
21
|
active: () => this.tabs.find((tab) => tab.selected),
|
|
@@ -43,6 +43,9 @@ let HelixHeadlessTabs = class HelixHeadlessTabs extends MixinControllerActive(He
|
|
|
43
43
|
get tabs() {
|
|
44
44
|
return [...this.children].filter((child) => child instanceof HelixHeadlessTab);
|
|
45
45
|
}
|
|
46
|
+
get linked() {
|
|
47
|
+
return this.tabs.some((tab) => (tab.href ?? '') !== '');
|
|
48
|
+
}
|
|
46
49
|
get panels() {
|
|
47
50
|
return [...this.children].filter((child) => child instanceof HelixHeadlessTabPanel);
|
|
48
51
|
}
|
|
@@ -57,6 +60,13 @@ let HelixHeadlessTabs = class HelixHeadlessTabs extends MixinControllerActive(He
|
|
|
57
60
|
});
|
|
58
61
|
}
|
|
59
62
|
const names = new Map(tabs.map((tab) => [tab.value, (tab.textContent ?? '').trim()]));
|
|
63
|
+
const panels = new Map(this.panels.map((panel) => [panel.value, panel]));
|
|
64
|
+
for (const tab of tabs) {
|
|
65
|
+
const panel = panels.get(tab.value);
|
|
66
|
+
whenHydrated(tab, () => {
|
|
67
|
+
tab.controls = panel;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
60
70
|
for (const panel of this.panels) {
|
|
61
71
|
const selected = panel.value === value;
|
|
62
72
|
const label = names.get(panel.value) ?? '';
|
|
@@ -88,7 +98,12 @@ let HelixHeadlessTabs = class HelixHeadlessTabs extends MixinControllerActive(He
|
|
|
88
98
|
this.indicator.place();
|
|
89
99
|
}
|
|
90
100
|
render() {
|
|
91
|
-
return html `<div
|
|
101
|
+
return html `<div
|
|
102
|
+
part="tabs"
|
|
103
|
+
role="tablist"
|
|
104
|
+
aria-label=${this.label}
|
|
105
|
+
aria-orientation=${this.orientation === 'vertical' ? 'vertical' : nothing}
|
|
106
|
+
>
|
|
92
107
|
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
93
108
|
<span part="indicator" aria-hidden="true"></span>
|
|
94
109
|
</div>
|
|
@@ -101,6 +116,9 @@ __decorate([
|
|
|
101
116
|
__decorate([
|
|
102
117
|
property({ reflect: true, type: Boolean })
|
|
103
118
|
], HelixHeadlessTabs.prototype, "manual", void 0);
|
|
119
|
+
__decorate([
|
|
120
|
+
property({ reflect: true })
|
|
121
|
+
], HelixHeadlessTabs.prototype, "orientation", void 0);
|
|
104
122
|
__decorate([
|
|
105
123
|
property({ reflect: true })
|
|
106
124
|
], HelixHeadlessTabs.prototype, "variant", void 0);
|
package/dist/tabs/tab/tab.d.ts
CHANGED
|
@@ -7,10 +7,10 @@ declare const HelixHeadlessTab_base: (new (...args: any[]) => import("@fusion.de
|
|
|
7
7
|
* @description
|
|
8
8
|
* A tab is an element, because it manages selection and its own tab stop.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* With an `href`, the tab is a link: `role="tab"` on an `<a>`, which a press,
|
|
11
|
+
* Enter and the browser's own link gestures follow. `helix-select` is sent
|
|
12
|
+
* first, and canceling it keeps the browser from following, so a client-side
|
|
13
|
+
* router follows it instead.
|
|
14
14
|
*
|
|
15
15
|
* @since 0.1.0
|
|
16
16
|
* @status stable
|
|
@@ -27,6 +27,38 @@ declare const HelixHeadlessTab_base: (new (...args: any[]) => import("@fusion.de
|
|
|
27
27
|
*/
|
|
28
28
|
export declare class HelixHeadlessTab extends HelixHeadlessTab_base {
|
|
29
29
|
protected itemPart: string;
|
|
30
|
+
/**
|
|
31
|
+
* @internal The panel this tab shows, written by the tab set. A property,
|
|
32
|
+
* because it is an element, and it reaches the tab's `aria-controls` as an
|
|
33
|
+
* element reference: the panel is in the light DOM, which a reference from
|
|
34
|
+
* inside this shadow root can reach.
|
|
35
|
+
*/
|
|
36
|
+
controls: Element | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* The URL the tab links to. Setting it renders the tab as a link, for a set
|
|
39
|
+
* of tabs that are pages of a site.
|
|
40
|
+
*/
|
|
41
|
+
href?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The link's `rel`, for a tab with an `href`.
|
|
44
|
+
*/
|
|
45
|
+
rel?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Where the link opens, such as `_blank`, for a tab with an `href`.
|
|
48
|
+
*/
|
|
49
|
+
target?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Chooses the tab before the browser follows its link, and keeps the browser
|
|
52
|
+
* from following where the choice was refused. A press with a modifier, or
|
|
53
|
+
* with a button other than the main one, opens the link where the browser
|
|
54
|
+
* opens it and chooses nothing here.
|
|
55
|
+
*/
|
|
56
|
+
private readonly handleLinkClick;
|
|
57
|
+
/**
|
|
58
|
+
* Points the control's `aria-controls` at the panel, where the engine can.
|
|
59
|
+
* The control is this tab's own, so the reference is always its to clear.
|
|
60
|
+
*/
|
|
61
|
+
protected updated(changed: PropertyValues): void;
|
|
30
62
|
/**
|
|
31
63
|
* Asks for the render that follows a hydration, so the stop stops being every
|
|
32
64
|
* tab's.
|