@aceshooting/lyra-ui 18.0.0 → 18.2.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +274 -0
  2. package/custom-elements.json +1 -1
  3. package/design-tokens.json +1 -1
  4. package/dist/cli/migration-contract.json +1 -1
  5. package/dist/components/conversation/message-actions/message-actions.class.d.ts +2 -1
  6. package/dist/components/forms/combobox/combobox.styles.js +1 -1
  7. package/dist/components/forms/icon-button/icon-button.class.d.ts +18 -9
  8. package/dist/components/forms/select/select.class.d.ts +34 -5
  9. package/dist/components/forms/select/select.class.js +4 -4
  10. package/dist/components/forms/select/select.styles.js +1 -1
  11. package/dist/components/layout/filter-bar/filter-bar.class.d.ts +80 -8
  12. package/dist/components/layout/filter-bar/filter-bar.class.js +11 -3
  13. package/dist/components/layout/filter-bar/filter-bar.styles.js +1 -1
  14. package/dist/components/layout/virtual-list/virtual-list.class.d.ts +47 -16
  15. package/dist/components/layout/virtual-list/virtual-list.class.js +1 -1
  16. package/dist/components/media/map/map.class.d.ts +161 -5
  17. package/dist/components/media/map/map.class.js +50 -21
  18. package/dist/components/media/map/map.styles.js +1 -1
  19. package/dist/components/utility/copy-button/copy-button.class.d.ts +4 -3
  20. package/dist/custom-elements-jsx.d.ts +1 -1
  21. package/dist/events.d.ts +7 -1
  22. package/dist/internal/package-metadata.d.ts +1 -1
  23. package/dist/internal/package-metadata.js +1 -1
  24. package/dist/internal/tokens.styles.js +1 -1
  25. package/dist/lyra.d.ts +1 -1
  26. package/dist/styles/tokens-root.css +1 -1
  27. package/dist/svelte.d.ts +1 -1
  28. package/dist/testing/lyra-tag-event-map.js +1 -1
  29. package/dist/vue.d.ts +1 -1
  30. package/llms/components/lr-combobox.md +8 -4
  31. package/llms/components/lr-filter-bar.md +37 -4
  32. package/llms/components/lr-icon-button.md +15 -7
  33. package/llms/components/lr-map.md +87 -10
  34. package/llms/components/lr-option.md +8 -4
  35. package/llms/components/lr-select.md +30 -5
  36. package/llms/shared.md +46 -0
  37. package/llms/tokens.md +8 -3
  38. package/llms-full.txt +227 -29
  39. package/package.json +1 -1
  40. package/vscode-css-data.json +1 -1
  41. package/vscode-html-data.json +1 -1
  42. package/web-types.json +1 -1
@@ -1,6 +1,11 @@
1
1
  import{type TemplateResult,type PropertyValues}from'lit';import type{Feature,FeatureCollection}from'geojson';import{LyraElement}from'../../../internal/lyra-element.js';import{type MapLibreGeoJsonDiff}from'./map-loader.js';import'../../overlays/skeleton/skeleton.class.js';
2
2
  /** Non-color encoding retained when a legend entry's authored color is unavailable. */
3
3
  export type LyraMapLegendPattern='solid'|'diagonal'|'dots'|'crosshatch';
4
+ /**
5
+ * Presentation role for each keyed `legendInteractive` row's toggle control. See the
6
+ * `legendControlRole` property JSDoc for the full contract.
7
+ */
8
+ export type LyraMapLegendControlRole='button'|'checkbox';
4
9
  /** One immutable, bounded map-legend row. Pattern is required so color is never the sole cue. */
5
10
  export interface LyraMapLegendEntry{readonly color:string;readonly label:string;readonly pattern:LyraMapLegendPattern;
6
11
  /**
@@ -37,7 +42,30 @@ readonly value?:string;
37
42
  * most 8192 characters. A glyph omission is not counted in `legendProjection` either, because
38
43
  * the row it belongs to still renders — only dropped rows are omissions.
39
44
  */
40
- readonly icon?:LyraMapPointIcon|Omit<LyraMapPointIcon,'value'>;}
45
+ readonly icon?:LyraMapPointIcon|Omit<LyraMapPointIcon,'value'>;
46
+ /**
47
+ * Optional section this row belongs to. A key describing two layers at once could previously
48
+ * only be one flat list, with nothing saying which rows belonged to which.
49
+ *
50
+ * **The grouping rule, which is pinned rather than inferred:** CONSECUTIVE entries sharing an
51
+ * identical `group` render as one section -- a visible heading plus a `role="group"` the heading
52
+ * names. An entry with no `group` keeps its DECLARED position: it is never hoisted above or sunk
53
+ * below a section, and a `group` that reappears after an interruption opens a SECOND section
54
+ * rather than reordering rows to merge them. Declaration order is the one thing the legend never
55
+ * rewrites, because the order is itself information about the map.
56
+ *
57
+ * It is caller-supplied DATA, so it renders verbatim and is never passed through the locale
58
+ * catalog. It is trimmed and bounded to 256 characters (ellipsized, since it is rendered prose
59
+ * rather than a matched key); a non-string, empty or whitespace-only value leaves no `group` key
60
+ * at all, so an empty string means "ungrouped" instead of an empty heading, and a legend that
61
+ * never used sections reads back exactly as it did before this field existed.
62
+ *
63
+ * Like the row-level `value`, it is NOT charged to the aggregate label budget: a budget bounds
64
+ * rendered text, and the rendered total here is already finite and stated -- at most one heading
65
+ * per rendered row, so at most 100 of them, each at most 256 characters. A section is also not a
66
+ * row: the 100-row cap and the `legend-limit` summary count rows, never sections.
67
+ */
68
+ readonly group?:string;}
41
69
  /**
42
70
  * One `[value, color]` stop of a continuous legend ramp — deliberately the same shape as
43
71
  * `LyraMapChoroplethLayer['stops']`, so a consumer passes the choropleth's own stops straight
@@ -349,7 +377,15 @@ readonly value:string;
349
377
  /** Proposed visibility of `value` after this toggle. */
350
378
  readonly visible:boolean;
351
379
  /** Complete canonical proposed hidden-category set, in the order it would be committed. */
352
- readonly hiddenCategories:readonly string[];}export interface LyraMapEventMap{'lr-map-load':CustomEvent<null>;'lr-map-marker-activate':CustomEvent<LyraMapMarkerActivationDetail>;'lr-map-legend-toggle':CustomEvent<LyraMapLegendToggleDetail>;'lr-map-click':CustomEvent<{readonly lngLat:readonly[number,number];readonly feature:Feature|undefined;
380
+ readonly hiddenCategories:readonly string[];}
381
+ /**
382
+ * Proposed disclosure state for the legend PANEL, which is a different thing from one category's
383
+ * visibility -- hence its own detail type rather than a reuse of `LyraMapLegendToggleDetail`.
384
+ * Frozen, and detached from the component's own state.
385
+ */
386
+ export interface LyraMapLegendPanelToggleDetail{
387
+ /** Proposed `legendOpen` after this activation. */
388
+ readonly open:boolean;}export interface LyraMapEventMap{'lr-map-load':CustomEvent<null>;'lr-map-marker-activate':CustomEvent<LyraMapMarkerActivationDetail>;'lr-map-legend-toggle':CustomEvent<LyraMapLegendToggleDetail>;'lr-map-legend-panel-toggle':CustomEvent<LyraMapLegendPanelToggleDetail>;'lr-map-click':CustomEvent<{readonly lngLat:readonly[number,number];readonly feature:Feature|undefined;
353
389
  /** Which layer `feature` was hit on, so a click is attributable when both a choropleth and
354
390
  * `dataLayers` are painted. `'cluster'` marks a hit on a clustered entry's aggregate circle,
355
391
  * whose `point_count`/`cluster_id` properties describe the group rather than one feature.
@@ -405,6 +441,14 @@ readonly sourceId:string|undefined;}>;}
405
441
  * before/after vocabulary would be permanent public surface nobody asked for. A programmatic
406
442
  * `hiddenCategories` assignment reconciles without emitting anything -- this event is a
407
443
  * DOM-interaction proposal only.
444
+ * @event lr-map-legend-panel-toggle - **Cancelable.** Fired once when the `legendCollapsible`
445
+ * disclosure is activated by pointer or by Enter/Space, carrying the immutable
446
+ * `detail: { open }` -- the proposed `legendOpen` value. It is the *panel's* disclosure, not a
447
+ * *category's* visibility, so it deliberately does not reuse `lr-map-legend-toggle`.
448
+ * `preventDefault()` is a real veto: `legendOpen` is not written, the rendered rows and the
449
+ * disclosure's `aria-expanded` do not change, which is what lets a host own the open state and
450
+ * write it itself. A programmatic `legendOpen` assignment reconciles without emitting anything,
451
+ * so a controlled host cannot loop.
408
452
  * @event lr-map-marker-activate - Fired once when an accepted declarative marker is activated by
409
453
  * pointer/click or by Enter/Space. The immutable detail carries its normalized `id`, validated
410
454
  * `lngLat`, accepted marker snapshot, and activation `source`.
@@ -421,6 +465,11 @@ readonly sourceId:string|undefined;}>;}
421
465
  * @slot legend - Custom legend content, rendered inside the legend panel's own layout so it stays
422
466
  * positioned with the map instead of floating beside it. Slotted content is never made
423
467
  * interactive by `legendInteractive`, which only reaches rows projected from `legend`.
468
+ * @slot legend-start - The same extension point at the TOP of the legend panel: it renders ahead
469
+ * of the gradient bar and every projected row, where `legend` renders after them. A panel header
470
+ * -- a title, a source note, a host-built control -- could previously only ever be a footer,
471
+ * because `legend` was the only slot. Content here alone opens the panel, exactly as `legend`
472
+ * content alone does, and it is never made interactive by `legendInteractive`.
424
473
  * @csspart legend - The map legend.
425
474
  * @csspart legend-swatch - A legend color swatch, or the entry's glyph when it carries an `icon`
426
475
  * — in which case the swatch drops its color block and pattern overlay, keeps the `pattern`
@@ -433,6 +482,18 @@ readonly sourceId:string|undefined;}>;}
433
482
  * @csspart legend-toggle-hidden - Second token carried alongside `legend-toggle` while that row's
434
483
  * category is in `hiddenCategories`. State lives in the part name rather than a separate
435
484
  * attribute, so `::part(legend-toggle-hidden)` is a reachable styling hook.
485
+ * @csspart legend-group - The `role="group"` wrapping one consecutive run of legend rows that
486
+ * share a `group`. Absent entirely when no admitted entry carries one, so an ungrouped legend's
487
+ * markup is unchanged.
488
+ * @csspart legend-group-heading - The visible heading naming a `legend-group`. It renders the
489
+ * caller-supplied `group` string verbatim and names the group through `aria-labelledby`.
490
+ * @csspart legend-disclosure - The `button` that collapses and expands the whole legend panel.
491
+ * Rendered only when `legendCollapsible` is set, so an unset map's legend markup is unchanged.
492
+ * It carries the localized panel name as its visible, accessible label plus `aria-expanded`
493
+ * rendered as the literal `"true"`/`"false"`, and it grows to the shared `--lr-icon-button-size`
494
+ * hit-area floor.
495
+ * @csspart legend-disclosure-icon - The decorative chevron inside `legend-disclosure`. It is the
496
+ * wrapping part that rotates (per the shared icon set's contract), including under RTL.
436
497
  * @csspart legend-gradient - The continuous ramp bar rendered from `legendGradient`.
437
498
  * @csspart legend-lo - The low endpoint caption of the `legendGradient` bar (mirrors `lr-heatmap`).
438
499
  * @csspart legend-hi - The high endpoint caption of the `legendGradient` bar (mirrors `lr-heatmap`).
@@ -520,7 +581,7 @@ renderWorldCopies?:boolean;
520
581
  maxBounds:LyraMapBounds|null;
521
582
  /** Required MapLibre style URL or peer-neutral style specification. No provider is contacted
522
583
  * unless a consumer assigns this property. */
523
- mapStyle?:Readonly<LyraMapStyleSpecification> |string;private _legend;private _legendProjection;
584
+ mapStyle?:Readonly<LyraMapStyleSpecification> |string;private _legend;private _legendProjection;private _legendGrouped;
524
585
  /** Immutable, bounded entries rendered in the optional map legend. A required pattern keeps
525
586
  * category identity available when authored colors collapse or are unavailable. */
526
587
  get legend():readonly LyraMapLegendEntry[];set legend(value:readonly LyraMapLegendEntry[]);
@@ -532,6 +593,9 @@ get legend():readonly LyraMapLegendEntry[];set legend(value:readonly LyraMapLege
532
593
  * it. `slotchange` still runs afterwards to track content added or removed later.
533
594
  */
534
595
  private hasLegendSlot;
596
+ /** The same presence flag for `slot="legend-start"`, tracked separately so a header alone opens
597
+ * the panel and so the two extension points never stand in for one another. */
598
+ private hasLegendStartSlot;
535
599
  /** Light-DOM probe for slotted legend content, valid before the slot itself has ever rendered. */
536
600
  private probeLegendSlot;private _legendGradient;
537
601
  /**
@@ -573,7 +637,72 @@ get legendProjection():LyraMapLegendProjection;
573
637
  * 100-series `lr-chart` legend does. Each row also grows to the `--lr-icon-button-size` hit-area
574
638
  * floor; the legend panel's own `max-block-size`/`overflow: auto` contains the taller list.
575
639
  */
576
- legendInteractive:boolean;private _hiddenCategories;
640
+ legendInteractive:boolean;private _legendControlRole;
641
+ /**
642
+ * How each keyed `legendInteractive` row's toggle control presents itself to assistive tech.
643
+ * Inert while `legendInteractive` is unset, exactly like the toggle itself.
644
+ *
645
+ * - `'button'` (default) -- `<button aria-pressed>`, byte-identical to every 18.1.0 interactive
646
+ * legend. Leaving this property unset changes nothing.
647
+ * - `'checkbox'` -- the SAME `<button>` element `renderLegendRow()` already renders, with its
648
+ * implicit role overridden to `role="checkbox"` and `aria-checked` in place of `aria-pressed`.
649
+ * A native `<input type="checkbox">` was considered and rejected: it would need its own
650
+ * swatch/label markup and its own click/keyboard wiring duplicated from the button branch,
651
+ * splitting `renderLegendRowContent()` in two. `<button role="checkbox">` keeps the swatch,
652
+ * the label, the click handler and the platform's own Enter/Space activation exactly as they
653
+ * are for the button branch -- only the two ARIA attributes differ, so the CSS in
654
+ * `map.styles.ts` (which targets `button[part~='legend-toggle']`, never a role or an ARIA
655
+ * state) needs no `'checkbox'`-specific rule.
656
+ *
657
+ * `aria-checked` tracks the same `visible` flag `aria-pressed` does, inverted from
658
+ * `hiddenCategories`: a hidden category renders `aria-checked="false"`. Both states always
659
+ * render explicitly (`"true"`/`"false"`), never a Lit `?aria-*` presence directive, which cannot
660
+ * express the false state at all.
661
+ */
662
+ get legendControlRole():LyraMapLegendControlRole;set legendControlRole(next:LyraMapLegendControlRole);
663
+ /**
664
+ * Renders a disclosure button inside the legend panel that collapses the key down to its header.
665
+ * Default `false`, and an unset map renders exactly the panel it rendered before this property
666
+ * existed -- no button, no `id` minted on the row list, and no `hidden` attribute anywhere.
667
+ *
668
+ * A collapsed panel hides the gradient bar, the rows, the `legend-limit` summary and the
669
+ * trailing `legend` slot; the `legend-start` slot and the disclosure itself stay visible, so a
670
+ * slotted header survives the collapse and the control that would restore the key is never the
671
+ * thing the collapse hides.
672
+ */
673
+ legendCollapsible:boolean;
674
+ /**
675
+ * Whether a `legendCollapsible` panel is expanded. Defaults **open**, so adding only
676
+ * `legendCollapsible` never hides an existing key; it does nothing at all while
677
+ * `legendCollapsible` is unset.
678
+ *
679
+ * It is a `true`-defaulting boolean, so it uses `trueDefaultBooleanConverter` rather than Lit's
680
+ * presence-based boolean converter, which cannot express `legend-open="false"` at all. The
681
+ * reflection follows the same converter: open (the default) reflects as an ABSENT attribute and
682
+ * collapsed reflects as `legend-open="false"`.
683
+ *
684
+ * Controlled public state, so -- exactly like `hiddenCategories` -- it deliberately survives a
685
+ * disconnect and reconnect: the "reset transient open-state in `disconnectedCallback()`" rule
686
+ * covers dropdown/preview/tooltip `@state`, not a documented property a host owns and re-reads.
687
+ * A programmatic assignment reconciles the rendered panel without emitting
688
+ * `lr-map-legend-panel-toggle`, so a controlled host cannot loop.
689
+ */
690
+ legendOpen:boolean;
691
+ /** True only when a collapsible panel is actually collapsed. `legendOpen` alone never hides
692
+ * anything, so an author who sets `legend-open="false"` without `legendCollapsible` -- and
693
+ * therefore renders no control to restore it -- still gets a readable key. */
694
+ private get legendCollapsed();
695
+ /**
696
+ * Flips the whole panel's disclosure from the `legendCollapsible` button.
697
+ *
698
+ * The veto is the absence of a write, not a write that is undone afterwards: a listener that
699
+ * owns the open state can assign its own `legendOpen` without this handler clobbering it.
700
+ */
701
+ private toggleLegendPanel;
702
+ /** The panel disclosure, or nothing at all when the panel cannot collapse. The chevron is
703
+ * decorative: the button's own visible, localized text carries its name, and `aria-expanded`
704
+ * carries the state. */
705
+ private renderLegendDisclosure;private _hiddenCategories;
577
706
  /**
578
707
  * Complete controlled set of muted category keys, mirroring `lr-chart`'s `hiddenDatasets`.
579
708
  * Clone-owned and frozen; non-string, empty, whitespace-only and duplicate entries are dropped,
@@ -812,4 +941,31 @@ private toggleLegendCategory;
812
941
  private announceLegendVisibility;
813
942
  /** Acquired lazily on the first toggle, and re-acquired against a new owner document, so a map
814
943
  * that never renders an interactive legend never mounts a live region at all. */
815
- private syncLegendAnnouncementSink;private releaseLegendAnnouncementSink;private renderLegendGradient;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-map':LyraMap;}}
944
+ private syncLegendAnnouncementSink;private releaseLegendAnnouncementSink;
945
+ /**
946
+ * One legend row. Extracted verbatim from the list template so the grouped and ungrouped section
947
+ * paths below render the same node rather than two copies that can drift.
948
+ *
949
+ * `aria-posinset`/`aria-setsize` deliberately stay whole-key values inside a section too.
950
+ * `aria-setsize` already reports the *input* count rather than the rendered one, so a bounded key
951
+ * stays honest; per-section input counts do not exist, because a row dropped by the bound carries
952
+ * no attributable group. A section adds a labelled sub-region; it does not renumber the key.
953
+ */
954
+ private renderLegendRow;
955
+ /**
956
+ * The row list's children: bare rows when no admitted entry carries a `group`, and otherwise one
957
+ * `role="group"` per CONSECUTIVE run sharing a group name, with ungrouped rows left exactly where
958
+ * they were declared. The ungrouped branch is literally the expression this list has always been,
959
+ * so a legend that uses no sections keeps rendering the markup it rendered before they existed.
960
+ *
961
+ * `group` is caller-supplied data: the heading renders it verbatim and never resolves it through
962
+ * the locale catalog.
963
+ *
964
+ * Each section owns its OWN `role="list"` rather than the sections sitting directly inside the
965
+ * outer one. `list` requires `listitem` children, and a `group` is not one -- axe reports both
966
+ * `aria-required-children` on the outer list and `aria-required-parent` on every row inside the
967
+ * group, critical, which is how this shape was caught. So a grouped legend renders one list per
968
+ * run (including each ungrouped run) and the outer element drops its own `role`, while an
969
+ * ungrouped legend keeps the single `role="list"` it has always had.
970
+ */
971
+ private renderLegendRows;private renderLegendGradient;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-map':LyraMap;}}