@fusion.dev/helix-headless 0.146.0 → 0.148.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 +9287 -1084
- package/dist/accordion/item/accordion-item.d.ts +43 -21
- package/dist/accordion/item/accordion-item.js +37 -11
- package/dist/accordion/root/accordion-root.d.ts +8 -2
- package/dist/accordion/root/accordion-root.js +6 -8
- package/dist/announcement/root/announcement-root.d.ts +66 -6
- package/dist/announcement/root/announcement-root.js +144 -13
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +14 -7
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/count.d.ts +14 -0
- package/dist/badge/count.js +20 -0
- package/dist/badge/root/badge-root.d.ts +57 -6
- package/dist/badge/root/badge-root.js +77 -8
- package/dist/bar-chart/root/bar-chart-root.js +11 -20
- package/dist/bar-chart/stack.d.ts +10 -0
- package/dist/bar-chart/stack.js +8 -0
- package/dist/blockquote/root/blockquote-root.d.ts +66 -8
- package/dist/blockquote/root/blockquote-root.js +85 -8
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -2
- package/dist/button/root/button-root.d.ts +24 -38
- package/dist/button/root/button-root.js +6 -37
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- package/dist/button-group/arrows.d.ts +14 -0
- package/dist/button-group/arrows.js +10 -0
- package/dist/button-group/root/button-group-root.d.ts +141 -3
- package/dist/button-group/root/button-group-root.js +142 -2
- package/dist/canvas/edge-pan.d.ts +61 -0
- package/dist/canvas/edge-pan.js +63 -0
- package/dist/canvas/node/canvas-node.d.ts +12 -2
- package/dist/canvas/node/canvas-node.js +6 -2
- package/dist/canvas/root/canvas-document.d.ts +10 -0
- package/dist/canvas/root/canvas-document.js +1 -0
- package/dist/canvas/root/canvas-root.d.ts +107 -5
- package/dist/canvas/root/canvas-root.js +140 -36
- package/dist/canvas/snap.d.ts +42 -0
- package/dist/canvas/snap.js +32 -0
- package/dist/card/root/card-root.d.ts +12 -1
- package/dist/card/root/card-root.js +11 -4
- package/dist/carousel/root/carousel-root.d.ts +4 -3
- package/dist/carousel/root/carousel-root.js +2 -6
- package/dist/chat/root/chat-root.d.ts +28 -4
- package/dist/chat/root/chat-root.js +12 -7
- package/dist/checkbox/root/checkbox-root.js +5 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +13 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +16 -7
- package/dist/checkbox-group/select-all.d.ts +9 -4
- package/dist/checkbox-group/select-all.js +1 -1
- package/dist/code-block/root/code-block-root.d.ts +41 -18
- package/dist/code-block/root/code-block-root.js +21 -6
- package/dist/color-input/root/color-input-root.d.ts +11 -0
- package/dist/color-input/root/color-input-root.js +12 -5
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +32 -24
- package/dist/color-picker/root/color-picker-root.js +99 -55
- package/dist/color-picker/wheel.d.ts +28 -0
- package/dist/color-picker/wheel.js +15 -0
- package/dist/combobox/root/combobox-root.d.ts +83 -11
- package/dist/combobox/root/combobox-root.js +81 -18
- package/dist/command/root/command-root.d.ts +7 -4
- package/dist/command/root/command-root.js +2 -19
- package/dist/copy-button/root/copy-button-root.d.ts +16 -1
- package/dist/copy-button/root/copy-button-root.js +7 -2
- package/dist/data-table/keys.d.ts +0 -18
- package/dist/data-table/keys.js +1 -11
- package/dist/data-table/root/data-table-root.js +29 -50
- package/dist/date-input/root/date-input-root.d.ts +8 -1
- package/dist/date-input/root/date-input-root.js +8 -5
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +21 -16
- package/dist/description-list/item/description-list-item.d.ts +22 -4
- package/dist/description-list/item/description-list-item.js +14 -4
- package/dist/divider/root/divider-root.d.ts +45 -16
- package/dist/divider/root/divider-root.js +28 -4
- package/dist/donut-chart/root/donut-chart-root.js +13 -6
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/root/drawer-root.d.ts +4 -2
- package/dist/drawer/root/drawer-root.js +15 -3
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +38 -4
- package/dist/drilldown/root/drilldown-root.js +3 -2
- package/dist/element-events.generated.js +5 -1
- package/dist/empty/root/empty-root.d.ts +46 -2
- package/dist/empty/root/empty-root.js +50 -5
- package/dist/file-input/root/file-input-root.d.ts +34 -6
- package/dist/file-input/root/file-input-root.js +55 -21
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +11 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +10 -2
- package/dist/filter-input/root/filter-input-root.d.ts +8 -0
- package/dist/filter-input/root/filter-input-root.js +17 -27
- package/dist/format-date/fields.d.ts +20 -0
- package/dist/format-date/fields.js +14 -0
- package/dist/format-date/options.d.ts +5 -5
- package/dist/format-date/options.js +10 -39
- package/dist/format-date/root/format-date-root.d.ts +53 -4
- package/dist/format-date/root/format-date-root.js +38 -50
- package/dist/graph/root/graph-root.d.ts +23 -5
- package/dist/graph/root/graph-root.js +17 -20
- package/dist/heatmap/root/buckets.d.ts +21 -0
- package/dist/heatmap/root/buckets.js +34 -0
- package/dist/heatmap/root/heatmap-root.d.ts +76 -3
- package/dist/heatmap/root/heatmap-root.js +105 -20
- package/dist/icon/index.d.ts +1 -1
- package/dist/icon/index.js +1 -1
- package/dist/icon/registry.d.ts +26 -1
- package/dist/icon/registry.js +12 -1
- package/dist/icon/root/icon-root.d.ts +13 -0
- package/dist/icon/root/icon-root.js +23 -2
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- package/dist/image/root/image-root.d.ts +20 -0
- package/dist/image/root/image-root.js +6 -1
- package/dist/input/root/input-root.d.ts +23 -2
- package/dist/input/root/input-root.js +12 -8
- package/dist/kbd/root/kbd-root.d.ts +20 -3
- package/dist/kbd/root/kbd-root.js +23 -50
- package/dist/legend/hidden-series.d.ts +10 -2
- package/dist/legend/hidden-series.js +5 -2
- package/dist/legend/root/legend-root.d.ts +25 -7
- package/dist/legend/root/legend-root.js +25 -26
- package/dist/lightbox/root/lightbox-root.d.ts +50 -5
- package/dist/lightbox/root/lightbox-root.js +76 -8
- package/dist/lightbox/zoom.d.ts +2 -0
- package/dist/lightbox/zoom.js +5 -3
- package/dist/line-chart/root/line-chart-root.d.ts +16 -0
- package/dist/line-chart/root/line-chart-root.js +10 -2
- package/dist/list/root/list-root.d.ts +10 -2
- package/dist/list/root/list-root.js +31 -24
- package/dist/list/selection.d.ts +17 -0
- package/dist/list/selection.js +16 -0
- package/dist/listbox/root/listbox-root.d.ts +125 -26
- package/dist/listbox/root/listbox-root.js +156 -166
- package/dist/map/marker/map-marker.d.ts +2 -1
- package/dist/map/root/map-root.d.ts +40 -2
- package/dist/map/root/map-root.js +64 -23
- package/dist/megamenu/hand-over.d.ts +75 -0
- package/dist/megamenu/hand-over.js +67 -0
- package/dist/megamenu/root/megamenu-root.d.ts +38 -14
- package/dist/megamenu/root/megamenu-root.js +29 -50
- package/dist/menu/item/menu-item.js +4 -4
- package/dist/menu/root/menu-root.d.ts +5 -2
- package/dist/meter/root/meter-root.d.ts +42 -0
- package/dist/meter/root/meter-root.js +33 -7
- package/dist/navigation/root/navigation-root.js +5 -8
- package/dist/notifications/group/notification-group.d.ts +8 -1
- package/dist/notifications/group/notification-group.js +12 -6
- package/dist/notifications/notification/notification.d.ts +12 -1
- package/dist/notifications/notification/notification.js +3 -1
- package/dist/notifications/root/notifications-root.d.ts +48 -3
- package/dist/notifications/root/notifications-root.js +36 -6
- package/dist/number-input/grain.d.ts +28 -0
- package/dist/number-input/grain.js +14 -0
- package/dist/number-input/root/number-input-root.d.ts +17 -1
- package/dist/number-input/root/number-input-root.js +29 -18
- package/dist/object-inspector/root/object-inspector-root.d.ts +17 -6
- package/dist/object-inspector/root/object-inspector-root.js +31 -20
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- package/dist/option/separator/option-separator.d.ts +30 -0
- package/dist/option/separator/option-separator.js +21 -0
- package/dist/outline/root/outline-root.d.ts +12 -0
- package/dist/outline/root/outline-root.js +5 -19
- package/dist/pagination/size/pagination-size.d.ts +6 -0
- package/dist/pagination/size/pagination-size.js +5 -3
- package/dist/pin-input/code.d.ts +51 -1
- package/dist/pin-input/code.js +37 -0
- package/dist/pin-input/root/pin-input-root.d.ts +98 -121
- package/dist/pin-input/root/pin-input-root.js +151 -156
- package/dist/popover/hide-outside.js +2 -9
- package/dist/popover/root/popover-root.d.ts +7 -1
- package/dist/popover/root/popover-root.js +9 -1
- package/dist/progress/root/progress-root.d.ts +27 -0
- package/dist/progress/root/progress-root.js +25 -7
- package/dist/qr-code/export.d.ts +19 -0
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/name.d.ts +11 -0
- package/dist/qr-code/name.js +7 -0
- package/dist/qr-code/root/qr-code-root.d.ts +31 -9
- package/dist/qr-code/root/qr-code-root.js +29 -17
- package/dist/radio/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.js +2 -2
- package/dist/rating/root/rating-root.d.ts +22 -9
- package/dist/rating/root/rating-root.js +15 -39
- package/dist/scatter-chart/measures.d.ts +22 -0
- package/dist/scatter-chart/measures.js +11 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +26 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +21 -7
- package/dist/scroll-area/scrollbar.d.ts +0 -8
- package/dist/scroll-area/scrollbar.js +1 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +115 -11
- package/dist/select/root/select-root.js +104 -20
- package/dist/slider/root/slider-root.d.ts +18 -1
- package/dist/slider/root/slider-root.js +22 -0
- package/dist/sparkline/readings.d.ts +30 -12
- package/dist/sparkline/readings.js +32 -15
- package/dist/sparkline/root/sparkline-root.d.ts +46 -3
- package/dist/sparkline/root/sparkline-root.js +60 -21
- package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
- package/dist/speed-dial/group/speed-dial-group.js +43 -0
- package/dist/speed-dial/index.d.ts +1 -0
- package/dist/speed-dial/index.js +1 -0
- package/dist/speed-dial/item/speed-dial-item.d.ts +27 -2
- package/dist/speed-dial/item/speed-dial-item.js +43 -5
- package/dist/speed-dial/long-press.d.ts +50 -0
- package/dist/speed-dial/long-press.js +48 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +86 -1
- package/dist/speed-dial/root/speed-dial-root.js +123 -6
- package/dist/splitter/root/splitter-root.d.ts +9 -2
- package/dist/splitter/root/splitter-root.js +18 -3
- package/dist/steps/root/steps-root.d.ts +8 -1
- package/dist/steps/root/steps-root.js +6 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/table/cell/table-cell.d.ts +8 -1
- package/dist/table/cell/table-cell.js +6 -2
- package/dist/table/column/table-column.d.ts +6 -0
- package/dist/table/column/table-column.js +5 -1
- package/dist/table/grid-controller.d.ts +117 -0
- package/dist/table/grid-controller.js +293 -0
- package/dist/table/root/table-root.d.ts +47 -3
- package/dist/table/root/table-root.js +93 -29
- package/dist/table/row/table-row.d.ts +36 -0
- package/dist/table/row/table-row.js +52 -2
- package/dist/tabs/root/tabs-root.d.ts +5 -3
- package/dist/tag/group/tag-group.d.ts +16 -4
- package/dist/tag/group/tag-group.js +23 -20
- package/dist/textarea/root/textarea-root.d.ts +14 -2
- package/dist/textarea/root/textarea-root.js +6 -7
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +10 -7
- package/dist/time-picker/root/time-picker-root.d.ts +12 -14
- package/dist/time-picker/root/time-picker-root.js +18 -23
- package/dist/toast/item/toast-item.d.ts +9 -6
- package/dist/toast/item/toast-item.js +1 -1
- package/dist/toast/root/toast-root.d.ts +40 -4
- package/dist/toast/root/toast-root.js +68 -16
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +29 -5
- package/dist/toggle/group/toggle-group.js +26 -43
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +52 -5
- package/dist/toolbar/root/toolbar-root.js +88 -13
- package/dist/tooltip/root/tooltip-root.d.ts +7 -1
- package/dist/tooltip/root/tooltip-root.js +10 -2
- package/dist/tour/root/tour-root.d.ts +15 -0
- package/dist/tour/root/tour-root.js +20 -1
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- package/dist/tree/root/tree-root.js +2 -2
- package/dist/trend/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +41 -2
- package/dist/trend/root/trend-root.js +29 -3
- package/dist/video/root/extra-controls.d.ts +12 -0
- package/dist/video/root/extra-controls.js +6 -2
- package/dist/video/root/video-root.d.ts +16 -1
- package/dist/video/root/video-root.js +15 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +11 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -0
- package/dist/virtual-list/fill.js +9 -0
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +17 -1
- package/dist/virtual-list/plan.js +13 -2
- package/dist/virtual-list/root/virtual-list-root.d.ts +25 -3
- package/dist/virtual-list/root/virtual-list-root.js +53 -41
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +4934 -954
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +946 -253
- package/dist/color-picker/swatches.d.ts +0 -12
- package/dist/color-picker/swatches.js +0 -26
- package/dist/rating/steps.d.ts +0 -7
- package/dist/rating/steps.js +0 -9
- package/dist/tooltip/focus-target.d.ts +0 -6
- package/dist/tooltip/focus-target.js +0 -9
|
@@ -23,6 +23,7 @@ const percentIn = (locale) => {
|
|
|
23
23
|
let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSource(HelixElement) {
|
|
24
24
|
constructor() {
|
|
25
25
|
super(...arguments);
|
|
26
|
+
this.overlap = false;
|
|
26
27
|
this.share = false;
|
|
27
28
|
this.totalLabel = 'Total';
|
|
28
29
|
this.warnedAboutNegatives = false;
|
|
@@ -36,7 +37,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
36
37
|
get stack() {
|
|
37
38
|
const rows = this.sourceRows;
|
|
38
39
|
const columns = this.plottedColumns;
|
|
39
|
-
const names = columns.map((column) =>
|
|
40
|
+
const names = columns.map((column) => this.columnName(column));
|
|
40
41
|
const values = columns.map((column, depth) => rows.map((row) => {
|
|
41
42
|
if (!this.showsSeries(names[depth] ?? '')) {
|
|
42
43
|
return 0;
|
|
@@ -57,7 +58,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
57
58
|
const layers = [];
|
|
58
59
|
let running = rows.map(() => 0);
|
|
59
60
|
for (const column of drawn) {
|
|
60
|
-
running = running.map((sum, index) => sum + (column[index] ?? 0));
|
|
61
|
+
running = this.overlap ? column : running.map((sum, index) => sum + (column[index] ?? 0));
|
|
61
62
|
layers.push(running);
|
|
62
63
|
}
|
|
63
64
|
return {
|
|
@@ -88,7 +89,11 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
88
89
|
if (rows.length === 0 || stack.columns.length === 0) {
|
|
89
90
|
return html `<div id=${CHART_PLOT} part="plot"></div>`;
|
|
90
91
|
}
|
|
91
|
-
const top = this.
|
|
92
|
+
const top = this.overlap
|
|
93
|
+
? Math.max(0, ...stack.layers.flat())
|
|
94
|
+
: this.share
|
|
95
|
+
? 1
|
|
96
|
+
: Math.max(0, ...stack.totals);
|
|
92
97
|
const domain = [0, top > 0 ? top : 1];
|
|
93
98
|
const y = linear(domain, [PLOT_HEIGHT, 0]);
|
|
94
99
|
const slot = PLOT_WIDTH / rows.length;
|
|
@@ -181,9 +186,8 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
181
186
|
]
|
|
182
187
|
: []);
|
|
183
188
|
const named = this.named ? `${this.named}, ` : '';
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
</p>`;
|
|
189
|
+
const words = `${named}${rows[last]?.label ?? ''}: ${this.totalLabel} ${format(total)}; ${shares.join(', ')}.`;
|
|
190
|
+
return html `<p id="helix-chart-summary" part="summary">${words}</p>`;
|
|
187
191
|
}
|
|
188
192
|
tallied(rows, stack) {
|
|
189
193
|
const format = formatNumbers(this.locale);
|
|
@@ -213,7 +217,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
213
217
|
return drawTooltip(rows, at, this.tag('tooltip'), {
|
|
214
218
|
placement: 'top',
|
|
215
219
|
x: `${at * slot + slot / 2}%`,
|
|
216
|
-
y: `${y(stack.layers.
|
|
220
|
+
y: `${y(Math.max(0, ...stack.layers.map((layer) => layer[at] ?? 0)))}%`,
|
|
217
221
|
}, (cell) => this.seriesOf(cell), this.pointer);
|
|
218
222
|
}
|
|
219
223
|
};
|
|
@@ -223,6 +227,9 @@ __decorate([
|
|
|
223
227
|
__decorate([
|
|
224
228
|
property()
|
|
225
229
|
], HelixHeadlessAreaChart.prototype, "gridlines", void 0);
|
|
230
|
+
__decorate([
|
|
231
|
+
property({ reflect: true, type: Boolean })
|
|
232
|
+
], HelixHeadlessAreaChart.prototype, "overlap", void 0);
|
|
226
233
|
__decorate([
|
|
227
234
|
property({ reflect: true, type: Boolean })
|
|
228
235
|
], HelixHeadlessAreaChart.prototype, "share", void 0);
|
|
@@ -15,7 +15,16 @@ export declare const initialsOf: (name: string) => string;
|
|
|
15
15
|
* a person's name does not describe what the avatar stands for.
|
|
16
16
|
*
|
|
17
17
|
* `load` and `error` are re-dispatched from the host, because they are not
|
|
18
|
-
* composed and would otherwise stop at the shadow boundary.
|
|
18
|
+
* composed and would otherwise stop at the shadow boundary. `status` says
|
|
19
|
+
* which of the two happened, for a listener that arrives after it, and the
|
|
20
|
+
* `loading`, `loaded` and `error` custom states say the same to a stylesheet.
|
|
21
|
+
*
|
|
22
|
+
* **On a server the avatar sends the picture's place**, an `<img>` that the
|
|
23
|
+
* browser fetches while it reads the page. The initials stand in only on the
|
|
24
|
+
* client: at once where the picture failed before the page hydrated, and after
|
|
25
|
+
* `fallback-delay` where it is still on its way. `load` or `error` for a
|
|
26
|
+
* picture that settled before hydration is sent a task after the avatar
|
|
27
|
+
* hydrates, so a page's own scripts are listening by then.
|
|
19
28
|
*
|
|
20
29
|
* @since 0.1.0
|
|
21
30
|
* @status stable
|
|
@@ -30,6 +39,10 @@ export declare const initialsOf: (name: string) => string;
|
|
|
30
39
|
*
|
|
31
40
|
* @csspart image - The image, when one is loading or loaded.
|
|
32
41
|
* @csspart initials - The initials shown when there is no usable image.
|
|
42
|
+
*
|
|
43
|
+
* @cssstate error - The picture failed, or there is none, and the initials show.
|
|
44
|
+
* @cssstate loaded - The picture arrived.
|
|
45
|
+
* @cssstate loading - The picture is on its way.
|
|
33
46
|
*/
|
|
34
47
|
export declare class HelixHeadlessAvatar extends HelixElement {
|
|
35
48
|
/**
|
|
@@ -43,6 +56,23 @@ export declare class HelixHeadlessAvatar extends HelixElement {
|
|
|
43
56
|
* same idea.
|
|
44
57
|
*/
|
|
45
58
|
fallbackDelay?: number;
|
|
59
|
+
/**
|
|
60
|
+
* The letters shown where no picture loaded, such as `GH`, in place of the
|
|
61
|
+
* ones taken from `name`.
|
|
62
|
+
*
|
|
63
|
+
* For a name whose initials are not its first and last letters, or an
|
|
64
|
+
* entity with a short mark of its own. Absent, the first letters of the
|
|
65
|
+
* first and last words of `name` are shown.
|
|
66
|
+
*/
|
|
67
|
+
initials?: string;
|
|
68
|
+
/**
|
|
69
|
+
* When the browser fetches the picture: `lazy` waits until it is near the
|
|
70
|
+
* screen, as an `<img loading="lazy">` does, and `eager` fetches it at once.
|
|
71
|
+
*
|
|
72
|
+
* Absent is the browser's own default, which is `eager`. `lazy` suits a long
|
|
73
|
+
* list of people, most of them off screen.
|
|
74
|
+
*/
|
|
75
|
+
loading?: 'eager' | 'lazy';
|
|
46
76
|
/**
|
|
47
77
|
* Name of the person or entity.
|
|
48
78
|
*
|
|
@@ -45,6 +45,9 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
|
|
|
45
45
|
label: this.name,
|
|
46
46
|
role: this.name === '' ? '' : 'img',
|
|
47
47
|
});
|
|
48
|
+
this.toggleState('error', this.status === 'error');
|
|
49
|
+
this.toggleState('loaded', this.status === 'loaded');
|
|
50
|
+
this.toggleState('loading', this.status === 'loading');
|
|
48
51
|
}
|
|
49
52
|
firstUpdated(changed) {
|
|
50
53
|
super.firstUpdated(changed);
|
|
@@ -91,6 +94,7 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
|
|
|
91
94
|
part="image"
|
|
92
95
|
src=${this.src}
|
|
93
96
|
alt=""
|
|
97
|
+
loading=${this.loading ?? nothing}
|
|
94
98
|
?hidden=${standIn}
|
|
95
99
|
@error=${this.handleError}
|
|
96
100
|
@load=${this.handleLoad}
|
|
@@ -100,13 +104,19 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
|
|
|
100
104
|
}
|
|
101
105
|
renderInitials() {
|
|
102
106
|
return html `<slot>
|
|
103
|
-
<span part="initials" aria-hidden="true">${initialsOf(this.name)}</span>
|
|
107
|
+
<span part="initials" aria-hidden="true">${this.initials ?? initialsOf(this.name)}</span>
|
|
104
108
|
</slot>`;
|
|
105
109
|
}
|
|
106
110
|
};
|
|
107
111
|
__decorate([
|
|
108
112
|
property({ attribute: 'fallback-delay', type: Number })
|
|
109
113
|
], HelixHeadlessAvatar.prototype, "fallbackDelay", void 0);
|
|
114
|
+
__decorate([
|
|
115
|
+
property()
|
|
116
|
+
], HelixHeadlessAvatar.prototype, "initials", void 0);
|
|
117
|
+
__decorate([
|
|
118
|
+
property()
|
|
119
|
+
], HelixHeadlessAvatar.prototype, "loading", void 0);
|
|
110
120
|
__decorate([
|
|
111
121
|
property()
|
|
112
122
|
], HelixHeadlessAvatar.prototype, "name", void 0);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Whether the value counts nothing, in which case there is no mark. */
|
|
2
|
+
export declare const badgeBlank: (given: string) => boolean;
|
|
3
|
+
/** Whether the count is past `max`, which the mark shows as `{max}+`. */
|
|
4
|
+
export declare const badgeCapped: (given: string, max: number | undefined) => boolean;
|
|
5
|
+
/**
|
|
6
|
+
* What the mark reads once the cap has been applied: the value as given, or
|
|
7
|
+
* written with `options` in `locale` where they are set and it is a number.
|
|
8
|
+
*/
|
|
9
|
+
export declare const badgeText: (given: string, max: number | undefined, locale: string, options: Intl.NumberFormatOptions | undefined) => string;
|
|
10
|
+
/**
|
|
11
|
+
* What a reader hears for the mark: `label` with `{count}` filled, or the text
|
|
12
|
+
* alone, and nothing for a blank mark or an unnamed dot.
|
|
13
|
+
*/
|
|
14
|
+
export declare const badgeWords: (text: string, label: string, blank: boolean) => string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { fillTemplate, formatNumber } from '@fusion.dev/helix-core';
|
|
2
|
+
export const badgeBlank = (given) => given.trim() !== '' && Number(given) === 0;
|
|
3
|
+
export const badgeCapped = (given, max) => {
|
|
4
|
+
const count = Number(given);
|
|
5
|
+
return max !== undefined && Number.isFinite(count) && count > max;
|
|
6
|
+
};
|
|
7
|
+
export const badgeText = (given, max, locale, options) => {
|
|
8
|
+
const write = (count) => options ? formatNumber(count, locale, options) : String(count);
|
|
9
|
+
if (badgeCapped(given, max)) {
|
|
10
|
+
return `${write(max)}+`;
|
|
11
|
+
}
|
|
12
|
+
const count = Number(given);
|
|
13
|
+
return options && given.trim() !== '' && Number.isFinite(count) ? write(count) : given;
|
|
14
|
+
};
|
|
15
|
+
export const badgeWords = (text, label, blank) => {
|
|
16
|
+
if (blank || (text === '' && label === '')) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
return fillTemplate(label, { count: text }) || text;
|
|
20
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type TemplateResult } from 'lit';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A count or a dot pinned to the corner of another element.
|
|
5
5
|
*
|
|
@@ -14,15 +14,20 @@ import { type TemplateResult } from 'lit';
|
|
|
14
14
|
* - Any other value shows the value. Above `max`, the indicator shows `{max}+`,
|
|
15
15
|
* so its width stays the same as the count grows.
|
|
16
16
|
*
|
|
17
|
+
* `format-options` writes a count with `Intl.NumberFormat`, in `locale`:
|
|
18
|
+
* `format-options='{"notation":"compact"}'` shows 1,200 as `1.2K`. Absent, the
|
|
19
|
+
* count is shown as it was given.
|
|
20
|
+
*
|
|
17
21
|
* A count is announced from its own text, and `label` replaces that with a
|
|
18
22
|
* fuller name, such as `4 unread`. A dot needs a `label`. Without one, the dot
|
|
19
23
|
* is a colored circle that screen readers do not announce.
|
|
20
24
|
*
|
|
21
|
-
* **A badge wrapped around a control
|
|
22
|
-
*
|
|
23
|
-
* so focusing
|
|
24
|
-
*
|
|
25
|
-
*
|
|
25
|
+
* **A badge wrapped around a control describes it.** The control is the first
|
|
26
|
+
* element in the badge that takes focus, and its description is the badge's
|
|
27
|
+
* words, so focusing `<helix-badge value="8" label="{count} unread"><button>Inbox
|
|
28
|
+
* </button></helix-badge>` announces "Inbox, button, 8 unread", current as the
|
|
29
|
+
* count changes. A control that already has a description keeps its own. The
|
|
30
|
+
* count is also a status of its own, read when it changes.
|
|
26
31
|
*
|
|
27
32
|
* **Put the badge inside the control to have its count read with the
|
|
28
33
|
* control's name**, as Web Awesome and Shoelace do: `<button>Inbox
|
|
@@ -39,8 +44,20 @@ import { type TemplateResult } from 'lit';
|
|
|
39
44
|
* @slot - The element being decorated.
|
|
40
45
|
*
|
|
41
46
|
* @csspart indicator - The count, or the dot when there is no value.
|
|
47
|
+
*
|
|
48
|
+
* @cssstate blank - The value is zero, so there is no mark.
|
|
49
|
+
* @cssstate capped - The count is past `max`, so the mark shows `{max}+`.
|
|
50
|
+
* @cssstate dot - There is no value, so the mark is a dot.
|
|
42
51
|
*/
|
|
43
52
|
export declare class HelixHeadlessBadge extends HelixElement {
|
|
53
|
+
/**
|
|
54
|
+
* `Intl.NumberFormat` options a count is written with, such as
|
|
55
|
+
* `{"notation":"compact"}` for `1.2K`, written as JSON in the attribute.
|
|
56
|
+
*
|
|
57
|
+
* Absent, a count is shown as it was given. Text that is not a number is
|
|
58
|
+
* shown as it is either way.
|
|
59
|
+
*/
|
|
60
|
+
formatOptions?: Intl.NumberFormatOptions;
|
|
44
61
|
/**
|
|
45
62
|
* The badge's name, read by screen readers.
|
|
46
63
|
*
|
|
@@ -49,6 +66,12 @@ export declare class HelixHeadlessBadge extends HelixElement {
|
|
|
49
66
|
* stays current as `value` changes, with no label of yours to keep in step.
|
|
50
67
|
*/
|
|
51
68
|
label: string;
|
|
69
|
+
/**
|
|
70
|
+
* The locale a count is written in under `format-options`, such as `de`.
|
|
71
|
+
*
|
|
72
|
+
* Absent uses the runtime's own.
|
|
73
|
+
*/
|
|
74
|
+
locale: string;
|
|
52
75
|
/**
|
|
53
76
|
* The largest number the badge shows.
|
|
54
77
|
*
|
|
@@ -75,8 +98,36 @@ export declare class HelixHeadlessBadge extends HelixElement {
|
|
|
75
98
|
private get given();
|
|
76
99
|
/** Whether the value counts nothing, in which case there is no mark. */
|
|
77
100
|
private get blank();
|
|
101
|
+
/** Whether the count is past `max`, which the mark shows as `{max}+`. */
|
|
102
|
+
private get capped();
|
|
78
103
|
/** What the indicator reads, once the cap has been applied. */
|
|
79
104
|
private get text();
|
|
105
|
+
/** What a reader hears for the mark, or nothing for a blank or unnamed one. */
|
|
106
|
+
private get words();
|
|
107
|
+
/** The control the badge describes, while it describes one. */
|
|
108
|
+
private described;
|
|
109
|
+
/**
|
|
110
|
+
* The first element the badge wraps that takes focus: one with a tab stop,
|
|
111
|
+
* or a component that hands its focus on.
|
|
112
|
+
*/
|
|
113
|
+
private wrapped;
|
|
114
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
115
|
+
/**
|
|
116
|
+
* Points the wrapped control's description at the badge, which carries its
|
|
117
|
+
* words as its own label, or takes the pointer back.
|
|
118
|
+
*
|
|
119
|
+
* **The badge itself and not the count**, because a reference from the
|
|
120
|
+
* control into the badge's shadow root is one the platform drops, and the
|
|
121
|
+
* badge is in the control's own tree. A control the page described is left
|
|
122
|
+
* alone.
|
|
123
|
+
*/
|
|
124
|
+
private describe;
|
|
125
|
+
private undescribe;
|
|
126
|
+
private readonly handleSlotchange;
|
|
127
|
+
disconnectedCallback(): void;
|
|
128
|
+
connectedCallback(): void;
|
|
129
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
130
|
+
protected updated(changed: PropertyValues): void;
|
|
80
131
|
protected render(): TemplateResult;
|
|
81
132
|
}
|
|
82
133
|
declare global {
|
|
@@ -4,46 +4,115 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement,
|
|
7
|
+
import { customElement, focusTarget, HelixElement } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
import { badgeBlank, badgeCapped, badgeText, badgeWords } from '../count.js';
|
|
10
11
|
let HelixHeadlessBadge = class HelixHeadlessBadge extends HelixElement {
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
13
14
|
this.label = '';
|
|
15
|
+
this.locale = '';
|
|
14
16
|
this.value = '';
|
|
17
|
+
this.handleSlotchange = () => {
|
|
18
|
+
this.describe();
|
|
19
|
+
};
|
|
15
20
|
}
|
|
16
21
|
get given() {
|
|
17
22
|
return String(this.value ?? '');
|
|
18
23
|
}
|
|
19
24
|
get blank() {
|
|
20
|
-
return
|
|
25
|
+
return badgeBlank(this.given);
|
|
26
|
+
}
|
|
27
|
+
get capped() {
|
|
28
|
+
return badgeCapped(this.given, this.max);
|
|
21
29
|
}
|
|
22
30
|
get text() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
return badgeText(this.given, this.max, this.locale, this.formatOptions);
|
|
32
|
+
}
|
|
33
|
+
get words() {
|
|
34
|
+
return badgeWords(this.text, this.label, this.blank);
|
|
35
|
+
}
|
|
36
|
+
wrapped() {
|
|
37
|
+
const found = this.renderRoot
|
|
38
|
+
.querySelector('slot:not([name])')
|
|
39
|
+
?.assignedElements({ flatten: true })
|
|
40
|
+
.find((element) => element instanceof HTMLElement &&
|
|
41
|
+
(element.tabIndex >= 0 || element.shadowRoot?.delegatesFocus === true));
|
|
42
|
+
return found && focusTarget(found);
|
|
43
|
+
}
|
|
44
|
+
firstUpdated(changed) {
|
|
45
|
+
super.firstUpdated(changed);
|
|
46
|
+
requestAnimationFrame(() => this.describe());
|
|
47
|
+
}
|
|
48
|
+
describe() {
|
|
49
|
+
const words = this.words;
|
|
50
|
+
const control = words === '' ? undefined : this.wrapped();
|
|
51
|
+
if (this.described && this.described !== control) {
|
|
52
|
+
this.undescribe();
|
|
53
|
+
}
|
|
54
|
+
if (!control || !('ariaDescribedByElements' in control)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const own = control.getAttribute('aria-describedby') || control.ariaDescribedByElements?.length;
|
|
58
|
+
if (control !== this.described && own) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.internals.ariaLabel = words;
|
|
62
|
+
control.ariaDescribedByElements = [this];
|
|
63
|
+
this.described = control;
|
|
64
|
+
}
|
|
65
|
+
undescribe() {
|
|
66
|
+
if (this.described?.ariaDescribedByElements?.includes(this)) {
|
|
67
|
+
this.described.ariaDescribedByElements = null;
|
|
26
68
|
}
|
|
27
|
-
|
|
69
|
+
this.described = undefined;
|
|
70
|
+
this.internals.ariaLabel = null;
|
|
71
|
+
}
|
|
72
|
+
disconnectedCallback() {
|
|
73
|
+
super.disconnectedCallback();
|
|
74
|
+
this.undescribe();
|
|
75
|
+
}
|
|
76
|
+
connectedCallback() {
|
|
77
|
+
super.connectedCallback();
|
|
78
|
+
if (this.hasUpdated) {
|
|
79
|
+
this.describe();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
willUpdate(changed) {
|
|
83
|
+
super.willUpdate(changed);
|
|
84
|
+
this.toggleState('capped', this.capped);
|
|
85
|
+
this.toggleState('dot', this.given.trim() === '');
|
|
86
|
+
this.toggleState('blank', this.blank);
|
|
87
|
+
}
|
|
88
|
+
updated(changed) {
|
|
89
|
+
super.updated(changed);
|
|
90
|
+
this.describe();
|
|
28
91
|
}
|
|
29
92
|
render() {
|
|
30
93
|
const blank = this.blank;
|
|
31
94
|
const text = this.text;
|
|
32
95
|
const announced = !blank && (text !== '' || this.label !== '');
|
|
33
|
-
return html `<slot></slot>
|
|
96
|
+
return html `<slot @slotchange=${this.handleSlotchange}></slot>
|
|
34
97
|
<span
|
|
35
98
|
part="indicator"
|
|
36
99
|
data-blank=${blank ? '' : nothing}
|
|
37
100
|
data-single=${text.length <= 1 ? '' : nothing}
|
|
38
101
|
role="status"
|
|
39
|
-
aria-label=${announced ?
|
|
102
|
+
aria-label=${announced ? this.words : nothing}
|
|
40
103
|
>${blank ? html `<span aria-hidden="true">${text}</span>` : text}</span
|
|
41
104
|
>`;
|
|
42
105
|
}
|
|
43
106
|
};
|
|
107
|
+
__decorate([
|
|
108
|
+
property({ attribute: 'format-options', type: Object })
|
|
109
|
+
], HelixHeadlessBadge.prototype, "formatOptions", void 0);
|
|
44
110
|
__decorate([
|
|
45
111
|
property()
|
|
46
112
|
], HelixHeadlessBadge.prototype, "label", void 0);
|
|
113
|
+
__decorate([
|
|
114
|
+
property()
|
|
115
|
+
], HelixHeadlessBadge.prototype, "locale", void 0);
|
|
47
116
|
__decorate([
|
|
48
117
|
property({ type: Number })
|
|
49
118
|
], HelixHeadlessBadge.prototype, "max", void 0);
|
|
@@ -4,10 +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 { byRow, CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesNames, ticks, unbroken, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { byRow, CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, seriesNames, ticks, unbroken, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
-
import { stackEnds, stackSpans } from '../stack.js';
|
|
10
|
+
import { stackEnds, stackedReadings, stackSpans } from '../stack.js';
|
|
11
11
|
import '../../tooltip/index.js';
|
|
12
12
|
let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource(HelixElement) {
|
|
13
13
|
constructor() {
|
|
@@ -38,23 +38,13 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
38
38
|
return html `<div id=${CHART_PLOT} part="plot"></div>`;
|
|
39
39
|
}
|
|
40
40
|
const scaled = this.scaled;
|
|
41
|
-
const own = (one) => scaled.has(one.name
|
|
41
|
+
const own = (one) => scaled.has(seriesKey(one.name));
|
|
42
42
|
const shown = series.filter((one) => this.showsSeries(one.name));
|
|
43
43
|
const values = shown.flatMap((one) => one.points.map((point) => point.value));
|
|
44
44
|
const lined = this.lined;
|
|
45
|
-
const readingsOf = (group) =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
const columns = group.filter((one) => !lined.has(one.name.trim().toLowerCase()));
|
|
50
|
-
const slots = columns.map((one) => byRow(one, categories.length));
|
|
51
|
-
return [
|
|
52
|
-
...group
|
|
53
|
-
.filter((one) => lined.has(one.name.trim().toLowerCase()))
|
|
54
|
-
.flatMap((one) => one.points.map((point) => point.value)),
|
|
55
|
-
...stackEnds(categories.map((_, at) => slots.map((one) => one[at]?.value))),
|
|
56
|
-
];
|
|
57
|
-
};
|
|
45
|
+
const readingsOf = (group) => this.stacked
|
|
46
|
+
? stackedReadings(group, categories.length, (one) => lined.has(seriesKey(one.name)))
|
|
47
|
+
: group.flatMap((one) => one.points.map((point) => point.value));
|
|
58
48
|
const on = (which) => {
|
|
59
49
|
const found = readingsOf(shown.filter(which));
|
|
60
50
|
return found.length > 0 ? found : values.length > 0 ? values : [0];
|
|
@@ -96,11 +86,11 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
96
86
|
const slot = 100 / categories.length;
|
|
97
87
|
const lined = this.lined;
|
|
98
88
|
const scaled = this.scaled;
|
|
99
|
-
const own = (one) => scaled.has(one.name
|
|
89
|
+
const own = (one) => scaled.has(seriesKey(one.name));
|
|
100
90
|
const against = (one) => z !== undefined && own(one) ? z : y;
|
|
101
91
|
const columns = series
|
|
102
92
|
.map((one, index) => ({ one, slots: byRow(one, categories.length), tone: index }))
|
|
103
|
-
.filter(({ one }) => !lined.has(one.name
|
|
93
|
+
.filter(({ one }) => !lined.has(seriesKey(one.name)) && this.showsSeries(one.name));
|
|
104
94
|
const abreast = this.stacked ? 1 : columns.length;
|
|
105
95
|
const stride = (slot * 0.72) / Math.max(abreast, 1);
|
|
106
96
|
const gap = abreast > 1 ? stride * 0.08 : 0;
|
|
@@ -178,7 +168,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
178
168
|
: bar(point.value, index, depth, tone, against(one));
|
|
179
169
|
})}
|
|
180
170
|
</g>`)}
|
|
181
|
-
${series.map((one) => lined.has(one.name
|
|
171
|
+
${series.map((one) => lined.has(seriesKey(one.name)) && this.showsSeries(one.name)
|
|
182
172
|
? this.renderLine(one, series.indexOf(one), slot, against(one), sideways)
|
|
183
173
|
: nothing)}
|
|
184
174
|
</svg>
|
|
@@ -269,8 +259,9 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
269
259
|
.map((one) => byRow(one, this.readings)[at]?.value)
|
|
270
260
|
.filter((one) => one !== undefined);
|
|
271
261
|
const values = this.stacked ? stackEnds([reached]) : reached;
|
|
262
|
+
const lined = this.lined;
|
|
272
263
|
const all = this.stacked
|
|
273
|
-
?
|
|
264
|
+
? stackedReadings(shown, this.readings, (one) => lined.has(seriesKey(one.name)))
|
|
274
265
|
: shown.flatMap((one) => one.points.map((point) => point.value));
|
|
275
266
|
const [low, high] = extent(all.length > 0 ? all : [0]);
|
|
276
267
|
const domain = [Math.min(0, low), Math.max(0, high)];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Series } from '@fusion.dev/helix-core';
|
|
1
2
|
/** Where a column starts and ends along the measure, in the data's own units. */
|
|
2
3
|
export type Span = readonly [from: number, to: number];
|
|
3
4
|
/**
|
|
@@ -13,3 +14,12 @@ export declare const stackSpans: (values: readonly (number | undefined)[]) => (S
|
|
|
13
14
|
* of negatives. `categories` holds each category's readings, one per column.
|
|
14
15
|
*/
|
|
15
16
|
export declare const stackEnds: (categories: readonly (readonly (number | undefined)[])[]) => number[];
|
|
17
|
+
/**
|
|
18
|
+
* The readings a stacked scale has to hold, over `count` categories: every
|
|
19
|
+
* reading of a series drawn as a line, which `lined` says, and the top and
|
|
20
|
+
* foot of each category's stack of the others.
|
|
21
|
+
*
|
|
22
|
+
* The plot's scale and the tooltip's placing ask the same question, and
|
|
23
|
+
* answered apart they disagreed about the lines.
|
|
24
|
+
*/
|
|
25
|
+
export declare const stackedReadings: (group: readonly Series[], count: number, lined: (one: Series) => boolean) => number[];
|
package/dist/bar-chart/stack.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { byRow } from '@fusion.dev/helix-core';
|
|
1
2
|
export const stackSpans = (values) => {
|
|
2
3
|
let up = 0;
|
|
3
4
|
let down = 0;
|
|
@@ -17,3 +18,10 @@ export const stackSpans = (values) => {
|
|
|
17
18
|
});
|
|
18
19
|
};
|
|
19
20
|
export const stackEnds = (categories) => categories.flatMap((values) => stackSpans(values).flatMap((span) => (span === undefined ? [] : [span[1]])));
|
|
21
|
+
export const stackedReadings = (group, count, lined) => {
|
|
22
|
+
const slots = group.filter((one) => !lined(one)).map((one) => byRow(one, count));
|
|
23
|
+
return [
|
|
24
|
+
...group.filter(lined).flatMap((one) => one.points.map((point) => point.value)),
|
|
25
|
+
...stackEnds(Array.from({ length: count }, (_, at) => slots.map((one) => one[at]?.value))),
|
|
26
|
+
];
|
|
27
|
+
};
|
|
@@ -1,16 +1,36 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { type CSSResultGroup, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A passage set off from the prose around it.
|
|
5
5
|
*
|
|
6
6
|
* @description
|
|
7
|
-
* Renders a
|
|
7
|
+
* Renders a figure holding the `<blockquote>` and a caption for the
|
|
8
8
|
* attribution, the structure the HTML spec describes. The attribution sits
|
|
9
9
|
* outside the quotation because it is about the quotation, and it names the
|
|
10
10
|
* figure, so a screen reader reads the source as the figure's caption.
|
|
11
11
|
*
|
|
12
|
-
* The figure
|
|
13
|
-
*
|
|
12
|
+
* **The figure is a `<div role="figure">`**, so the headless tier draws no
|
|
13
|
+
* space around the quotation. A `<figure>` takes a 40px indent and a line of
|
|
14
|
+
* space above and below from the browser's own sheet, which every page had to
|
|
15
|
+
* reset. The `<blockquote>` keeps its own margins, as a bare one does. A
|
|
16
|
+
* screen reader meets the same figure, named by its caption.
|
|
17
|
+
*
|
|
18
|
+
* **A figure only while there is an attribution.** With nothing in the caption
|
|
19
|
+
* the figure has no name and nothing to say, so the role and its name are
|
|
20
|
+
* dropped and a reader meets the quotation alone. A server cannot see what is
|
|
21
|
+
* slotted, so it serves the figure, and the client drops it after hydration;
|
|
22
|
+
* an `attribution` written as words is served exactly.
|
|
23
|
+
*
|
|
24
|
+
* **Quotation marks follow the language**, under `marks`. The opening mark is
|
|
25
|
+
* the one the browser sets for a `<q>` in the element's language, „ under
|
|
26
|
+
* `lang="de"` and « under `lang="fr"`, and a `Quote` inside the passage takes
|
|
27
|
+
* the inner marks. The mark is drawn, not read: a screen reader hears the
|
|
28
|
+
* passage. A passage under `marks` that starts with a mark typed into the text
|
|
29
|
+
* would show two, and warns once, with the runtime kind `typed-marks`.
|
|
30
|
+
*
|
|
31
|
+
* **`cite` is the source's URL**, which the browser keeps and does not show.
|
|
32
|
+
* Words in it, such as the author's name, warn once, with the runtime kind
|
|
33
|
+
* `cite-not-url`.
|
|
14
34
|
*
|
|
15
35
|
* For a quotation inside a sentence, use `Quote`.
|
|
16
36
|
*
|
|
@@ -21,17 +41,37 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
21
41
|
* @documentation https://fusion.dev/helix/components/blockquote
|
|
22
42
|
*
|
|
23
43
|
* @slot - The quoted passage.
|
|
24
|
-
* @slot attribution - Who said it, and where.
|
|
44
|
+
* @slot attribution - Who said it, and where. Replaces the words of `attribution`.
|
|
25
45
|
*
|
|
26
|
-
* @csspart attribution - The
|
|
46
|
+
* @csspart attribution - The caption carrying the source.
|
|
27
47
|
* @csspart blockquote - The quotation.
|
|
28
|
-
* @csspart figure - The
|
|
48
|
+
* @csspart figure - The figure holding the quotation and its attribution, a `<div>` with `role="figure"` while the attribution has words.
|
|
29
49
|
*/
|
|
30
50
|
export declare class HelixHeadlessBlockquote extends HelixElement {
|
|
51
|
+
static styles: CSSResultGroup;
|
|
31
52
|
/**
|
|
32
|
-
*
|
|
53
|
+
* Who said it, and where, as words, such as "Maria Lopez, operations
|
|
54
|
+
* manager". The `attribution` slot replaces them, for markup such as a link.
|
|
55
|
+
*
|
|
56
|
+
* Words are served with the figure they name, where a server cannot see a
|
|
57
|
+
* slotted attribution.
|
|
58
|
+
*/
|
|
59
|
+
attribution: string;
|
|
60
|
+
/**
|
|
61
|
+
* The URL of the source the passage came from. Who said it goes in
|
|
62
|
+
* `attribution`: a `cite` with words in it warns once, with the runtime kind
|
|
63
|
+
* `cite-not-url`.
|
|
33
64
|
*/
|
|
34
65
|
cite: string;
|
|
66
|
+
/**
|
|
67
|
+
* Whether to draw an opening quotation mark before the passage, in the
|
|
68
|
+
* element's language. Leave the marks out of the text.
|
|
69
|
+
*/
|
|
70
|
+
marks: boolean;
|
|
71
|
+
/** Whether this blockquote has said its passage starts with a typed mark, so it says so once. */
|
|
72
|
+
private warned;
|
|
73
|
+
/** Whether this blockquote has said its `cite` holds words, so it says so once. */
|
|
74
|
+
private citeWarned;
|
|
35
75
|
/**
|
|
36
76
|
* Says on the caption whether there is an attribution in it.
|
|
37
77
|
*
|
|
@@ -44,8 +84,26 @@ export declare class HelixHeadlessBlockquote extends HelixElement {
|
|
|
44
84
|
* rendered, which React reports on hydration.
|
|
45
85
|
*/
|
|
46
86
|
private markEmpty;
|
|
87
|
+
/**
|
|
88
|
+
* Reads the passage for a mark typed at its start, which `marks` would
|
|
89
|
+
* double. Only the start: the mark drawn is an opening one.
|
|
90
|
+
*/
|
|
91
|
+
private readonly readPassage;
|
|
92
|
+
/**
|
|
93
|
+
* Reads `cite` for words where the source's URL belongs, the common mistake
|
|
94
|
+
* of naming the author there. A URL holds no spaces, so words with a space
|
|
95
|
+
* between them are enough to tell.
|
|
96
|
+
*/
|
|
97
|
+
private readCite;
|
|
98
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
47
99
|
protected updated(changed: PropertyValues): void;
|
|
48
100
|
protected render(): TemplateResult;
|
|
101
|
+
/**
|
|
102
|
+
* The caption, with the words of `attribution` as its slot's fallback,
|
|
103
|
+
* behind a seam a tier can move. The words are in an element, so the region
|
|
104
|
+
* counts them as its own.
|
|
105
|
+
*/
|
|
106
|
+
protected renderAttribution(): TemplateResult;
|
|
49
107
|
}
|
|
50
108
|
declare global {
|
|
51
109
|
interface HTMLElementTagNameMap {
|