ngwr 14.7.0 → 14.8.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/bar-chart/styles/_index.scss +1 -0
- package/calendar-heatmap/styles/_index.scss +1 -0
- package/cascader/styles/_rules.scss +86 -14
- package/date-picker/styles/_index.scss +30 -0
- package/density/styles/_index.scss +4 -2
- package/donut-chart/styles/_index.scss +10 -0
- package/dropdown/styles/_index.scss +67 -5
- package/event-calendar/styles/_index.scss +209 -35
- package/fesm2022/ngwr-bar-chart.mjs +29 -4
- package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +59 -4
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +12 -2
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +705 -46
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +46 -4
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +166 -17
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +9 -2
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +52 -1
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +33 -4
- package/fesm2022/ngwr-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ar.mjs +2 -0
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-cs.mjs +2 -0
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-de.mjs +2 -0
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +5 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +2 -0
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-fr.mjs +2 -0
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-he.mjs +2 -0
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-hi.mjs +2 -0
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-id.mjs +2 -0
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-it.mjs +2 -0
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ja.mjs +2 -0
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ko.mjs +2 -0
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-nl.mjs +2 -0
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pl.mjs +2 -0
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pt.mjs +2 -0
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +2 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +2 -0
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-tr.mjs +2 -0
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-uk.mjs +2 -0
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-vi.mjs +2 -0
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh-TW.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +12 -0
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +16 -5
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group-testing.mjs +7 -3
- package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +24 -4
- package/fesm2022/ngwr-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-page-header.mjs +10 -2
- package/fesm2022/ngwr-page-header.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +569 -7
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +7 -0
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +82 -8
- package/fesm2022/ngwr-sparkline.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +1 -1
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +7 -0
- package/fesm2022/ngwr-toolbar.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/form/styles/_index.scss +11 -1
- package/gauge/styles/_index.scss +1 -0
- package/i18n/ar.json +3 -1
- package/i18n/cs.json +3 -1
- package/i18n/de.json +3 -1
- package/i18n/en.json +3 -1
- package/i18n/es.json +3 -1
- package/i18n/fr.json +3 -1
- package/i18n/he.json +3 -1
- package/i18n/hi.json +3 -1
- package/i18n/id.json +3 -1
- package/i18n/it.json +3 -1
- package/i18n/ja.json +3 -1
- package/i18n/ko.json +3 -1
- package/i18n/nl.json +3 -1
- package/i18n/pl.json +3 -1
- package/i18n/pt.json +3 -1
- package/i18n/ru.json +3 -1
- package/i18n/sv.json +3 -1
- package/i18n/tr.json +3 -1
- package/i18n/uk.json +3 -1
- package/i18n/vi.json +3 -1
- package/i18n/zh-TW.json +3 -1
- package/i18n/zh.json +3 -1
- package/input/styles/_index.scss +19 -0
- package/input-number/styles/_index.scss +69 -0
- package/line-chart/styles/_index.scss +30 -2
- package/llms-full.txt +3 -3
- package/meter-group/styles/_index.scss +1 -0
- package/overlay/styles/_arrow.scss +27 -2
- package/package.json +1 -1
- package/page-header/styles/_index.scss +37 -1
- package/pagination/styles/_index.scss +9 -5
- package/popover/styles/_index.scss +73 -5
- package/select/styles/_index.scss +48 -9
- package/sidebar/styles/_index.scss +34 -2
- package/sparkline/styles/_index.scss +19 -0
- package/toolbar/styles/_index.scss +35 -1
- package/tree/styles/_index.scss +45 -6
- package/types/ngwr-bar-chart.d.ts +19 -1
- package/types/ngwr-calendar-heatmap.d.ts +29 -1
- package/types/ngwr-checkbox.d.ts +2 -0
- package/types/ngwr-date-picker.d.ts +308 -43
- package/types/ngwr-donut-chart.d.ts +24 -1
- package/types/ngwr-dropdown.d.ts +22 -2
- package/types/ngwr-event-calendar.d.ts +8 -0
- package/types/ngwr-form.d.ts +35 -5
- package/types/ngwr-gauge.d.ts +20 -1
- package/types/ngwr-input-number.d.ts +7 -0
- package/types/ngwr-line-chart.d.ts +9 -1
- package/types/ngwr-meter-group-testing.d.ts +3 -2
- package/types/ngwr-meter-group.d.ts +14 -1
- package/types/ngwr-page-header.d.ts +10 -2
- package/types/ngwr-popover.d.ts +154 -3
- package/types/ngwr-sidebar.d.ts +7 -0
- package/types/ngwr-sparkline.d.ts +43 -1
- package/types/ngwr-toolbar.d.ts +7 -0
- package/types/ngwr-version.d.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-meter-group-testing.mjs","sources":["../../../projects/lib/meter-group/testing/wr-meter-group-harness.ts","../../../projects/lib/meter-group/testing/ngwr-meter-group-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrMeterGroupHarnessFilters, WrMeterGroupSlice } from './interfaces';\n\n/** The `width: <n>%` the component writes onto a band, out of its inline `style`. */\nconst SLICE_WIDTH = /(?:^|;)\\s*width\\s*:\\s*([\\d.]+)%/;\n\n/**\n * Test harness for `<wr-meter-group>` — one bar divided into labelled bands.\n *\n * **The bar is a single `progressbar`, and its value is the TOTAL.** The bands\n * themselves announce nothing: they carry a `title` for a mouse and their share as an
|
|
1
|
+
{"version":3,"file":"ngwr-meter-group-testing.mjs","sources":["../../../projects/lib/meter-group/testing/wr-meter-group-harness.ts","../../../projects/lib/meter-group/testing/ngwr-meter-group-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrMeterGroupHarnessFilters, WrMeterGroupSlice } from './interfaces';\n\n/** The `width: <n>%` the component writes onto a band, out of its inline `style`. */\nconst SLICE_WIDTH = /(?:^|;)\\s*width\\s*:\\s*([\\d.]+)%/;\n\n/**\n * Test harness for `<wr-meter-group>` — one bar divided into labelled bands.\n *\n * **The bar is a single `progressbar`, and its value is the TOTAL.** The bands\n * themselves announce nothing: they carry a hover tooltip (or, with `tooltip` off, a\n * `title`) for a mouse and their share as an inline width, and the legend is where\n * their labels and values are readable. So a\n * spec that wants \"how much of each\" reads {@link getSlices} for the shares or\n * {@link getLegendLabels} / {@link getLegendValues} for what is printed, and one that\n * wants \"how full\" reads {@link getValue}.\n *\n * **A band's share is read off the `style` ATTRIBUTE, not through `getCssValue()`**,\n * and the difference is not cosmetic: `getCssValue()` is `getComputedStyle()`, and\n * `width` resolves to the USED value — so the declared `30%` comes straight back in\n * jsdom and arrives as `180px` on a 600px bar in a real browser, and the same harness\n * answered 30 here and 180 under a browser runner with nothing to say which one you\n * got.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrMeterGroupHarness extends ComponentHarness {\n static hostSelector = 'wr-meter-group';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrMeterGroupHarnessFilters = {}): HarnessPredicate<WrMeterGroupHarness> {\n return new HarnessPredicate(WrMeterGroupHarness, options)\n .addOption('ariaLabel', options.ariaLabel, (harness, label) =>\n HarnessPredicate.stringMatches(harness.getAccessibleName(), label)\n )\n .addOption('sliceLabel', options.sliceLabel, async (harness, label) => {\n for (const printed of await harness.getLegendLabels()) {\n if (await HarnessPredicate.stringMatches(printed, label)) return true;\n }\n return false;\n });\n }\n\n private readonly bar = this.locatorFor('.wr-meter-group__bar');\n\n /** The role the bar announces — `progressbar`, for the total. */\n async getRole(): Promise<string | null> {\n return (await this.bar()).getAttribute('role');\n }\n\n /** The bar's accessible name. */\n async getAccessibleName(): Promise<string | null> {\n return (await this.bar()).getAttribute('aria-label');\n }\n\n /** The total the bands add up to, from `aria-valuenow`. */\n async getValue(): Promise<number> {\n return Number(await (await this.bar()).getAttribute('aria-valuenow'));\n }\n\n /** The full capacity, from `aria-valuemax` — given, or the sum of the bands. */\n async getMax(): Promise<number> {\n return Number(await (await this.bar()).getAttribute('aria-valuemax'));\n }\n\n /** The bands, in order, with the share of the bar each takes. */\n async getSlices(): Promise<WrMeterGroupSlice[]> {\n const slices = await this.locatorForAll('.wr-meter-group__slice')();\n\n return Promise.all(\n slices.map(async slice => {\n // `data-label`, which the band carries whatever `tooltip` says. The `title`\n // this used to read is written only while the tooltip is off, so reading it\n // would answer `null` for every band of a default meter.\n const label = await slice.getAttribute('data-label');\n return { label, percent: WrMeterGroupHarness.percentOf(label, await slice.getAttribute('style')) };\n })\n );\n }\n\n /** Parse one band's declared share. See the class note on why this is not `getCssValue()`. */\n private static percentOf(label: string | null, style: string | null): number {\n const match = SLICE_WIDTH.exec(style ?? '');\n if (!match) {\n throw new Error(\n `WrMeterGroupHarness.getSlices(): the band ${label === null ? '(untitled)' : `\"${label}\"`} carries no ` +\n `inline width percentage (style: \"${style ?? ''}\"). The component writes one for every band, since the ` +\n 'total always falls back to 1 — so its absence is the bug, and reporting 0 would read as an empty band.'\n );\n }\n return Number.parseFloat(match[1]);\n }\n\n /** Whether the legend is rendered (`showLegend`, and at least one band). */\n async hasLegend(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-meter-group__legend')()) !== null;\n }\n\n /** The legend's labels, in order. */\n async getLegendLabels(): Promise<string[]> {\n const labels = await this.locatorForAll('.wr-meter-group__legend-label')();\n return Promise.all(labels.map(label => label.text()));\n }\n\n /** The legend's values, in order — empty when `showValues` is off. */\n async getLegendValues(): Promise<string[]> {\n const values = await this.locatorForAll('.wr-meter-group__legend-value')();\n return Promise.all(values.map(value => value.text()));\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { input, computed, ViewEncapsulation, Component } from '@angular/core';
|
|
3
|
+
import { input, viewChildren, computed, ViewEncapsulation, Component } from '@angular/core';
|
|
4
4
|
import { useI18nText } from 'ngwr/i18n';
|
|
5
|
+
import { useChartTooltip } from 'ngwr/popover';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @license
|
|
@@ -47,6 +48,14 @@ class WrMeterGroup {
|
|
|
47
48
|
showLegend = input(true, { ...(ngDevMode ? { debugName: "showLegend" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
48
49
|
/** Show each segment's value in the legend, next to its label. @default true */
|
|
49
50
|
showValues = input(true, { ...(ngDevMode ? { debugName: "showValues" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
51
|
+
/**
|
|
52
|
+
* Show a tooltip with the segment's label and value on hover. It replaces the
|
|
53
|
+
* band's `title`, which is written only while this is off — or the browser would
|
|
54
|
+
* open a second copy a moment later. @default true
|
|
55
|
+
*/
|
|
56
|
+
tooltip = input(true, { ...(ngDevMode ? { debugName: "tooltip" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
57
|
+
sliceEls = viewChildren('slice', /* @ts-ignore */
|
|
58
|
+
...(ngDevMode ? [{ debugName: "sliceEls" }] : /* istanbul ignore next */ []));
|
|
50
59
|
/**
|
|
51
60
|
* A segment's contribution, floored at `0` and with anything non-finite read
|
|
52
61
|
* as `0`. One `NaN` used to poison the whole bar: the sum is `NaN` as soon as
|
|
@@ -82,13 +91,24 @@ class WrMeterGroup {
|
|
|
82
91
|
percent: (WrMeterGroup.amount(segment.value) / this.resolvedMax()) * 100,
|
|
83
92
|
})), /* @ts-ignore */
|
|
84
93
|
...(ngDevMode ? [{ debugName: "slices" }] : /* istanbul ignore next */ []));
|
|
94
|
+
/**
|
|
95
|
+
* One tooltip for the whole bar, pointing at the hovered band, with the value as
|
|
96
|
+
* the legend prints it.
|
|
97
|
+
*/
|
|
98
|
+
tip = useChartTooltip(this.tooltip, index => {
|
|
99
|
+
const slice = this.slices()[index];
|
|
100
|
+
const el = this.sliceEls()[index]?.nativeElement;
|
|
101
|
+
if (!slice || !el)
|
|
102
|
+
return null;
|
|
103
|
+
return { datum: { label: slice.label, value: String(slice.value), color: slice.color }, anchor: el };
|
|
104
|
+
});
|
|
85
105
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMeterGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
86
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrMeterGroup, isStandalone: true, selector: "wr-meter-group", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-meter-group" }, ngImport: i0, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <span\n class=\"wr-meter-group__slice\"\n [title]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n", encapsulation: i0.ViewEncapsulation.None });
|
|
106
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrMeterGroup, isStandalone: true, selector: "wr-meter-group", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-meter-group" }, viewQueries: [{ propertyName: "sliceEls", predicate: ["slice"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <!-- `data-label` is what the harness reads a band's label from; the `title` it\n used to read is only written while the tooltip is off. -->\n <span\n #slice\n class=\"wr-meter-group__slice\"\n [attr.title]=\"tooltip() ? null : slice.label\"\n [attr.data-label]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n", encapsulation: i0.ViewEncapsulation.None });
|
|
87
107
|
}
|
|
88
108
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMeterGroup, decorators: [{
|
|
89
109
|
type: Component,
|
|
90
|
-
args: [{ selector: 'wr-meter-group', encapsulation: ViewEncapsulation.None, host: { class: 'wr-meter-group' }, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <span\n class=\"wr-meter-group__slice\"\n [title]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n" }]
|
|
91
|
-
}], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }] } });
|
|
110
|
+
args: [{ selector: 'wr-meter-group', encapsulation: ViewEncapsulation.None, host: { class: 'wr-meter-group' }, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <!-- `data-label` is what the harness reads a band's label from; the `title` it\n used to read is only written while the tooltip is off. -->\n <span\n #slice\n class=\"wr-meter-group__slice\"\n [attr.title]=\"tooltip() ? null : slice.label\"\n [attr.data-label]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n" }]
|
|
111
|
+
}], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], sliceEls: [{ type: i0.ViewChildren, args: ['slice', { isSignal: true }] }] } });
|
|
92
112
|
|
|
93
113
|
/**
|
|
94
114
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-meter-group.mjs","sources":["../../../projects/lib/meter-group/meter-group.ts","../../../projects/lib/meter-group/meter-group.html","../../../projects/lib/meter-group/ngwr-meter-group.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\n\nimport type { WrMeterSegment } from './interfaces';\n\nconst FALLBACK_COLORS = [\n 'var(--wr-color-primary)',\n 'var(--wr-color-success)',\n 'var(--wr-color-warning)',\n 'var(--wr-color-danger)',\n 'var(--wr-color-medium)',\n];\n\n/**\n * Stacked-segment progress bar. Visualises a breakdown of a total —\n * disk usage, budget, vote share, etc. Each segment contributes a slice\n * proportional to its `value` relative to the sum (or the explicit `max`).\n *\n * @example\n * ```html\n * <wr-meter-group\n * [segments]=\"[\n * { label: 'Used', value: 60 },\n * { label: 'Reserved', value: 25, color: 'var(--wr-color-warning)' }\n * ]\"\n * [max]=\"100\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/meter-group\n */\n@Component({\n selector: 'wr-meter-group',\n templateUrl: './meter-group.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-meter-group' },\n})\nexport class WrMeterGroup {\n /** Accessible name — the role needs one. Falls back to `meterGroup.label`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'meterGroup.label', 'Meter');\n\n readonly segments = input<readonly WrMeterSegment[]>([]);\n\n /** Explicit total. When `0` (default), `max = sum(values)`. @default 0 */\n readonly max = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Show the labelled legend under the bar. @default true */\n readonly showLegend = input(true, { transform: coerceBooleanProperty });\n\n /** Show each segment's value in the legend, next to its label. @default true */\n readonly showValues = input(true, { transform: coerceBooleanProperty });\n\n /**\n * A segment's contribution, floored at `0` and with anything non-finite read\n * as `0`. One `NaN` used to poison the whole bar: the sum is `NaN` as soon as\n * one value is, so the total fell back to `1` and every OTHER segment was\n * asked for a width of `value * 100`%, while `aria-valuenow` announced `NaN`.\n */\n private static amount(raw: number): number {\n return Number.isFinite(raw) ? Math.max(0, raw) : 0;\n }\n\n protected readonly resolvedMax = computed(() => {\n const explicit = this.max();\n if (explicit > 0) return explicit;\n const sum = this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0);\n return sum > 0 ? sum : 1;\n });\n\n /**\n * Sum of the segments, for `aria-valuenow`. `role=\"progressbar\"` without it\n * announces no value at all, so the bar was invisible to assistive tech.\n *\n * Capped at the total, because segments summing past an explicit `max` used\n * to announce a value outside the range they were announced against.\n */\n protected readonly totalValue = computed(() =>\n Math.min(\n this.resolvedMax(),\n this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0)\n )\n );\n\n protected readonly slices = computed(() =>\n this.segments().map((segment, i) => ({\n label: segment.label,\n // The legend keeps a negative value visible — it is data the caller gave\n // us — but not a non-finite one, which reads as the literal text `NaN`.\n value: Number.isFinite(segment.value) ? segment.value : 0,\n color: segment.color ?? FALLBACK_COLORS[i % FALLBACK_COLORS.length],\n percent: (WrMeterGroup.amount(segment.value) / this.resolvedMax()) * 100,\n }))\n );\n}\n","<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <span\n class=\"wr-meter-group__slice\"\n [title]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ngwr-meter-group.mjs","sources":["../../../projects/lib/meter-group/meter-group.ts","../../../projects/lib/meter-group/meter-group.html","../../../projects/lib/meter-group/ngwr-meter-group.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, type ElementRef, ViewEncapsulation, computed, input, viewChildren } from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { useChartTooltip } from 'ngwr/popover';\n\nimport type { WrMeterSegment } from './interfaces';\n\nconst FALLBACK_COLORS = [\n 'var(--wr-color-primary)',\n 'var(--wr-color-success)',\n 'var(--wr-color-warning)',\n 'var(--wr-color-danger)',\n 'var(--wr-color-medium)',\n];\n\n/**\n * Stacked-segment progress bar. Visualises a breakdown of a total —\n * disk usage, budget, vote share, etc. Each segment contributes a slice\n * proportional to its `value` relative to the sum (or the explicit `max`).\n *\n * @example\n * ```html\n * <wr-meter-group\n * [segments]=\"[\n * { label: 'Used', value: 60 },\n * { label: 'Reserved', value: 25, color: 'var(--wr-color-warning)' }\n * ]\"\n * [max]=\"100\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/meter-group\n */\n@Component({\n selector: 'wr-meter-group',\n templateUrl: './meter-group.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-meter-group' },\n})\nexport class WrMeterGroup {\n /** Accessible name — the role needs one. Falls back to `meterGroup.label`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'meterGroup.label', 'Meter');\n\n readonly segments = input<readonly WrMeterSegment[]>([]);\n\n /** Explicit total. When `0` (default), `max = sum(values)`. @default 0 */\n readonly max = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Show the labelled legend under the bar. @default true */\n readonly showLegend = input(true, { transform: coerceBooleanProperty });\n\n /** Show each segment's value in the legend, next to its label. @default true */\n readonly showValues = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Show a tooltip with the segment's label and value on hover. It replaces the\n * band's `title`, which is written only while this is off — or the browser would\n * open a second copy a moment later. @default true\n */\n readonly tooltip = input(true, { transform: coerceBooleanProperty });\n\n private readonly sliceEls = viewChildren<ElementRef<HTMLElement>>('slice');\n\n /**\n * A segment's contribution, floored at `0` and with anything non-finite read\n * as `0`. One `NaN` used to poison the whole bar: the sum is `NaN` as soon as\n * one value is, so the total fell back to `1` and every OTHER segment was\n * asked for a width of `value * 100`%, while `aria-valuenow` announced `NaN`.\n */\n private static amount(raw: number): number {\n return Number.isFinite(raw) ? Math.max(0, raw) : 0;\n }\n\n protected readonly resolvedMax = computed(() => {\n const explicit = this.max();\n if (explicit > 0) return explicit;\n const sum = this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0);\n return sum > 0 ? sum : 1;\n });\n\n /**\n * Sum of the segments, for `aria-valuenow`. `role=\"progressbar\"` without it\n * announces no value at all, so the bar was invisible to assistive tech.\n *\n * Capped at the total, because segments summing past an explicit `max` used\n * to announce a value outside the range they were announced against.\n */\n protected readonly totalValue = computed(() =>\n Math.min(\n this.resolvedMax(),\n this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0)\n )\n );\n\n protected readonly slices = computed(() =>\n this.segments().map((segment, i) => ({\n label: segment.label,\n // The legend keeps a negative value visible — it is data the caller gave\n // us — but not a non-finite one, which reads as the literal text `NaN`.\n value: Number.isFinite(segment.value) ? segment.value : 0,\n color: segment.color ?? FALLBACK_COLORS[i % FALLBACK_COLORS.length],\n percent: (WrMeterGroup.amount(segment.value) / this.resolvedMax()) * 100,\n }))\n );\n\n /**\n * One tooltip for the whole bar, pointing at the hovered band, with the value as\n * the legend prints it.\n */\n protected readonly tip = useChartTooltip(this.tooltip, index => {\n const slice = this.slices()[index];\n const el = this.sliceEls()[index]?.nativeElement;\n if (!slice || !el) return null;\n return { datum: { label: slice.label, value: String(slice.value), color: slice.color }, anchor: el };\n });\n}\n","<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <!-- `data-label` is what the harness reads a band's label from; the `title` it\n used to read is only written while the tooltip is off. -->\n <span\n #slice\n class=\"wr-meter-group__slice\"\n [attr.title]=\"tooltip() ? null : slice.label\"\n [attr.data-label]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,14 @@ import { input, ViewEncapsulation, Component } from '@angular/core';
|
|
|
14
14
|
* side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +
|
|
15
15
|
* subtitle come from inputs.
|
|
16
16
|
*
|
|
17
|
+
* A bare `<div>` wrapper in the actions slot, one with no `class` and no
|
|
18
|
+
* `style`, is laid out as a wrapping row with the actions region's own gap, so
|
|
19
|
+
* the buttons inside it are spaced exactly like buttons projected one by one.
|
|
20
|
+
* The gap follows `--wr-density-gap`. Give the wrapper a class or a style and
|
|
21
|
+
* its layout is yours: the header sets nothing on it. The extra row spaces its
|
|
22
|
+
* own children and leaves a wrapper alone, since that is where metadata prose
|
|
23
|
+
* goes, so project tags through an `<ng-container>` as below.
|
|
24
|
+
*
|
|
17
25
|
* @example
|
|
18
26
|
* ```html
|
|
19
27
|
* <wr-page-header title="Settings" subtitle="Manage your workspace">
|
|
@@ -22,10 +30,10 @@ import { input, ViewEncapsulation, Component } from '@angular/core';
|
|
|
22
30
|
* <button wr-btn>Invite</button>
|
|
23
31
|
* <button wr-btn color="primary">Save</button>
|
|
24
32
|
* </div>
|
|
25
|
-
* <
|
|
33
|
+
* <ng-container wrPageHeaderExtra>
|
|
26
34
|
* <wr-tag>v2.4</wr-tag>
|
|
27
35
|
* <wr-tag color="success">Stable</wr-tag>
|
|
28
|
-
* </
|
|
36
|
+
* </ng-container>
|
|
29
37
|
* </wr-page-header>
|
|
30
38
|
* ```
|
|
31
39
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-page-header.mjs","sources":["../../../projects/lib/page-header/page-header.ts","../../../projects/lib/page-header/page-header.html","../../../projects/lib/page-header/ngwr-page-header.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\n/**\n * Top-of-page heading block. Three named slots via attribute selectors:\n * `[wrPageHeaderBreadcrumbs]` (top row), `[wrPageHeaderActions]` (right\n * side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +\n * subtitle come from inputs.\n *\n * @example\n * ```html\n * <wr-page-header title=\"Settings\" subtitle=\"Manage your workspace\">\n * <nav wrPageHeaderBreadcrumbs>…</nav>\n * <div wrPageHeaderActions>\n * <button wr-btn>Invite</button>\n * <button wr-btn color=\"primary\">Save</button>\n * </div>\n * <
|
|
1
|
+
{"version":3,"file":"ngwr-page-header.mjs","sources":["../../../projects/lib/page-header/page-header.ts","../../../projects/lib/page-header/page-header.html","../../../projects/lib/page-header/ngwr-page-header.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\n/**\n * Top-of-page heading block. Three named slots via attribute selectors:\n * `[wrPageHeaderBreadcrumbs]` (top row), `[wrPageHeaderActions]` (right\n * side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +\n * subtitle come from inputs.\n *\n * A bare `<div>` wrapper in the actions slot, one with no `class` and no\n * `style`, is laid out as a wrapping row with the actions region's own gap, so\n * the buttons inside it are spaced exactly like buttons projected one by one.\n * The gap follows `--wr-density-gap`. Give the wrapper a class or a style and\n * its layout is yours: the header sets nothing on it. The extra row spaces its\n * own children and leaves a wrapper alone, since that is where metadata prose\n * goes, so project tags through an `<ng-container>` as below.\n *\n * @example\n * ```html\n * <wr-page-header title=\"Settings\" subtitle=\"Manage your workspace\">\n * <nav wrPageHeaderBreadcrumbs>…</nav>\n * <div wrPageHeaderActions>\n * <button wr-btn>Invite</button>\n * <button wr-btn color=\"primary\">Save</button>\n * </div>\n * <ng-container wrPageHeaderExtra>\n * <wr-tag>v2.4</wr-tag>\n * <wr-tag color=\"success\">Stable</wr-tag>\n * </ng-container>\n * </wr-page-header>\n * ```\n *\n * @see https://ngwr.dev/reference/components/page-header\n */\n@Component({\n selector: 'wr-page-header',\n templateUrl: './page-header.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-page-header', '[class.wr-page-header--responsive]': 'responsive()' },\n})\nexport class WrPageHeader {\n /** Primary title shown as an h1. */\n readonly title = input<string>('');\n\n /** Secondary line below the title. */\n readonly subtitle = input<string>('');\n\n /**\n * Stack the title and actions vertically when the header's own box is too\n * narrow to sit them side by side (a container query on its own width, not\n * the viewport — so it adapts inside a narrow column or split pane).\n * @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n}\n","<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAAA;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;MAOU,YAAY,CAAA;;IAEd,KAAK,GAAG,KAAK,CAAS,EAAE;8EAAC;;IAGzB,QAAQ,GAAG,KAAK,CAAS,EAAE;iFAAC;AAErC;;;;;AAKG;IACM,UAAU,GAAG,KAAK,CAAC,KAAK,kFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;uGAb7D,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,skBC/CzB,0lBAqBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FD0Ba,YAAY,EAAA,UAAA,EAAA,CAAA;kBANxB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gBAAgB,EAAA,aAAA,EAEX,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B,EAAE,KAAK,EAAE,gBAAgB,EAAE,oCAAoC,EAAE,cAAc,EAAE,EAAA,QAAA,EAAA,0lBAAA,EAAA;;;AE7CzF;;AAEG;;;;"}
|