@fusion.dev/helix-headless 0.145.0 → 0.146.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 +7373 -3849
- package/dist/accordion/item/accordion-item.d.ts +14 -0
- package/dist/accordion/item/accordion-item.js +16 -6
- package/dist/accordion/root/accordion-root.d.ts +8 -5
- package/dist/announcement/root/announcement-root.d.ts +3 -2
- package/dist/announcement/root/announcement-root.js +3 -1
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +25 -3
- package/dist/chat/root/chat-root.js +22 -5
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -1
- package/dist/code-block/root/code-block-root.js +58 -3
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +5 -0
- package/dist/copy-button/root/copy-button-root.js +10 -3
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +20 -52
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +21 -3
- package/dist/element-events.generated.js +31 -5
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +5 -1
- package/dist/image/root/image-root.js +1 -1
- package/dist/input/root/input-root.d.ts +12 -2
- package/dist/input/root/input-root.js +11 -2
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +62 -13
- package/dist/list/root/list-root.js +70 -13
- package/dist/list/selection.d.ts +37 -7
- package/dist/list/selection.js +16 -7
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -3
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/megamenu/root/megamenu-root.d.ts +51 -10
- package/dist/megamenu/root/megamenu-root.js +76 -5
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +47 -23
- package/dist/menu/root/menu-root.d.ts +14 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +10 -3
- package/dist/notifications/root/notifications-root.js +19 -7
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
- package/dist/object-inspector/root/object-inspector-root.js +117 -76
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/root/outline-root.d.ts +18 -0
- package/dist/outline/root/outline-root.js +23 -5
- package/dist/pagination/size/pagination-size.d.ts +1 -0
- package/dist/pagination/size/pagination-size.js +1 -1
- package/dist/pin-input/code.d.ts +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +9 -4
- package/dist/rating/root/rating-root.js +31 -7
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -0
- package/dist/scroll-area/scrollbar.js +9 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +7 -12
- package/dist/splitter/root/splitter-root.js +209 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +49 -3
- package/dist/steps/root/steps-root.js +44 -5
- package/dist/steps/step/step.d.ts +7 -0
- package/dist/steps/step/step.js +7 -2
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +0 -10
- package/dist/table/column/table-column.js +3 -19
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +2 -13
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +12 -0
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +14 -1
- package/dist/toast/item/toast-item.js +22 -5
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/video-root.d.ts +18 -5
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
- package/dist/virtual-list/fill.d.ts +0 -8
- package/dist/virtual-list/fill.js +1 -17
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
- package/dist/virtual-list/root/virtual-list-root.js +183 -40
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +4577 -835
- package/types/vue.d.ts +926 -168
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -5,18 +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
|
var HelixHeadlessDataTable_1;
|
|
8
|
-
import { countLabel, customElement, deepActiveElement, deepContains, fillTemplate, formatNumbers, HelixActivateEvent, HelixElement, HelixExpandEvent, HelixFilterEvent, HelixFilteredEvent, HelixLoadMoreEvent, HelixNavigateEvent, HelixReorderEvent, HelixReorderedEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, hostAria, inlineStep, isRtl, MixinCollection, markRegion, rangeAdd, reportRuntime, requestChange, Typeahead, typesCharacter, VirtualizeController, writtenList, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { arranged, commaList, countLabel, customElement, cycle, deepActiveElement, deepContains, fillTemplate, format, formatNumbers, HelixActivateEvent, HelixElement, HelixExpandEvent, HelixFilterEvent, HelixFilteredEvent, HelixLoadMoreEvent, HelixNavigateEvent, HelixReorderEvent, HelixReorderedEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, hostAria, inlineStep, isRtl, MixinCollection, markRegion, ordered, parse, rangeAdd, reportRuntime, requestChange, Typeahead, toggleEvery, treeArrow, typesCharacter, VirtualizeController, valueAt, window_, writtenList, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { caretDown, caretRight } from '@fusion.dev/helix-icons';
|
|
10
10
|
import { nothing } from 'lit';
|
|
11
11
|
import { property, state } from 'lit/decorators.js';
|
|
12
12
|
import { repeat } from 'lit/directives/repeat.js';
|
|
13
13
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
14
14
|
import { html } from 'lit/static-html.js';
|
|
15
|
-
import {
|
|
15
|
+
import { edgeOf } from '../../table/column/table-column.js';
|
|
16
16
|
import '../../checkbox/index.js';
|
|
17
17
|
import '../../pagination/index.js';
|
|
18
|
+
import { anchorAt, inRowOrder, toggledOpen } from '../keys.js';
|
|
18
19
|
import { grow } from '../tree.js';
|
|
19
|
-
import { arranged, cycle, format, ordered, parse, window_, } from './order.js';
|
|
20
20
|
const CONTROL = [
|
|
21
21
|
'a[href]',
|
|
22
22
|
'button:not([disabled])',
|
|
@@ -79,7 +79,6 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
79
79
|
this.typeahead = new Typeahead();
|
|
80
80
|
this.anchorKey = undefined;
|
|
81
81
|
this.shiftPressed = false;
|
|
82
|
-
this.askedAt = -1;
|
|
83
82
|
this.counts = {
|
|
84
83
|
columns: undefined,
|
|
85
84
|
rows: undefined,
|
|
@@ -427,7 +426,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
427
426
|
return value;
|
|
428
427
|
}
|
|
429
428
|
get opened() {
|
|
430
|
-
return new Set(
|
|
429
|
+
return new Set(commaList(this.expanded));
|
|
431
430
|
}
|
|
432
431
|
flat() {
|
|
433
432
|
if (this.childField) {
|
|
@@ -472,7 +471,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
472
471
|
if (!this.rowKey) {
|
|
473
472
|
return String(index);
|
|
474
473
|
}
|
|
475
|
-
const value =
|
|
474
|
+
const value = valueAt(row, this.rowKey);
|
|
476
475
|
return value === undefined || value === null ? String(index) : String(value);
|
|
477
476
|
}
|
|
478
477
|
currentRow(rows) {
|
|
@@ -648,18 +647,15 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
648
647
|
},
|
|
649
648
|
event: (value) => new HelixSelectEvent({ value }),
|
|
650
649
|
host: this,
|
|
651
|
-
next:
|
|
650
|
+
next: inRowOrder(keys, this.everyKey).join(','),
|
|
652
651
|
});
|
|
653
652
|
}
|
|
654
653
|
get chosen() {
|
|
655
|
-
return new Set(this.selected
|
|
656
|
-
.split(',')
|
|
657
|
-
.map((key) => key.trim())
|
|
658
|
-
.filter(Boolean));
|
|
654
|
+
return new Set(commaList(this.selected));
|
|
659
655
|
}
|
|
660
656
|
keyOf(row, place) {
|
|
661
657
|
if (this.rowKey) {
|
|
662
|
-
const value =
|
|
658
|
+
const value = valueAt(row, this.rowKey);
|
|
663
659
|
return value === undefined || value === null ? String(place) : String(value);
|
|
664
660
|
}
|
|
665
661
|
if (this.selectable && !this.warnedAboutKey && typeof window !== 'undefined') {
|
|
@@ -684,11 +680,8 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
684
680
|
}
|
|
685
681
|
selectRange(to, from = to) {
|
|
686
682
|
const keys = this.pageKeys;
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
anchor = from;
|
|
690
|
-
this.anchorKey = keys[from];
|
|
691
|
-
}
|
|
683
|
+
const { anchor, anchorKey } = anchorAt(keys, this.anchorKey, from);
|
|
684
|
+
this.anchorKey = anchorKey;
|
|
692
685
|
const next = rangeAdd([...this.chosen], keys, anchor, to);
|
|
693
686
|
if (next) {
|
|
694
687
|
this.requestSelected(new Set(next));
|
|
@@ -712,13 +705,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
712
705
|
if (!this.windowed || !this.loadMore || this.loading) {
|
|
713
706
|
return;
|
|
714
707
|
}
|
|
715
|
-
|
|
716
|
-
const count = this.rows.length;
|
|
717
|
-
if (screen > 0 &&
|
|
718
|
-
count > 0 &&
|
|
719
|
-
this.askedAt !== count &&
|
|
720
|
-
this.virtualize.remaining() <= screen) {
|
|
721
|
-
this.askedAt = count;
|
|
708
|
+
if (this.virtualize.endInSight(this.rows.length)) {
|
|
722
709
|
this.askForMore();
|
|
723
710
|
}
|
|
724
711
|
}
|
|
@@ -734,19 +721,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
734
721
|
this.requestSelected(keys);
|
|
735
722
|
}
|
|
736
723
|
chooseAll() {
|
|
737
|
-
|
|
738
|
-
const keys = this.chosen;
|
|
739
|
-
if (every.length > 0 && every.every((key) => keys.has(key))) {
|
|
740
|
-
for (const key of every) {
|
|
741
|
-
keys.delete(key);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
else {
|
|
745
|
-
for (const key of every) {
|
|
746
|
-
keys.add(key);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
this.requestSelected(keys);
|
|
724
|
+
this.requestSelected(new Set(toggleEvery(this.chosen, this.everyKey)));
|
|
750
725
|
}
|
|
751
726
|
moveColumn(field, by) {
|
|
752
727
|
const drawn = this.shownColumns.filter((column) => column.field !== '');
|
|
@@ -776,7 +751,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
776
751
|
return /[",\r\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
|
|
777
752
|
};
|
|
778
753
|
const head = columns.map((column) => quote(column.textContent?.trim() || column.field));
|
|
779
|
-
const body = rows.map((row) => columns.map((column) => quote(
|
|
754
|
+
const body = rows.map((row) => columns.map((column) => quote(valueAt(row, column.field))));
|
|
780
755
|
return [head, ...body].map((line) => line.join(',')).join('\r\n');
|
|
781
756
|
}
|
|
782
757
|
requestFilter(next) {
|
|
@@ -951,18 +926,11 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
951
926
|
><svg part="toggle-mark" ?data-mirror=${!open} fill="currentColor" viewBox=${glyph.viewBox}>${unsafeSVG(glyph.content)}</svg></span>`;
|
|
952
927
|
}
|
|
953
928
|
toggleOpen(row, open) {
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
if (keys.has(key) === open) {
|
|
929
|
+
const next = toggledOpen(this.expanded, this.rowKeyOf(row, -1), open, this.everyKey);
|
|
930
|
+
if (next === undefined) {
|
|
957
931
|
return false;
|
|
958
932
|
}
|
|
959
|
-
|
|
960
|
-
keys.add(key);
|
|
961
|
-
}
|
|
962
|
-
else {
|
|
963
|
-
keys.delete(key);
|
|
964
|
-
}
|
|
965
|
-
this.expanded = [...keys].join(',');
|
|
933
|
+
this.expanded = next;
|
|
966
934
|
this.dispatchEvent(new HelixExpandEvent({ value: this.expanded }));
|
|
967
935
|
return true;
|
|
968
936
|
}
|
|
@@ -1300,14 +1268,14 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1300
1268
|
return false;
|
|
1301
1269
|
}
|
|
1302
1270
|
const placed = this.tree().placed.get(row);
|
|
1303
|
-
const
|
|
1304
|
-
if (
|
|
1271
|
+
const arrow = treeArrow({ branch: placed?.branch ?? false, open: placed?.open ?? false }, inlineStep(this, event.key) > 0 ? 1 : -1);
|
|
1272
|
+
if (arrow === 'open' || arrow === 'close') {
|
|
1305
1273
|
event.preventDefault();
|
|
1306
|
-
this.toggleOpen(row,
|
|
1274
|
+
this.toggleOpen(row, arrow === 'open');
|
|
1307
1275
|
return true;
|
|
1308
1276
|
}
|
|
1309
1277
|
const parent = placed?.parent ? this.drawnPage.indexOf(placed.parent) : -1;
|
|
1310
|
-
if (
|
|
1278
|
+
if (arrow === 'parent' && parent >= 0) {
|
|
1311
1279
|
event.preventDefault();
|
|
1312
1280
|
this.moveTo(parent, place.column);
|
|
1313
1281
|
return true;
|
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Rows that hold rows, arranged for a tree grid: filtered, sorted within each
|
|
3
|
+
* parent, and laid out flat in reading order with the open rows' children under
|
|
4
|
+
* them.
|
|
5
|
+
*
|
|
6
|
+
* Pure and beside the family's `index.ts`, because which rows show and at what
|
|
7
|
+
* depth is a fact about the data, and a spec can hold it without a page.
|
|
8
|
+
*
|
|
9
|
+
* **Filtered by descent.** A row stays when it matches the query or any row
|
|
10
|
+
* under it does, so a match deep in the tree is shown with the rows that lead to
|
|
11
|
+
* it, and while a query is on every row with a match under it is open.
|
|
12
|
+
*
|
|
13
|
+
* **Sorted among siblings.** A sort orders each parent's rows and leaves every
|
|
14
|
+
* row under its parent, which is the only order a tree can be read in.
|
|
15
|
+
*/
|
|
16
|
+
import { type Axis, type DataRow } from '@fusion.dev/helix-core';
|
|
2
17
|
/** Where a row sits in the tree. */
|
|
3
18
|
export interface Placement {
|
|
4
19
|
/** Whether it has children to show. */
|
package/dist/data-table/tree.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { filter, parse, sort } from './root/order.js';
|
|
1
|
+
import { filter, parse, sort, valueAt } from '@fusion.dev/helix-core';
|
|
3
2
|
export const childrenOf = (row, field) => {
|
|
4
|
-
const value =
|
|
3
|
+
const value = valueAt(row, field);
|
|
5
4
|
return Array.isArray(value) ? value : [];
|
|
6
5
|
};
|
|
7
6
|
export const grow = (rows, axes, { field, isOpen, query, spec, }) => {
|
|
@@ -36,6 +36,8 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
36
36
|
* @slot feedback - The error message under the field.
|
|
37
37
|
* @slot hint - The help text under the field.
|
|
38
38
|
* @slot next-icon - The icon on the calendar's next month control.
|
|
39
|
+
* @slot panel-footer - Content in the panel under the calendar, such as a note or an action.
|
|
40
|
+
* @slot panel-header - Content in the panel above the calendar, such as a heading or a shortcut.
|
|
39
41
|
* @slot previous-icon - The icon on the calendar's previous month control.
|
|
40
42
|
* @slot trigger - The icon on the button that opens the calendar.
|
|
41
43
|
*
|
|
@@ -355,7 +357,7 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
355
357
|
/** Each date, where `mode` holds several, sent one entry each. */
|
|
356
358
|
protected get answers(): readonly string[] | undefined;
|
|
357
359
|
/** What is wrong with the dates, which the text input cannot say. */
|
|
358
|
-
protected validate(): string;
|
|
360
|
+
protected validate(): string | readonly [keyof ValidityStateFlags, string];
|
|
359
361
|
/**
|
|
360
362
|
* The message shown when `disable-dates` or `disable-days` bars a date.
|
|
361
363
|
*/
|
|
@@ -176,14 +176,20 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
|
|
|
176
176
|
: 'Enter dates as YYYY-MM-DD, separated by commas.'));
|
|
177
177
|
}
|
|
178
178
|
if (this.min !== '' && held.some((one) => one < this.min)) {
|
|
179
|
-
return
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
return [
|
|
180
|
+
'rangeUnderflow',
|
|
181
|
+
fillTemplate(this.rangeUnderflowMessage || 'Choose a date on or after {min}.', {
|
|
182
|
+
min: this.written(this.min),
|
|
183
|
+
}),
|
|
184
|
+
];
|
|
182
185
|
}
|
|
183
186
|
if (this.max !== '' && held.some((one) => one > this.max)) {
|
|
184
|
-
return
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
return [
|
|
188
|
+
'rangeOverflow',
|
|
189
|
+
fillTemplate(this.rangeOverflowMessage || 'Choose a date on or before {max}.', {
|
|
190
|
+
max: this.written(this.max),
|
|
191
|
+
}),
|
|
192
|
+
];
|
|
187
193
|
}
|
|
188
194
|
const why = held.map((one) => {
|
|
189
195
|
const date = asDate(one);
|
|
@@ -193,7 +199,10 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
|
|
|
193
199
|
return this.unavailableMessage || 'Choose a date that is available.';
|
|
194
200
|
}
|
|
195
201
|
if (why.includes('step')) {
|
|
196
|
-
return
|
|
202
|
+
return [
|
|
203
|
+
'stepMismatch',
|
|
204
|
+
this.stepMismatchMessage || 'Choose one of the dates the calendar offers.',
|
|
205
|
+
];
|
|
197
206
|
}
|
|
198
207
|
if (this.mode === 'range' && held.length > 2) {
|
|
199
208
|
return this.rangeLengthMessage || 'A range is two dates.';
|
|
@@ -327,7 +336,9 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
|
|
|
327
336
|
popover="manual"
|
|
328
337
|
?hidden=${!this.open}
|
|
329
338
|
>
|
|
339
|
+
<slot name="panel-header"></slot>
|
|
330
340
|
${this.renderPicker()}
|
|
341
|
+
<slot name="panel-footer"></slot>
|
|
331
342
|
</div>
|
|
332
343
|
${this.renderHint()}${this.renderFeedback()}`;
|
|
333
344
|
}
|
|
@@ -21,6 +21,7 @@ const KEYS = new Set([
|
|
|
21
21
|
'PageUp',
|
|
22
22
|
' ',
|
|
23
23
|
]);
|
|
24
|
+
const firstOf = (year, month) => addMonths(asDate('2000-01-01'), (year - 2000) * 12 + month);
|
|
24
25
|
let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControllerValue(HelixFormElement) {
|
|
25
26
|
constructor() {
|
|
26
27
|
super(...arguments);
|
|
@@ -139,13 +140,13 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
|
|
|
139
140
|
get shown() {
|
|
140
141
|
const explicit = /^(\d{4})-(\d{2})$/.exec(this.monthState ?? this.defaultMonth);
|
|
141
142
|
if (explicit) {
|
|
142
|
-
return
|
|
143
|
+
return firstOf(Number(explicit[1]), Number(explicit[2]) - 1);
|
|
143
144
|
}
|
|
144
145
|
return this.derivedMonth;
|
|
145
146
|
}
|
|
146
147
|
get derivedMonth() {
|
|
147
148
|
const from = asDate(this.selected[0] ?? '') ?? new Date();
|
|
148
|
-
return
|
|
149
|
+
return firstOf(from.getUTCFullYear(), from.getUTCMonth());
|
|
149
150
|
}
|
|
150
151
|
get anchor() {
|
|
151
152
|
const shown = this.shown;
|
|
@@ -268,11 +269,16 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
|
|
|
268
269
|
return;
|
|
269
270
|
}
|
|
270
271
|
this.pageYear = at;
|
|
271
|
-
|
|
272
|
+
const month = this.shown.getUTCMonth();
|
|
273
|
+
const open = Array.from({ length: 12 }, (_, index) => index).filter((index) => !this.monthOut(firstOf(at, index)));
|
|
274
|
+
this.periodFocus = open.includes(month)
|
|
275
|
+
? month
|
|
276
|
+
: ([...open].sort((left, right) => Math.abs(left - month) - Math.abs(right - month))[0] ??
|
|
277
|
+
month);
|
|
272
278
|
this.zoom('month');
|
|
273
279
|
return;
|
|
274
280
|
}
|
|
275
|
-
const first =
|
|
281
|
+
const first = firstOf(this.periodYear, at);
|
|
276
282
|
if (this.monthOut(first)) {
|
|
277
283
|
return;
|
|
278
284
|
}
|
|
@@ -558,8 +564,8 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
|
|
|
558
564
|
const years = this.view === 'year';
|
|
559
565
|
const page = years ? yearPageOf(this.periodYear) : this.periodYear;
|
|
560
566
|
const heading = years
|
|
561
|
-
? `${yearName.format(
|
|
562
|
-
: yearName.format(
|
|
567
|
+
? `${yearName.format(firstOf(page, 0))} – ${yearName.format(firstOf(page + YEARS_SHOWN - 1, 0))}`
|
|
568
|
+
: yearName.format(firstOf(page, 0));
|
|
563
569
|
const stop = this.periodStop;
|
|
564
570
|
const cells = periodCells({
|
|
565
571
|
max: this.max,
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
const CONTROL = 'a[href], audio[controls], button, details, form, iframe, input, select, textarea, video[controls], [contenteditable], [tabindex]';
|
|
2
|
-
const isControl = (element) =>
|
|
2
|
+
const isControl = (element) => {
|
|
3
|
+
if (element.matches(CONTROL)) {
|
|
4
|
+
return true;
|
|
5
|
+
}
|
|
6
|
+
if (!element.localName.includes('-')) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const definition = customElements.get(element.localName);
|
|
10
|
+
const root = element.shadowRoot;
|
|
11
|
+
return (definition === undefined ||
|
|
12
|
+
!(element instanceof definition) ||
|
|
13
|
+
definition.formAssociated === true ||
|
|
14
|
+
root?.delegatesFocus === true ||
|
|
15
|
+
root?.querySelector(CONTROL) != null);
|
|
16
|
+
};
|
|
3
17
|
export const wordsIn = (slot) => {
|
|
4
18
|
const words = [];
|
|
5
19
|
for (const one of slot?.assignedElements({ flatten: true }) ?? []) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AriaForwardController, CommandController, HelixElement, OpenPhaseController } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, CommandController, FocusScopeController, HelixElement, OpenPhaseController } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
|
|
4
4
|
/**
|
|
@@ -13,6 +13,10 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
|
|
|
13
13
|
* - an inert page behind the dialog, unreachable by pointer, keyboard, or
|
|
14
14
|
* virtual cursor
|
|
15
15
|
*
|
|
16
|
+
* The dialog adds one thing to those: `Tab` from its last control goes to its
|
|
17
|
+
* first, and `Shift+Tab` from its first to its last. A native modal lets `Tab`
|
|
18
|
+
* past its last control out to the browser's own controls.
|
|
19
|
+
*
|
|
16
20
|
* `open` calls `showModal()`, and every way the dialog closes goes through
|
|
17
21
|
* `requestOpen`. A native dialog closes three ways: the property, Escape, and a
|
|
18
22
|
* `<form method="dialog">` submit. Routing all three through `requestOpen`
|
|
@@ -25,7 +29,8 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
|
|
|
25
29
|
*
|
|
26
30
|
* The dialog is described by the words at the start of its body: the elements
|
|
27
31
|
* in the default slot before the first one that is or holds a control. A
|
|
28
|
-
* question above a form describes the dialog, and the form does not.
|
|
32
|
+
* question above a form describes the dialog, and the form does not. A Helix
|
|
33
|
+
* component that draws words and no control, such as `Text`, counts as words. An
|
|
29
34
|
* `aria-describedby` on the host replaces it.
|
|
30
35
|
*
|
|
31
36
|
* Set `alert` for a dialog that interrupts to ask for an answer, such as a
|
|
@@ -190,6 +195,7 @@ export declare class HelixHeadlessDialog extends HelixHeadlessDialog_base {
|
|
|
190
195
|
* either. A browser without element reflection keeps the fallback name.
|
|
191
196
|
*/
|
|
192
197
|
private nameByHeader;
|
|
198
|
+
protected readonly scope: FocusScopeController;
|
|
193
199
|
/** Whether the body's words are what currently describe the dialog. */
|
|
194
200
|
private describedByBody;
|
|
195
201
|
/**
|
|
@@ -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 { AriaForwardController, CommandController, customElement, drawDismiss, drawDismissGlyph, HelixElement, headingsIn, hostAria, lockScroll, MixinControllerOpen, OpenPhaseController, reflectElements, unlockScroll, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, auditName, CommandController, customElement, drawDismiss, drawDismissGlyph, FocusScopeController, HelixElement, headingsIn, hostAria, lockScroll, MixinControllerOpen, OpenPhaseController, reflectElements, unlockScroll, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { wordsIn } from '../description.js';
|
|
@@ -60,6 +60,16 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
|
|
|
60
60
|
this.close(submitter?.hasAttribute('value') ? submitter.value : undefined);
|
|
61
61
|
};
|
|
62
62
|
this.namedByHeader = false;
|
|
63
|
+
this.scope = new FocusScopeController(this, {
|
|
64
|
+
contain: () => this.open,
|
|
65
|
+
contents: () => [
|
|
66
|
+
...['icon', 'header', '', 'footer'].flatMap((name) => this.renderRoot
|
|
67
|
+
?.querySelector(name ? `slot[name="${name}"]` : 'slot:not([name])')
|
|
68
|
+
?.assignedElements({ flatten: true }) ?? []),
|
|
69
|
+
...[...(this.dialog?.children ?? [])].filter((one) => !(one instanceof HTMLSlotElement)),
|
|
70
|
+
],
|
|
71
|
+
surface: () => this.dialog,
|
|
72
|
+
});
|
|
63
73
|
this.describedByBody = false;
|
|
64
74
|
this.handleBackdrop = (event) => {
|
|
65
75
|
const panel = this.dialog;
|
|
@@ -145,6 +155,11 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
|
|
|
145
155
|
return;
|
|
146
156
|
}
|
|
147
157
|
if (this.open && !dialog.open) {
|
|
158
|
+
auditName(this, () => null, 'Give it a `label`, or a heading in the `header` slot.', () => this.label !== '' ||
|
|
159
|
+
this.namedByHeader ||
|
|
160
|
+
headingsIn(this.renderRoot
|
|
161
|
+
.querySelector('slot[name="header"]')
|
|
162
|
+
?.assignedElements({ flatten: true }) ?? []).length > 0);
|
|
148
163
|
void this.openWhenSlotted(dialog);
|
|
149
164
|
}
|
|
150
165
|
else if (!this.open && dialog.open) {
|
|
@@ -9,6 +9,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
9
9
|
* rendered element. The semantics are then in the server-rendered markup, with
|
|
10
10
|
* no attribute written by script after the element connects.
|
|
11
11
|
*
|
|
12
|
+
* Set `announced` for a line that divides one thing from another, and it is
|
|
13
|
+
* read as a separator, named by any content set into it.
|
|
14
|
+
*
|
|
12
15
|
* Use `orientation="vertical"` between items on one line, such as inside a
|
|
13
16
|
* toolbar. A vertical divider stretches to fit its flex parent and sets no
|
|
14
17
|
* height of its own.
|
|
@@ -23,9 +23,10 @@ let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
|
|
|
23
23
|
return html `<div
|
|
24
24
|
part="line"
|
|
25
25
|
role=${this.announced ? 'separator' : 'presentation'}
|
|
26
|
+
aria-labelledby=${this.announced ? 'content' : nothing}
|
|
26
27
|
aria-orientation=${this.announced ? (this.orientation ?? 'horizontal') : nothing}
|
|
27
28
|
></div>
|
|
28
|
-
<span part="content"><slot @slotchange=${() => this.markEmpty()}></slot></span>
|
|
29
|
+
<span id="content" part="content"><slot @slotchange=${() => this.markEmpty()}></slot></span>
|
|
29
30
|
<div part="line" role="presentation"></div>`;
|
|
30
31
|
}
|
|
31
32
|
};
|
|
@@ -49,6 +49,7 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
|
|
|
49
49
|
* @csspart segment - One slice.
|
|
50
50
|
* @csspart segment-active - The slice under the pointer. Set alongside `segment`.
|
|
51
51
|
* @csspart segment-edge - One slice as a closed shape, used to draw its outline.
|
|
52
|
+
* @csspart slice-label - One slice's share, written on the slice under `slice-labels`. Placed with `left` and `top`, or `inset-inline-start` and `top` on a half ring, and carries its series color as `--chart-series`.
|
|
52
53
|
* @csspart summary - The chart's name and each slice's share, written as a sentence for screen readers. Hide it visually.
|
|
53
54
|
* @csspart tooltip - The bubble, forwarded from `Tooltip`.
|
|
54
55
|
* @csspart tooltip-anchor - The `Tooltip` element itself.
|
|
@@ -115,6 +116,16 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
|
|
|
115
116
|
* because the styled sheet selects on it.
|
|
116
117
|
*/
|
|
117
118
|
hole?: 'large' | 'none' | 'small';
|
|
119
|
+
/**
|
|
120
|
+
* Writes each slice's share on the slice, the `slice-label` part, so a
|
|
121
|
+
* reader sees the parts without a legend or a pointer: "29%" in the middle
|
|
122
|
+
* of the band.
|
|
123
|
+
*
|
|
124
|
+
* Absent writes none. A slice under a twentieth of the whole takes no
|
|
125
|
+
* label, there being no room on it for one. A screen reader hears every
|
|
126
|
+
* share in the summary, and the labels are hidden from it.
|
|
127
|
+
*/
|
|
128
|
+
sliceLabels: boolean;
|
|
118
129
|
/**
|
|
119
130
|
* How much of the circle the whole occupies.
|
|
120
131
|
*
|
|
@@ -175,6 +186,11 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
|
|
|
175
186
|
* slice, so a key stepping by rows would land on a slice that is not there.
|
|
176
187
|
*/
|
|
177
188
|
get readings(): number;
|
|
189
|
+
/**
|
|
190
|
+
* Whether the slice at this place is drawn, which a slice a legend hid is
|
|
191
|
+
* not. The keys pass over it, as the ring closes over it.
|
|
192
|
+
*/
|
|
193
|
+
showsReading(at: number): boolean;
|
|
178
194
|
protected render(): TemplateResult;
|
|
179
195
|
/**
|
|
180
196
|
* What a reader who cannot see the ring is told: the chart's name and each
|
|
@@ -194,6 +210,13 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
|
|
|
194
210
|
* table does not hold.
|
|
195
211
|
*/
|
|
196
212
|
protected renderPlot(shares: DonutShare[]): TemplateResult;
|
|
213
|
+
/**
|
|
214
|
+
* Each slice's share, written in the middle of its band at its mid-angle,
|
|
215
|
+
* as an element beside the drawing so the text is not stretched with it.
|
|
216
|
+
* Placed as the tooltip's point is placed: from the left on a whole ring,
|
|
217
|
+
* whose bearing is a clock's, and from the inline start on a half one.
|
|
218
|
+
*/
|
|
219
|
+
protected renderSliceLabels(shares: DonutShare[]): TemplateResult;
|
|
197
220
|
/**
|
|
198
221
|
* The view box, cropped to what is actually drawn.
|
|
199
222
|
*
|
|
@@ -238,6 +261,14 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
|
|
|
238
261
|
* box, which is the ring's center for a circle and is not for a sector.
|
|
239
262
|
*/
|
|
240
263
|
protected renderEdge(share: DonutShare, index: number): TemplateResult;
|
|
264
|
+
/**
|
|
265
|
+
* The rows the tooltip reads, with the slice's share of the whole after its
|
|
266
|
+
* amount, as `AreaChart` writes a part's share under `share`: "612 (24%)".
|
|
267
|
+
*
|
|
268
|
+
* The share is what the ring shows and the table does not, so a reading
|
|
269
|
+
* said by key gives it too, as the summary does.
|
|
270
|
+
*/
|
|
271
|
+
private withShare;
|
|
241
272
|
/**
|
|
242
273
|
* What a pointer resting on a slice shows.
|
|
243
274
|
*
|
|
@@ -30,6 +30,10 @@ const THICKNESS = {
|
|
|
30
30
|
small: 26,
|
|
31
31
|
};
|
|
32
32
|
let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSource(HelixElement) {
|
|
33
|
+
constructor() {
|
|
34
|
+
super(...arguments);
|
|
35
|
+
this.sliceLabels = false;
|
|
36
|
+
}
|
|
33
37
|
connectedCallback() {
|
|
34
38
|
super.connectedCallback();
|
|
35
39
|
this.pointer.axis = 'none';
|
|
@@ -70,6 +74,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
|
|
|
70
74
|
get readings() {
|
|
71
75
|
return this.shares.length;
|
|
72
76
|
}
|
|
77
|
+
showsReading(at) {
|
|
78
|
+
return (this.shares[at]?.fraction ?? 0) > 0;
|
|
79
|
+
}
|
|
73
80
|
render() {
|
|
74
81
|
const shares = this.shares;
|
|
75
82
|
return html `${this.renderPlot(shares)}${shares.length === 0 ? nothing : this.renderSummary(shares)}`;
|
|
@@ -111,9 +118,31 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
|
|
|
111
118
|
${shares.map((share, index) => this.renderSegment(share, index))}
|
|
112
119
|
</svg>
|
|
113
120
|
${this.hole === 'none' ? nothing : html `<div id="helix-chart-center" part="center"><slot></slot></div>`}
|
|
121
|
+
${this.sliceLabels ? this.renderSliceLabels(shares) : nothing}
|
|
114
122
|
${this.renderTooltip()}
|
|
115
123
|
</div>`;
|
|
116
124
|
}
|
|
125
|
+
renderSliceLabels(shares) {
|
|
126
|
+
const half = this.sweep === 'half';
|
|
127
|
+
const top = half ? CENTER - EDGE : 0;
|
|
128
|
+
const tall = half ? EDGE + this.thickness / 2 : PLOT_HEIGHT;
|
|
129
|
+
const format = percentIn(this.locale);
|
|
130
|
+
return html `${shares.map((share, index) => {
|
|
131
|
+
if (share.fraction < 0.05) {
|
|
132
|
+
return nothing;
|
|
133
|
+
}
|
|
134
|
+
const angle = (share.start + share.fraction / 2) * 2 * Math.PI * this.span + this.origin;
|
|
135
|
+
const x = ((CENTER + Math.cos(angle) * this.radius) / PLOT_WIDTH) * 100;
|
|
136
|
+
const y = ((CENTER + Math.sin(angle) * this.radius - top) / tall) * 100;
|
|
137
|
+
return html `<span
|
|
138
|
+
aria-hidden="true"
|
|
139
|
+
data-series=${seriesIndex(index)}
|
|
140
|
+
part="slice-label"
|
|
141
|
+
style=${`--chart-series: var(--chart-series-${seriesIndex(index)}); ${half ? 'inset-inline-start' : 'left'}: ${x}%; top: ${y}%`}
|
|
142
|
+
>${format.format(share.fraction)}</span
|
|
143
|
+
>`;
|
|
144
|
+
})}`;
|
|
145
|
+
}
|
|
117
146
|
get frame() {
|
|
118
147
|
if (this.sweep !== 'half') {
|
|
119
148
|
return `0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}`;
|
|
@@ -174,6 +203,21 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
|
|
|
174
203
|
style="--chart-series: var(--chart-series-${seriesIndex(index)})"
|
|
175
204
|
/>`;
|
|
176
205
|
}
|
|
206
|
+
withShare(share) {
|
|
207
|
+
const rows = this.sourceRows;
|
|
208
|
+
const column = this.plottedColumns[0];
|
|
209
|
+
const row = rows[share.row];
|
|
210
|
+
const cell = column === undefined ? undefined : row?.cells[column];
|
|
211
|
+
if (!row || !cell || column === undefined) {
|
|
212
|
+
return rows;
|
|
213
|
+
}
|
|
214
|
+
const cells = [...row.cells];
|
|
215
|
+
cells[column] = {
|
|
216
|
+
...cell,
|
|
217
|
+
text: `${cell.text} (${percentIn(this.locale).format(share.fraction)})`,
|
|
218
|
+
};
|
|
219
|
+
return rows.map((one, index) => (index === share.row ? { ...row, cells } : one));
|
|
220
|
+
}
|
|
177
221
|
renderTooltip() {
|
|
178
222
|
const at = this.pointer.at;
|
|
179
223
|
const share = this.shares[at];
|
|
@@ -188,7 +232,7 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
|
|
|
188
232
|
const y = ((CENTER + Math.sin(angle) * edge - top) / tall) * 100;
|
|
189
233
|
const turned = this.sweep === 'half' && this.pointer.mirrored;
|
|
190
234
|
const across = Math.cos(angle) > 0 !== turned;
|
|
191
|
-
return drawTooltip(this.
|
|
235
|
+
return drawTooltip(this.withShare(share), share.row, this.tag('tooltip'), {
|
|
192
236
|
fixed: this.sweep !== 'half',
|
|
193
237
|
placement: Math.abs(Math.cos(angle)) > Math.abs(Math.sin(angle))
|
|
194
238
|
? across
|
|
@@ -205,6 +249,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
|
|
|
205
249
|
__decorate([
|
|
206
250
|
property()
|
|
207
251
|
], HelixHeadlessDonutChart.prototype, "hole", void 0);
|
|
252
|
+
__decorate([
|
|
253
|
+
property({ attribute: 'slice-labels', reflect: true, type: Boolean })
|
|
254
|
+
], HelixHeadlessDonutChart.prototype, "sliceLabels", void 0);
|
|
208
255
|
__decorate([
|
|
209
256
|
property({ reflect: true })
|
|
210
257
|
], HelixHeadlessDonutChart.prototype, "sweep", void 0);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a box reaches past the window's edges, by more than a pixel.
|
|
3
|
+
*
|
|
4
|
+
* What a drawer resting at a snap point asks of the element focus has just
|
|
5
|
+
* moved to: the part of the panel past the window's edge is off screen, and a
|
|
6
|
+
* control there has focus where the reader cannot see it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const beyondWindow: (box: Pick<DOMRectReadOnly, 'bottom' | 'left' | 'right' | 'top'>, width: number, height: number) => boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const beyondWindow = (box, width, height) => box.top < -1 || box.left < -1 || box.bottom > height + 1 || box.right > width + 1;
|