@adia-ai/web-components 0.8.43 → 0.8.45
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/CHANGELOG.md +54 -0
- package/components/avatar/avatar.class.js +12 -1
- package/components/button/button.d.ts +4 -0
- package/components/chart/chart.a2ui.json +26 -0
- package/components/chart/chart.class.js +1304 -222
- package/components/chart/chart.css +151 -1
- package/components/chart/chart.d.ts +6 -0
- package/components/chart/chart.yaml +57 -0
- package/components/chart-legend/chart-legend.a2ui.json +17 -2
- package/components/chart-legend/chart-legend.class.js +69 -4
- package/components/chart-legend/chart-legend.css +65 -1
- package/components/chart-legend/chart-legend.d.ts +4 -2
- package/components/chart-legend/chart-legend.examples.md +4 -4
- package/components/chart-legend/chart-legend.yaml +43 -3
- package/components/combobox/combobox.a2ui.json +3 -0
- package/components/combobox/combobox.class.js +9 -8
- package/components/combobox/combobox.css +25 -4
- package/components/combobox/combobox.yaml +6 -0
- package/components/command/command.css +17 -1
- package/components/context-menu/context-menu.a2ui.json +8 -3
- package/components/context-menu/context-menu.class.js +46 -5
- package/components/context-menu/context-menu.d.ts +8 -3
- package/components/context-menu/context-menu.examples.md +2 -2
- package/components/context-menu/context-menu.yaml +22 -5
- package/components/heatmap/heatmap.a2ui.json +5 -0
- package/components/heatmap/heatmap.d.ts +2 -0
- package/components/heatmap/heatmap.yaml +8 -0
- package/components/input/input.a2ui.json +2 -2
- package/components/input/input.class.js +12 -7
- package/components/input/input.yaml +6 -5
- package/components/integration-card/integration-card.d.ts +2 -0
- package/components/nav/nav.a2ui.json +2 -2
- package/components/nav/nav.css +1 -1
- package/components/nav/nav.d.ts +1 -1
- package/components/nav/nav.yaml +14 -3
- package/components/nav-group/nav-group.css +37 -3
- package/components/noodles/noodles.a2ui.json +0 -15
- package/components/noodles/noodles.yaml +0 -12
- package/components/number-format/number-format.class.js +10 -0
- package/components/pagination/pagination.class.js +140 -26
- package/components/popover/popover.d.ts +2 -0
- package/components/progress/progress.class.js +11 -6
- package/components/range/range.class.js +9 -1
- package/components/search/search.class.js +39 -5
- package/components/select/select.a2ui.json +10 -1
- package/components/select/select.class.js +34 -14
- package/components/select/select.css +39 -1
- package/components/select/select.d.ts +2 -0
- package/components/select/select.yaml +19 -1
- package/components/stream/stream.d.ts +2 -0
- package/components/table/cell-types.js +9 -0
- package/components/table/table.a2ui.json +6 -1
- package/components/table/table.class.js +265 -34
- package/components/table/table.css +38 -10
- package/components/table/table.d.ts +3 -1
- package/components/table/table.examples.md +2 -2
- package/components/table/table.yaml +15 -2
- package/components/table-toolbar/table-toolbar.a2ui.json +43 -4
- package/components/table-toolbar/table-toolbar.class.js +407 -28
- package/components/table-toolbar/table-toolbar.css +299 -0
- package/components/table-toolbar/table-toolbar.d.ts +15 -1
- package/components/table-toolbar/table-toolbar.yaml +162 -15
- package/components/tag/tag.class.js +13 -1
- package/components/text/text.a2ui.json +3 -3
- package/components/text/text.d.ts +5 -3
- package/components/text/text.yaml +3 -3
- package/components/textarea/textarea.class.js +9 -1
- package/components/tour/tour.d.ts +10 -0
- package/core/a11y.d.ts +22 -0
- package/core/a11y.js +64 -0
- package/core/anchor.js +9 -5
- package/core/data-stream.js +37 -2
- package/core/element.js +1 -1
- package/core/index.d.ts +1 -0
- package/core/index.js +1 -0
- package/core/provider.d.ts +9 -13
- package/core/provider.js +9 -113
- package/core/store.d.ts +46 -0
- package/core/store.js +89 -0
- package/custom-elements.json +127 -33
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +1 -1
- package/dist/theme-provider.min.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +119 -119
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -1
- package/patterns/access-requests/access-requests.examples.html +1 -1
- package/patterns/admin-keys-and-export/admin-keys-and-export.examples.html +7 -7
- package/patterns/agent-cost/agent-cost.examples.html +6 -6
- package/patterns/agent-memory/agent-memory.examples.html +3 -3
- package/patterns/agent-prompt-library/agent-prompt-library.examples.html +8 -8
- package/patterns/agent-tool-call/agent-tool-call.examples.html +1 -1
- package/patterns/approvals/approvals.examples.html +6 -6
- package/patterns/audit-log/audit-log.examples.html +1 -1
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.html +4 -4
- package/patterns/chart-in-card/chart-in-card.examples.html +114 -0
- package/patterns/chart-in-card/chart-in-card.examples.js +37 -0
- package/patterns/comments-and-collaboration/comments-and-collaboration.examples.html +5 -5
- package/patterns/data-tables-inline-edit-and-tree/data-tables-inline-edit-and-tree.examples.html +2 -2
- package/patterns/diff-review/diff-review.examples.html +6 -6
- package/patterns/export-flow/export-flow.examples.html +2 -2
- package/patterns/filter-bar/filter-bar.examples.html +2 -2
- package/patterns/forms-conditional-and-autocomplete/forms-conditional-and-autocomplete.examples.html +2 -2
- package/patterns/inline-dialog/inline-dialog.examples.html +2 -2
- package/patterns/marketing-engagement/marketing-engagement.examples.html +4 -4
- package/patterns/notifications-bell-and-digest/notifications-bell-and-digest.examples.html +1 -1
- package/patterns/permissions-matrix/permissions-matrix.examples.html +1 -1
- package/patterns/permissions-sharing/permissions-sharing.examples.html +2 -2
- package/patterns/profile-public-and-verification/profile-public-and-verification.examples.html +4 -4
- package/patterns/search-discovery/search-discovery.examples.html +2 -2
- package/styles/api/sizing.css +46 -0
- package/styles/type/roles.css +29 -9
|
@@ -130,7 +130,25 @@
|
|
|
130
130
|
NOTE: size="sm|md|lg" used to cap max-width (25/50/100%) which was a bug:
|
|
131
131
|
a chart in a 160px grid cell would be clamped to 40px wide. Size now
|
|
132
132
|
only tunes typography/padding/density inside #dims(); layout is the
|
|
133
|
-
responsibility of the consumer.
|
|
133
|
+
responsibility of the consumer.
|
|
134
|
+
|
|
135
|
+
ADR-0074 (Chart 2.0 ratio grammar, gh#1624 plan step 1) — [ratio]
|
|
136
|
+
PINS one of three named buckets (3:2|1:1|2:3), overriding whatever
|
|
137
|
+
height the box would otherwise get; unset auto-snaps by classifying
|
|
138
|
+
the chart's own live rendered aspect against two midpoint boundaries.
|
|
139
|
+
Because this primitive derives height in JS from a measured
|
|
140
|
+
clientWidth/clientHeight rather than from CSS layout (see the note
|
|
141
|
+
above — the SAME reason `size` stopped clamping max-width), the
|
|
142
|
+
ratified "CSS container query" mechanism is realized inside
|
|
143
|
+
chart.class.js's #dims() (the same measurement pass the pre-existing
|
|
144
|
+
ResizeObserver already drives), not as a literal `@container` rule
|
|
145
|
+
here: `container-type: size` (required to query aspect-ratio, not
|
|
146
|
+
just inline-size like the legend query below) would force block-size
|
|
147
|
+
containment on :scope, collapsing any chart with no explicit height
|
|
148
|
+
set today — the common case across this file's own demo gallery.
|
|
149
|
+
Same ratified grammar/snap-boundary/override contract either way;
|
|
150
|
+
`#dims()` reflects the resolved bucket onto the host as
|
|
151
|
+
`data-ratio-resolved` for later waves' per-type CSS to key off. */
|
|
134
152
|
|
|
135
153
|
/* Debug resize handle */
|
|
136
154
|
:scope[resize] {
|
|
@@ -158,6 +176,16 @@
|
|
|
158
176
|
fill: none;
|
|
159
177
|
}
|
|
160
178
|
|
|
179
|
+
/* REQ-R-007 (Chart 2.0 color-role plan) — "denser 1:1/2:3 layouts need a
|
|
180
|
+
quieter gridline than spacious 3:2": both buckets already thin the
|
|
181
|
+
gridline COUNT (#gridAndAxes' thinGrid, chart.class.js); this dims the
|
|
182
|
+
remaining lines' CONTRAST tier a step further rather than minting a
|
|
183
|
+
second gridline token. */
|
|
184
|
+
:scope[data-ratio-resolved="1:1"] [data-chart-grid],
|
|
185
|
+
:scope[data-ratio-resolved="2:3"] [data-chart-grid] {
|
|
186
|
+
opacity: 0.72;
|
|
187
|
+
}
|
|
188
|
+
|
|
161
189
|
/* ── Y-axis labels ── */
|
|
162
190
|
|
|
163
191
|
[data-y-label] {
|
|
@@ -387,6 +415,51 @@
|
|
|
387
415
|
stroke: none;
|
|
388
416
|
}
|
|
389
417
|
|
|
418
|
+
/* REQ-R-003 (pie, 1:1) — "legend as a ring of labels around the pie":
|
|
419
|
+
one label per slice, positioned OUTSIDE the ring (chart.class.js sizes
|
|
420
|
+
the pie itself smaller at 1:1 to leave this room). Sits on the plain
|
|
421
|
+
chart background, not on a colored slice fill, so it uses the ordinary
|
|
422
|
+
on-surface label token rather than treemap/donut's on-color token. */
|
|
423
|
+
[data-ring-label] {
|
|
424
|
+
fill: var(--chart-label);
|
|
425
|
+
font-weight: var(--a-weight-medium);
|
|
426
|
+
pointer-events: none;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/* REQ-R-003 (pie/donut, 1:1) — the ring of labels (pie) / maximized ring
|
|
430
|
+
+ center-stat (donut) already function as the legend at 1:1, so the
|
|
431
|
+
always-visible inline `[data-legend]` block below the chart would
|
|
432
|
+
duplicate that information and compete for the same square footprint;
|
|
433
|
+
suppress it at 1:1 only. Tooltip-on-hover and (donut) the center-stat
|
|
434
|
+
text both stay unaffected either way.
|
|
435
|
+
|
|
436
|
+
REQ-R-003 (radial-bar, 1:1 "legend as ring") — same rationale, one
|
|
437
|
+
ring's worth of `[data-ring-label]` text already IS the legend at 1:1
|
|
438
|
+
(chart.class.js).
|
|
439
|
+
|
|
440
|
+
REQ-R-003 (multi-line, 3:2 "all series labeled inline at line end (no
|
|
441
|
+
legend needed)") — same rationale, inverted axis: multi-line's own
|
|
442
|
+
inline end-labels ([data-series-end-label]) only render at 3:2, so
|
|
443
|
+
THAT'S the ratio whose internal legend is redundant and suppressed;
|
|
444
|
+
1:1/2:3 drop the end-labels and rely on the ordinary legend instead
|
|
445
|
+
(unsuppressed there), matching the matrix's own progressive
|
|
446
|
+
de-emphasis for this type. */
|
|
447
|
+
:scope[type="pie"][data-ratio-resolved="1:1"] [data-legend],
|
|
448
|
+
:scope[type="donut"][data-ratio-resolved="1:1"] [data-legend],
|
|
449
|
+
:scope[type="radial-bar"][data-ratio-resolved="1:1"] [data-legend],
|
|
450
|
+
:scope[type="multi-line"][data-ratio-resolved="3:2"] [data-legend] {
|
|
451
|
+
display: none;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/* REQ-R-003 (multi-line, 3:2) — the inline end-of-line series label the
|
|
455
|
+
suppression rule above pairs with. Colored per-series via the same
|
|
456
|
+
`--color-{key}` fallback-chain hook every other series-keyed element
|
|
457
|
+
in this file uses (chart.class.js's `#seriesFill`). */
|
|
458
|
+
[data-series-end-label] {
|
|
459
|
+
font-weight: var(--a-weight-medium);
|
|
460
|
+
pointer-events: none;
|
|
461
|
+
}
|
|
462
|
+
|
|
390
463
|
/* ── Donut center text ── */
|
|
391
464
|
|
|
392
465
|
[data-donut-total] {
|
|
@@ -553,6 +626,15 @@
|
|
|
553
626
|
fill: var(--chart-label);
|
|
554
627
|
}
|
|
555
628
|
|
|
629
|
+
/* REQ-R-003 (funnel, 1:1) — "stage labels inline": placed inside the
|
|
630
|
+
colored trapezoid body instead of the plain chart background, so it
|
|
631
|
+
needs the on-color label token (same convention treemap's own
|
|
632
|
+
in-tile label already uses) rather than the ordinary chart-fg. */
|
|
633
|
+
[data-funnel-label-inline] {
|
|
634
|
+
fill: var(--a-canvas-0);
|
|
635
|
+
font-weight: var(--a-weight-semibold);
|
|
636
|
+
}
|
|
637
|
+
|
|
556
638
|
/* ── Treemap ──
|
|
557
639
|
Flat tiles — each rect filled by the data palette. Labels +
|
|
558
640
|
values appear only on tiles large enough to fit them (size
|
|
@@ -625,6 +707,22 @@
|
|
|
625
707
|
stroke-width: 2;
|
|
626
708
|
}
|
|
627
709
|
|
|
710
|
+
/* REQ-R-003 (composed, 2:3) — the sparkline-inset backing + line. Quiet
|
|
711
|
+
container-low surface (REQ-R-007's own "quiet surfaces" role) so the
|
|
712
|
+
inset reads as a distinct panel without competing with the primary
|
|
713
|
+
bar series for visual weight. */
|
|
714
|
+
[data-composed-inset-bg] {
|
|
715
|
+
fill: var(--md-sys-color-neutral-container-low);
|
|
716
|
+
}
|
|
717
|
+
[data-composed-inset-line] {
|
|
718
|
+
fill: none;
|
|
719
|
+
stroke-width: calc(var(--chart-line-width) - 0.5);
|
|
720
|
+
}
|
|
721
|
+
[data-composed-inset-label] {
|
|
722
|
+
fill: var(--chart-label);
|
|
723
|
+
font-family: var(--chart-font);
|
|
724
|
+
}
|
|
725
|
+
|
|
628
726
|
/* ── Sparkline container ──
|
|
629
727
|
`height: 100%` fills an explicit parent height (e.g. when the
|
|
630
728
|
containing section is a flex-grow item inside card-ui). Falls
|
|
@@ -640,6 +738,33 @@
|
|
|
640
738
|
:scope[type="segments"] svg {
|
|
641
739
|
height: 1.5rem;
|
|
642
740
|
}
|
|
741
|
+
|
|
742
|
+
/* REQ-R-003 (segments, 2:3) — "tall vertical stacked bars": the
|
|
743
|
+
horizontal default's fixed-HEIGHT/fluid-WIDTH strip inverts to a
|
|
744
|
+
fixed-WIDTH/fluid-HEIGHT column — same technique every other type's
|
|
745
|
+
own base `svg { width: 100%; height: auto }` rule already uses
|
|
746
|
+
(a definite dimension on one axis, `auto` on the other so the SVG's
|
|
747
|
+
own intrinsic viewBox aspect ratio solves the rest), just with the
|
|
748
|
+
definite axis swapped. `height: 100%` was tried first and produces a
|
|
749
|
+
wrong render: chart-ui has no definite height of its own in ordinary
|
|
750
|
+
use for `height: 100%` to resolve against, and the actual resolved
|
|
751
|
+
value in testing came from an unrelated ancestor percentage chain —
|
|
752
|
+
visually correct-looking proportions by coincidence, but the wrong
|
|
753
|
+
mechanism (caught by a real browser probe, not the Vitest DOM
|
|
754
|
+
assertions above, which never render CSS at all). */
|
|
755
|
+
:scope[type="segments"][data-ratio-resolved="2:3"] svg {
|
|
756
|
+
width: 2rem;
|
|
757
|
+
height: auto;
|
|
758
|
+
margin-inline: auto;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/* REQ-R-003 (segments, 2:3) — "legend stacked": one item per line
|
|
762
|
+
instead of the default wrapped row, matching the vertical strip's own
|
|
763
|
+
tall/narrow footprint. */
|
|
764
|
+
:scope[type="segments"][data-ratio-resolved="2:3"] [data-legend] {
|
|
765
|
+
flex-direction: column;
|
|
766
|
+
align-items: flex-start;
|
|
767
|
+
}
|
|
643
768
|
[data-sparkline] {
|
|
644
769
|
display: block;
|
|
645
770
|
width: 100%;
|
|
@@ -694,6 +819,31 @@
|
|
|
694
819
|
[data-hit] { cursor: default; }
|
|
695
820
|
}
|
|
696
821
|
|
|
822
|
+
/* ─────────────────────────────────────────────────────────────────
|
|
823
|
+
REQ-R-001/R-007 (Chart 2.0 full-bleed anatomy + color-role plan) —
|
|
824
|
+
full-bleed background depth.
|
|
825
|
+
|
|
826
|
+
Deliberately OUTSIDE `@scope (chart-ui)`: the rule needs to match an
|
|
827
|
+
ANCESTOR (`card-ui[padding="none"]`) of the scoping root, which a
|
|
828
|
+
selector inside the scope block can't express against :scope itself.
|
|
829
|
+
card-ui's own `padding="none"` already zeroes its inset (`--card-inset:
|
|
830
|
+
0`, card.css) — a chart filling that slot at 100%×100% was already
|
|
831
|
+
edge-to-edge (REQ-R-001's two pre-existing mechanisms), but with a fully
|
|
832
|
+
transparent background it read as "no background" rather than a
|
|
833
|
+
deliberate flush surface. This tints it with a quiet container-low role
|
|
834
|
+
(ADR-0064/0073's ladder) — REQ-P-002's own opt-in requirement is what
|
|
835
|
+
the `card-ui[padding="none"]` ancestor gate enforces: a chart in a
|
|
836
|
+
normal-padding card never matches this selector, so its rendering is
|
|
837
|
+
unchanged (additive, not a new default). --md-sys-color-neutral-
|
|
838
|
+
container-low was chosen over -surface-dim (the SPEC's other named
|
|
839
|
+
option) for a closer value-step to the ambient canvas so the categorical
|
|
840
|
+
series data stays the visual foreground.
|
|
841
|
+
───────────────────────────────────────────────────────────────── */
|
|
842
|
+
card-ui[padding="none"] chart-ui {
|
|
843
|
+
background: var(--md-sys-color-neutral-container-low);
|
|
844
|
+
border-radius: inherit;
|
|
845
|
+
}
|
|
846
|
+
|
|
697
847
|
/* ─────────────────────────────────────────────────────────────────
|
|
698
848
|
Chart tooltip (top-layer, outside @scope)
|
|
699
849
|
|
|
@@ -38,6 +38,8 @@ export class UIChart extends UIElement {
|
|
|
38
38
|
noGrid: boolean;
|
|
39
39
|
/** Hide value labels. Canonical spelling (ADR-0063, gh#1563) — the deprecated `hideValues` dual-read shim was cut in 0.8.43 (gh#1617). */
|
|
40
40
|
noValues: boolean;
|
|
41
|
+
/** Chart 2.0 aspect-ratio bucket (ADR-0074). Unset (default) auto-snaps to the nearest of the three studied ratios by comparing the chart's own live box aspect against two midpoint boundaries (5:4 between 3:2/1:1, 4:5 between 1:1/2:3) — never interpolated; the resolved bucket reflects onto the host as `data-ratio-resolved`. Setting `ratio` explicitly pins that bucket regardless of the box's actual aspect, overriding the auto-snap. Orthogonal to `size` (overall scale) and `type`/`color` (ADR-0064's family axis) — this attribute lands the grammar + snap plumbing only; per-type studied renderings per bucket are later waves (gh#1624 plan steps 2-4). */
|
|
42
|
+
ratio: '3:2' | '1:1' | '2:3';
|
|
41
43
|
/** Multi-line only. Names one series key (matching a `y` key) to render at full strength — area fill + full-opacity line. Every other series drops its area fill and renders line-only at --chart-deemphasized-opacity. Empty (default) applies full treatment to every series, unchanged from pre-gh#561 behavior. */
|
|
42
44
|
seriesEmphasis: string;
|
|
43
45
|
/** Chart size */
|
|
@@ -48,6 +50,10 @@ export class UIChart extends UIElement {
|
|
|
48
50
|
x: string;
|
|
49
51
|
/** Y-axis key(s), comma-separated for multi-series */
|
|
50
52
|
y: string;
|
|
53
|
+
/** Pins the value-axis domain ceiling for cartesian types (bar, line, area, scatter, multi-line, stacked-bar, grouped-bar, composed). Unset (default, null) keeps today's auto-scale ceiling (the data max). Pairs with `yMin` to pin the full domain; either may be set alone. N/A for radial/part-to-whole types — see `yMin` (gh#1690). A datum outside the pinned domain is CLAMPED to the nearest edge for rendering (the value label/tooltip still shows the real value) rather than escaping the plot box. */
|
|
54
|
+
yMax: number | null;
|
|
55
|
+
/** Pins the value-axis domain floor for cartesian types (bar, line, area, scatter, multi-line, stacked-bar, grouped-bar, composed). Unset (default, null) already floors a positive series at 0 (the pre-1690 behavior, unchanged) — a migrating d3 consumer's own "pin the floor to 0" habit is the built-in default, not something to configure. Pin `y-min` explicitly for three OTHER cases: (1) zooming a narrow window — e.g. `y-min="0.9" y-max="1"` magnifies a percent series clustered near 92-95%, which reads flatter against the full auto-scaled [0,1] domain; (2) a mixed-sign series, where the unpinned floor never goes below 0 and negative values clip at the axis; (3) aligning two charts to one shared scale for a fair comparison. N/A for radial/part-to-whole types (pie, donut, radar, radial-bar, gauge, funnel, treemap, sankey, segments, sparkline) — those never read a shared linear value axis, so this prop is a no-op there (gh#1690). A datum outside the pinned domain is CLAMPED to the nearest edge for rendering (the value label/tooltip still shows the real value) rather than escaping the plot box. */
|
|
56
|
+
yMin: number | null;
|
|
51
57
|
|
|
52
58
|
addEventListener(type: 'chart-hover', listener: (ev: ChartHoverEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
53
59
|
addEventListener(type: 'chart-leave', listener: (ev: ChartLeaveEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
@@ -96,6 +96,25 @@ props:
|
|
|
96
96
|
- sm
|
|
97
97
|
- md
|
|
98
98
|
- lg
|
|
99
|
+
ratio:
|
|
100
|
+
description: >-
|
|
101
|
+
Chart 2.0 aspect-ratio bucket (ADR-0074). Unset (default) auto-snaps
|
|
102
|
+
to the nearest of the three studied ratios by comparing the chart's
|
|
103
|
+
own live box aspect against two midpoint boundaries (5:4 between
|
|
104
|
+
3:2/1:1, 4:5 between 1:1/2:3) — never interpolated; the resolved
|
|
105
|
+
bucket reflects onto the host as `data-ratio-resolved`. Setting
|
|
106
|
+
`ratio` explicitly pins that bucket regardless of the box's actual
|
|
107
|
+
aspect, overriding the auto-snap. Orthogonal to `size` (overall
|
|
108
|
+
scale) and `type`/`color` (ADR-0064's family axis) — this attribute
|
|
109
|
+
lands the grammar + snap plumbing only; per-type studied renderings
|
|
110
|
+
per bucket are later waves (gh#1624 plan steps 2-4).
|
|
111
|
+
type: string
|
|
112
|
+
default: ""
|
|
113
|
+
enum:
|
|
114
|
+
- "3:2"
|
|
115
|
+
- "1:1"
|
|
116
|
+
- "2:3"
|
|
117
|
+
reflect: true
|
|
99
118
|
smooth:
|
|
100
119
|
description: Line smoothing factor
|
|
101
120
|
type: number
|
|
@@ -138,6 +157,44 @@ props:
|
|
|
138
157
|
type: boolean
|
|
139
158
|
default: false
|
|
140
159
|
reflect: true
|
|
160
|
+
yMin:
|
|
161
|
+
description: >-
|
|
162
|
+
Pins the value-axis domain floor for cartesian types (bar, line,
|
|
163
|
+
area, scatter, multi-line, stacked-bar, grouped-bar, composed).
|
|
164
|
+
Unset (default, null) already floors a positive series at 0 (the
|
|
165
|
+
pre-1690 behavior, unchanged) — a migrating d3 consumer's own
|
|
166
|
+
"pin the floor to 0" habit is the built-in default, not something
|
|
167
|
+
to configure. Pin `y-min` explicitly for three OTHER cases: (1)
|
|
168
|
+
zooming a narrow window — e.g. `y-min="0.9" y-max="1"` magnifies a
|
|
169
|
+
percent series clustered near 92-95%, which reads flatter against
|
|
170
|
+
the full auto-scaled [0,1] domain; (2) a mixed-sign series, where
|
|
171
|
+
the unpinned floor never goes below 0 and negative values clip at
|
|
172
|
+
the axis; (3) aligning two charts to one shared scale for a fair
|
|
173
|
+
comparison. N/A for radial/part-to-whole types (pie, donut, radar,
|
|
174
|
+
radial-bar, gauge, funnel, treemap, sankey, segments, sparkline) —
|
|
175
|
+
those never read a shared linear value axis, so this prop is a
|
|
176
|
+
no-op there (gh#1690).
|
|
177
|
+
A datum outside the pinned domain is CLAMPED to the nearest edge
|
|
178
|
+
for rendering (the value label/tooltip still shows the real value)
|
|
179
|
+
rather than escaping the plot box.
|
|
180
|
+
type: number
|
|
181
|
+
default: null
|
|
182
|
+
attribute: y-min
|
|
183
|
+
reflect: true
|
|
184
|
+
yMax:
|
|
185
|
+
description: >-
|
|
186
|
+
Pins the value-axis domain ceiling for cartesian types (bar, line,
|
|
187
|
+
area, scatter, multi-line, stacked-bar, grouped-bar, composed).
|
|
188
|
+
Unset (default, null) keeps today's auto-scale ceiling (the data
|
|
189
|
+
max). Pairs with `yMin` to pin the full domain; either may be set
|
|
190
|
+
alone. N/A for radial/part-to-whole types — see `yMin` (gh#1690).
|
|
191
|
+
A datum outside the pinned domain is CLAMPED to the nearest edge
|
|
192
|
+
for rendering (the value label/tooltip still shows the real value)
|
|
193
|
+
rather than escaping the plot box.
|
|
194
|
+
type: number
|
|
195
|
+
default: null
|
|
196
|
+
attribute: y-max
|
|
197
|
+
reflect: true
|
|
141
198
|
x:
|
|
142
199
|
description: Data key for x-axis (category) values
|
|
143
200
|
type: string
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"properties": {
|
|
16
16
|
"items": {
|
|
17
|
-
"description": "JSON array of {key, label, slot?, pct?} legend items. Takes precedence over [for] when both are provided.",
|
|
17
|
+
"description": "JSON array of {key, label, slot?, pct?, deemphasized?} legend items. Takes precedence over [for] when both are provided. `deemphasized` (REQ-R-007) mutes the row's swatch/label to the same muted-neutral tier chart-ui's own internal legend uses for a de-emphasized series (e.g. `composed@1:1`'s secondary line) — mirrored automatically from a `[for]`-bound chart's own `.legendData`, or settable explicitly here.",
|
|
18
18
|
"type": "string",
|
|
19
19
|
"default": ""
|
|
20
20
|
},
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"default": "hide"
|
|
42
42
|
},
|
|
43
43
|
"position": {
|
|
44
|
-
"description": "Layout hint — drives flex-direction. Actual placement follows DOM order.",
|
|
44
|
+
"description": "Layout hint — drives flex-direction. Actual placement follows DOM order. Superseded by a resolved `ratio` bucket (below) whenever one is in effect; this is the pre-ADR-0074 fallback for a legend with neither an explicit `ratio` nor a `[for]`-bound chart.",
|
|
45
45
|
"type": "string",
|
|
46
46
|
"enum": [
|
|
47
47
|
"top",
|
|
@@ -51,6 +51,16 @@
|
|
|
51
51
|
],
|
|
52
52
|
"default": "bottom"
|
|
53
53
|
},
|
|
54
|
+
"ratio": {
|
|
55
|
+
"description": "Chart 2.0 legend layout bucket (ADR-0074, gh#1624 plan step 5, REQ-R-005): 3:2 renders a horizontal row, 1:1 a wrapped 2-column grid, 2:3 a vertical stacked list. An explicit value PINS the bucket regardless of any bound chart. Unset (default) auto-mirrors the `[for]`-bound chart's own resolved `data-ratio-resolved` bucket — the legend never runs its own container-query classification, since its own box is typically a thin strip with no studied aspect of its own. With neither a pin nor a bound chart, no bucket resolves and `position`'s flex-direction rules apply unchanged. The resolved bucket reflects read-only onto the host as `data-ratio-resolved`, mirroring chart-ui's own convention.",
|
|
56
|
+
"type": "string",
|
|
57
|
+
"enum": [
|
|
58
|
+
"3:2",
|
|
59
|
+
"1:1",
|
|
60
|
+
"2:3"
|
|
61
|
+
],
|
|
62
|
+
"default": ""
|
|
63
|
+
},
|
|
54
64
|
"shape": {
|
|
55
65
|
"description": "Swatch shape. Maps to badge-ui's icon for dot/square variants.",
|
|
56
66
|
"type": "string",
|
|
@@ -99,6 +109,11 @@
|
|
|
99
109
|
"a2ui": "[\n {\n \"id\": \"legend\", \"component\": \"ChartLegend\",\n \"shape\": \"dot\",\n \"items\": \"[{\\\"key\\\":\\\"revenue\\\",\\\"label\\\":\\\"Revenue\\\",\\\"slot\\\":0},{\\\"key\\\":\\\"users\\\",\\\"label\\\":\\\"Users\\\",\\\"slot\\\":1}]\"\n }\n]",
|
|
100
110
|
"name": "standalone-with-items"
|
|
101
111
|
},
|
|
112
|
+
{
|
|
113
|
+
"description": "Standalone legend pinned to the 1:1 (2-col grid) layout bucket.",
|
|
114
|
+
"a2ui": "[\n {\n \"id\": \"legend\", \"component\": \"ChartLegend\",\n \"ratio\": \"1:1\",\n \"items\": \"[{\\\"key\\\":\\\"revenue\\\",\\\"label\\\":\\\"Revenue\\\",\\\"slot\\\":0},{\\\"key\\\":\\\"users\\\",\\\"label\\\":\\\"Users\\\",\\\"slot\\\":1},{\\\"key\\\":\\\"churn\\\",\\\"label\\\":\\\"Churn\\\",\\\"slot\\\":2},{\\\"key\\\":\\\"nps\\\",\\\"label\\\":\\\"NPS\\\",\\\"slot\\\":3}]\"\n }\n]",
|
|
115
|
+
"name": "ratio-pinned-grid"
|
|
116
|
+
},
|
|
102
117
|
{
|
|
103
118
|
"description": "Legend mirrors a named chart's series data.",
|
|
104
119
|
"a2ui": "[\n {\n \"id\": \"root\", \"component\": \"Column\",\n \"children\": [\"chart\", \"legend\"]\n },\n {\n \"id\": \"chart\", \"component\": \"Chart\",\n \"type\": \"multi-line\", \"x\": \"month\", \"y\": \"revenue,users\"\n },\n {\n \"id\": \"legend\", \"component\": \"ChartLegend\",\n \"for\": \"chart\",\n \"shape\": \"line\",\n \"position\": \"bottom\"\n }\n]",
|
|
@@ -34,7 +34,27 @@
|
|
|
34
34
|
* aren't representable as icon glyphs.
|
|
35
35
|
* position — top | bottom | left | right. Layout hint; actual placement
|
|
36
36
|
* is where the element is placed in the DOM. Drives
|
|
37
|
-
* flex-direction.
|
|
37
|
+
* flex-direction. Superseded by a resolved `ratio` bucket
|
|
38
|
+
* (below) whenever one is in effect — `position` is the
|
|
39
|
+
* pre-ADR-0074 fallback for a legend with neither an
|
|
40
|
+
* explicit `ratio` nor a `[for]`-bound chart.
|
|
41
|
+
* ratio — '' | 3:2 | 1:1 | 2:3 (ADR-0074, gh#1624 plan step 5).
|
|
42
|
+
* Explicit value PINS the legend's own layout bucket
|
|
43
|
+
* (row / 2-col grid / vertical list — REQ-R-005) regardless
|
|
44
|
+
* of any bound chart. Unset (default) auto-mirrors the
|
|
45
|
+
* `[for]`-bound chart's own resolved `data-ratio-resolved`
|
|
46
|
+
* bucket — the legend does not run its own container-query
|
|
47
|
+
* classification (REQ-R-005: "follows the per-type legend
|
|
48
|
+
* position column rather than introducing a separate
|
|
49
|
+
* legend-only ratio contract"); a legend's own box is
|
|
50
|
+
* typically a thin strip whose aspect carries no studied
|
|
51
|
+
* meaning of its own. With neither a pin nor a bound chart,
|
|
52
|
+
* no bucket resolves and `position`'s pre-existing
|
|
53
|
+
* flex-direction rules apply unchanged (zero regression for
|
|
54
|
+
* standalone legends that predate this attribute). The
|
|
55
|
+
* resolved bucket is reflected read-only as
|
|
56
|
+
* `data-ratio-resolved`, mirroring chart-ui's own
|
|
57
|
+
* convention.
|
|
38
58
|
* interactive — canonical opt-in spelling (ADR-0063, gh#1563). Rows
|
|
39
59
|
* default interactive (`role="button"` badges that toggle
|
|
40
60
|
* on click + Enter/Space) until the 0.9.0 default-inversion
|
|
@@ -49,6 +69,12 @@
|
|
|
49
69
|
* interactive. `active` is the new state (true=visible).
|
|
50
70
|
*/
|
|
51
71
|
|
|
72
|
+
// ADR-0074's three ratified ratio buckets — same enum chart-ui pins/resolves
|
|
73
|
+
// to (CHART_RATIOS in chart.class.js). Kept as a Set here rather than
|
|
74
|
+
// re-importing chart.class.js: the legend must resolve standalone (no
|
|
75
|
+
// chart-ui ancestor required, per its own "renders standalone" contract).
|
|
76
|
+
const RATIO_BUCKETS = new Set(['3:2', '1:1', '2:3']);
|
|
77
|
+
|
|
52
78
|
import { UIElement } from '../../core/element.js';
|
|
53
79
|
|
|
54
80
|
export class UIChartLegend extends UIElement {
|
|
@@ -60,6 +86,9 @@ export class UIChartLegend extends UIElement {
|
|
|
60
86
|
items: { type: String, default: '', reflect: false },
|
|
61
87
|
shape: { type: String, default: 'dot', reflect: true },
|
|
62
88
|
position: { type: String, default: 'bottom', reflect: true },
|
|
89
|
+
// ADR-0074 (gh#1624 plan step 5) — explicit pin; see the class-doc
|
|
90
|
+
// comment above for the full pin > mirror > position-fallback chain.
|
|
91
|
+
ratio: { type: String, default: '', reflect: true },
|
|
63
92
|
// ADR-0063 (gh#1563) — `interactive` (opt-in) is the canonical
|
|
64
93
|
// positively-named boolean; the deprecated `static` opt-out alias was
|
|
65
94
|
// cut in 0.8.43 (gh#1617). Deliberately keeps its `true` default:
|
|
@@ -122,6 +151,25 @@ export class UIChartLegend extends UIElement {
|
|
|
122
151
|
this.#targetListener = null;
|
|
123
152
|
}
|
|
124
153
|
|
|
154
|
+
/* ── Ratio resolution (ADR-0074, gh#1624 plan step 5) ─────────────── */
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Pin > mirror > none. A pinned `[ratio]` always wins; absent that, a
|
|
158
|
+
* `[for]`-bound chart's own `data-ratio-resolved` is mirrored (set by
|
|
159
|
+
* the SAME `#renderChart()` pass that fires the `legend-update` event
|
|
160
|
+
* this class already listens for — the mirror is always reading a
|
|
161
|
+
* value already fresh by the time `#paint()` runs). Neither present →
|
|
162
|
+
* '' (no bucket resolves; `position`'s pre-existing CSS applies).
|
|
163
|
+
*/
|
|
164
|
+
#resolveRatio() {
|
|
165
|
+
if (RATIO_BUCKETS.has(this.ratio)) return this.ratio;
|
|
166
|
+
if (this.#target) {
|
|
167
|
+
const mirrored = this.#target.getAttribute('data-ratio-resolved');
|
|
168
|
+
if (RATIO_BUCKETS.has(mirrored)) return mirrored;
|
|
169
|
+
}
|
|
170
|
+
return '';
|
|
171
|
+
}
|
|
172
|
+
|
|
125
173
|
/* ── Item source ────────────────────────────────────────────────── */
|
|
126
174
|
|
|
127
175
|
#resolveItems() {
|
|
@@ -142,6 +190,15 @@ export class UIChartLegend extends UIElement {
|
|
|
142
190
|
/* ── Render ─────────────────────────────────────────────────────── */
|
|
143
191
|
|
|
144
192
|
#paint() {
|
|
193
|
+
const resolved = this.#resolveRatio();
|
|
194
|
+
if (resolved) {
|
|
195
|
+
if (this.getAttribute('data-ratio-resolved') !== resolved) {
|
|
196
|
+
this.setAttribute('data-ratio-resolved', resolved);
|
|
197
|
+
}
|
|
198
|
+
} else if (this.hasAttribute('data-ratio-resolved')) {
|
|
199
|
+
this.removeAttribute('data-ratio-resolved');
|
|
200
|
+
}
|
|
201
|
+
|
|
145
202
|
const items = this.#resolveItems();
|
|
146
203
|
this.innerHTML = '';
|
|
147
204
|
if (!items.length) return;
|
|
@@ -165,6 +222,12 @@ export class UIChartLegend extends UIElement {
|
|
|
165
222
|
row.setAttribute('text', label);
|
|
166
223
|
if (key) row.setAttribute('data-key', key);
|
|
167
224
|
if (active) row.setAttribute('data-active', '');
|
|
225
|
+
// REQ-R-007 (Chart 2.0 ratio-and-surface SPEC) — a de-emphasized
|
|
226
|
+
// series (e.g. composed@1:1's secondary line, Wave C) mutes the
|
|
227
|
+
// mirrored legend row the same way chart-ui's own internal legend
|
|
228
|
+
// already mutes its dot (chart.class.js #buildLegend): the muted
|
|
229
|
+
// neutral token, not the series' categorical color slot.
|
|
230
|
+
if (item.deemphasized) row.setAttribute('data-deemphasized', '');
|
|
168
231
|
if (this.interactive) {
|
|
169
232
|
row.setAttribute('tabindex', '0');
|
|
170
233
|
row.setAttribute('aria-pressed', active ? 'true' : 'false');
|
|
@@ -184,9 +247,11 @@ export class UIChartLegend extends UIElement {
|
|
|
184
247
|
const swatch = document.createElement('swatch-ui');
|
|
185
248
|
swatch.setAttribute('shape', swatchShape);
|
|
186
249
|
swatch.setAttribute('size', 'sm');
|
|
187
|
-
const swatchColor =
|
|
188
|
-
?
|
|
189
|
-
:
|
|
250
|
+
const swatchColor = item.deemphasized
|
|
251
|
+
? 'var(--md-sys-color-neutral-on-surface-variant)'
|
|
252
|
+
: key
|
|
253
|
+
? `var(--color-${key}, var(--a-data-${slot}))`
|
|
254
|
+
: `var(--a-data-${slot})`;
|
|
190
255
|
swatch.style.setProperty('--swatch-color', swatchColor);
|
|
191
256
|
row.appendChild(swatch);
|
|
192
257
|
|
|
@@ -35,7 +35,11 @@
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/* Position variants — drive flex-direction. DOM placement still wins for
|
|
38
|
-
actual layout; these tune the internal row direction.
|
|
38
|
+
actual layout; these tune the internal row direction. Pre-ADR-0074
|
|
39
|
+
fallback: superseded below by a resolved [data-ratio-resolved] bucket
|
|
40
|
+
whenever one is in effect (an explicit [ratio] pin, or a [for]-bound
|
|
41
|
+
chart's own mirrored bucket) — a legend with neither keeps this exact
|
|
42
|
+
behavior, unchanged. */
|
|
39
43
|
:scope[position="top"],
|
|
40
44
|
:scope[position="bottom"] {
|
|
41
45
|
flex-direction: row;
|
|
@@ -48,6 +52,32 @@
|
|
|
48
52
|
align-items: flex-start;
|
|
49
53
|
}
|
|
50
54
|
|
|
55
|
+
/* Ratio-resolved layout buckets (ADR-0074, gh#1624 plan step 5, REQ-R-005).
|
|
56
|
+
Same selector specificity as the [position] rules above — placed AFTER
|
|
57
|
+
them in source order so a resolved bucket always wins the cascade over
|
|
58
|
+
a stale/default [position] on the same element. */
|
|
59
|
+
|
|
60
|
+
/* 3:2 — horizontal row (beside/below the chart). */
|
|
61
|
+
:scope[data-ratio-resolved="3:2"] {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: row;
|
|
64
|
+
justify-content: flex-start;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* 1:1 — wrapped 2-column grid. */
|
|
68
|
+
:scope[data-ratio-resolved="1:1"] {
|
|
69
|
+
display: grid;
|
|
70
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
71
|
+
align-items: start;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* 2:3 — vertical stacked list. */
|
|
75
|
+
:scope[data-ratio-resolved="2:3"] {
|
|
76
|
+
display: flex;
|
|
77
|
+
flex-direction: column;
|
|
78
|
+
align-items: flex-start;
|
|
79
|
+
}
|
|
80
|
+
|
|
51
81
|
/* Rows are <badge-ui> chips. We override badge-ui's default tokens
|
|
52
82
|
to give them a quieter, click-to-toggle appearance — transparent
|
|
53
83
|
bg by default (so they read as inline text not chips), highlighted
|
|
@@ -93,6 +123,16 @@
|
|
|
93
123
|
opacity: 0.4;
|
|
94
124
|
}
|
|
95
125
|
|
|
126
|
+
/* De-emphasized (REQ-R-007) rows — a mirrored chart's own muted series
|
|
127
|
+
(e.g. composed@1:1's secondary line). Distinct from :not([data-active])
|
|
128
|
+
above: this is the chart's OWN designed treatment for a still-visible
|
|
129
|
+
series, not a user-toggled-off one; the swatch color itself is set
|
|
130
|
+
inline per-row (matches the neutral token, not opacity) so only the
|
|
131
|
+
label's --badge-fg needs the muted tier here. */
|
|
132
|
+
badge-ui[data-row][data-deemphasized] {
|
|
133
|
+
--badge-fg: var(--chart-legend-fg-inactive);
|
|
134
|
+
}
|
|
135
|
+
|
|
96
136
|
/* Swatch is composed via <swatch-ui shape="…">; per-shape styling
|
|
97
137
|
lives in swatch.css. The legend just hands its [shape] attr through
|
|
98
138
|
and writes --swatch-color inline. Pre-2026-05-01 this file owned a
|
|
@@ -101,3 +141,27 @@
|
|
|
101
141
|
rule (cascade leak). Composing the primitive moves the styling to
|
|
102
142
|
one place. */
|
|
103
143
|
}
|
|
144
|
+
|
|
145
|
+
/* ─────────────────────────────────────────────────────────────────
|
|
146
|
+
gh#1624 plan step 7 — full-bleed × legend horizontal breathing room.
|
|
147
|
+
|
|
148
|
+
Deliberately OUTSIDE `@scope (chart-legend-ui)`, same reason as
|
|
149
|
+
chart.css's own `card-ui[padding="none"] chart-ui` rule: this needs to
|
|
150
|
+
match an ANCESTOR of the scoping root. `--chart-legend-px` defaults to
|
|
151
|
+
0 because a legend normally sits inside a card section that already
|
|
152
|
+
supplies horizontal inset via `--card-inset` (card.css's own
|
|
153
|
+
margin-based section model); `card-ui[padding="none"]` zeroes that
|
|
154
|
+
inset CARD-WIDE (every section, not just the chart's), so a legend
|
|
155
|
+
paired with a full-bleed chart lost its own horizontal clearance too —
|
|
156
|
+
confirmed via browser probe: badge rows sat ~1px from the card's
|
|
157
|
+
rounded edge, at real risk of visual crowding against the corner-radius
|
|
158
|
+
`overflow: hidden` (card.css :scope). The chart itself doesn't need this
|
|
159
|
+
— its own internal plot margins (REQ-R-004) already supply clearance
|
|
160
|
+
regardless of the card's inset — but the legend's chip rows have no
|
|
161
|
+
equivalent internal margin of their own. Restoring `--chart-legend-px`
|
|
162
|
+
only (not `-py`, which the legend already carries unconditionally) is
|
|
163
|
+
the minimal fix: vertical spacing between the chart and legend sections
|
|
164
|
+
is unaffected, only the legend's own left/right clearance is restored. */
|
|
165
|
+
card-ui[padding="none"] chart-legend-ui {
|
|
166
|
+
--chart-legend-px: var(--a-space-4);
|
|
167
|
+
}
|
|
@@ -24,7 +24,7 @@ export interface ChartLegendToggleEventDetail {
|
|
|
24
24
|
export type ChartLegendToggleEvent = CustomEvent<ChartLegendToggleEventDetail>;
|
|
25
25
|
|
|
26
26
|
export class UIChartLegend extends UIElement {
|
|
27
|
-
/** JSON array of {key, label, slot?, pct?} legend items. Takes precedence over [for] when both are provided. */
|
|
27
|
+
/** JSON array of {key, label, slot?, pct?, deemphasized?} legend items. Takes precedence over [for] when both are provided. `deemphasized` (REQ-R-007) mutes the row's swatch/label to the same muted-neutral tier chart-ui's own internal legend uses for a de-emphasized series (e.g. `composed@1:1`'s secondary line) — mirrored automatically from a `[for]`-bound chart's own `.legendData`, or settable explicitly here. */
|
|
28
28
|
items: string;
|
|
29
29
|
/** id-ref of a chart-ui / heatmap-ui to mirror series from. */
|
|
30
30
|
for: string;
|
|
@@ -32,8 +32,10 @@ export class UIChartLegend extends UIElement {
|
|
|
32
32
|
interactive: boolean;
|
|
33
33
|
/** Series-toggle mode emitted via the `toggle` event. `hide` removes the series from the render; `opacity` fades it. Wired via [for] on chart-ui. */
|
|
34
34
|
onToggle: 'hide' | 'opacity';
|
|
35
|
-
/** Layout hint — drives flex-direction. Actual placement follows DOM order. */
|
|
35
|
+
/** Layout hint — drives flex-direction. Actual placement follows DOM order. Superseded by a resolved `ratio` bucket (below) whenever one is in effect; this is the pre-ADR-0074 fallback for a legend with neither an explicit `ratio` nor a `[for]`-bound chart. */
|
|
36
36
|
position: 'top' | 'bottom' | 'left' | 'right';
|
|
37
|
+
/** Chart 2.0 legend layout bucket (ADR-0074, gh#1624 plan step 5, REQ-R-005): 3:2 renders a horizontal row, 1:1 a wrapped 2-column grid, 2:3 a vertical stacked list. An explicit value PINS the bucket regardless of any bound chart. Unset (default) auto-mirrors the `[for]`-bound chart's own resolved `data-ratio-resolved` bucket — the legend never runs its own container-query classification, since its own box is typically a thin strip with no studied aspect of its own. With neither a pin nor a bound chart, no bucket resolves and `position`'s flex-direction rules apply unchanged. The resolved bucket reflects read-only onto the host as `data-ratio-resolved`, mirroring chart-ui's own convention. */
|
|
38
|
+
ratio: '3:2' | '1:1' | '2:3';
|
|
37
39
|
/** Swatch shape. Maps to badge-ui's icon for dot/square variants. */
|
|
38
40
|
shape: 'dot' | 'square' | 'line' | 'dashed';
|
|
39
41
|
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
<chart-legend-ui id="legend-bottom" shape="dot" position="bottom" items='[{"key":"a","label":"Series A","slot":0},{"key":"b","label":"Series B","slot":1},{"key":"c","label":"Series C","slot":2}]'></chart-legend-ui>
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## ratio — mirrors a bound chart's resolved ratio (ADR-0074)
|
|
16
16
|
|
|
17
17
|
```html
|
|
18
|
-
<div style="display:flex; flex-direction:column; gap:var(--a-space-2);">
|
|
19
|
-
<chart-ui id="
|
|
20
|
-
<chart-legend-ui id="legend-
|
|
18
|
+
<div style="display:flex; flex-direction:column; gap:var(--a-space-2); width:360px;">
|
|
19
|
+
<chart-ui id="ratio-chart-32" type="multi-line" ratio="3:2" x="month" y="revenue,users,churn"></chart-ui>
|
|
20
|
+
<chart-legend-ui id="ratio-legend-32" for="ratio-chart-32" shape="line"></chart-legend-ui>
|
|
21
21
|
</div>
|
|
22
22
|
```
|