@aceshooting/lyra-ui 18.1.0 → 18.3.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 (36) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/custom-elements.json +1 -1
  3. package/design-tokens.json +1 -1
  4. package/dist/components/data/heatmap/heatmap.class.d.ts +10 -0
  5. package/dist/components/data/heatmap/heatmap.class.js +1 -1
  6. package/dist/components/media/image-viewer/image-viewer.class.js +1 -1
  7. package/dist/components/media/lightbox/lightbox.class.d.ts +7 -2
  8. package/dist/components/media/lightbox/lightbox.class.js +3 -2
  9. package/dist/components/media/map/map.class.d.ts +28 -1
  10. package/dist/components/media/map/map.class.js +7 -5
  11. package/dist/components/media/pan-zoom/pan-zoom.class.d.ts +6 -2
  12. package/dist/components/media/pan-zoom/pan-zoom.class.js +2 -2
  13. package/dist/components/media/pan-zoom/pan-zoom.styles.js +1 -1
  14. package/dist/components/utility/export-button/export-button.class.d.ts +13 -2
  15. package/dist/components/utility/export-button/export-button.class.js +2 -2
  16. package/dist/components/utility/export-button/export-button.styles.js +1 -1
  17. package/dist/custom-elements-jsx.d.ts +1 -1
  18. package/dist/internal/image-fit.d.ts +1 -0
  19. package/dist/internal/image-fit.js +1 -0
  20. package/dist/internal/package-metadata.d.ts +1 -1
  21. package/dist/internal/package-metadata.js +1 -1
  22. package/dist/internal/tokens.styles.js +1 -1
  23. package/dist/lyra.d.ts +1 -1
  24. package/dist/svelte.d.ts +1 -1
  25. package/dist/vue.d.ts +1 -1
  26. package/llms/components/lr-export-button.md +5 -0
  27. package/llms/components/lr-heatmap.md +7 -3
  28. package/llms/components/lr-lightbox.md +11 -0
  29. package/llms/components/lr-map.md +19 -4
  30. package/llms/components/lr-pan-zoom.md +4 -0
  31. package/llms/shared.md +6 -1
  32. package/llms/tokens.md +5 -3
  33. package/llms-full.txt +52 -8
  34. package/package.json +1 -1
  35. package/vscode-html-data.json +1 -1
  36. package/web-types.json +1 -1
@@ -57,6 +57,11 @@ extension?: string }`. Descriptor labels/descriptions are consumer-supplied, alr
57
57
  copy. `formatId` must be nonempty and unique; malformed options and later duplicates are omitted
58
58
  first-wins before menu state, focus reconciliation, or export events. Custom format ids are
59
59
  event-only; no custom encoder is bundled
60
+ - `size?: LyraSize` — optional density on the shared `2xs` through `xl` ladder, including the
61
+ `small`/`medium`/`large` aliases. It changes trigger and menu-row typography and padding while
62
+ retaining the shared 40px minimum hit-area floor. Unset preserves the established geometry
63
+ - `appearance?: LyraExportButtonAppearance` — `outlined` or `quiet` trigger treatment. Unset
64
+ preserves the established surface, border, and text colors
60
65
  - `disabled: boolean = false` (reflected) — also disables every `[part="menu-item"]` button, not just
61
66
  the trigger
62
67
  - `loading: boolean = false` (reflected) — controlled busy state for an async or server-generated
@@ -348,9 +348,13 @@ color?: string; label?: string; partOfRamp?: boolean }`: a discrete legend key r
348
348
  "no data" color next to an N-step ramp) to exclude just that stop from the comparison; defaults to
349
349
  `true`. A caption-only stop (no `color`) is already excluded regardless of this flag.
350
350
 
351
- **Getters/methods:** `refreshTheme()` redraws canvas content after an upstream design-token or
352
- color-scheme change; called automatically on theme changes, exposed for a consumer that needs to
353
- force a redraw manually. `matrixGeometry: Readonly<LyraHeatmapMatrixGeometryChangeDetail> | undefined` — the gutter/cell geometry the last matrix-mode draw actually painted with,
351
+ **Getters/methods:** `exportData('png')` returns a PNG data URL for the most recently completed
352
+ canvas paint. It includes the painted axes, cells, focus/selection/annotation overlays, and frozen
353
+ label bands while `stickyLabels` is enabled; the DOM legend, tooltip, and accessible-cell buttons
354
+ are deliberately excluded. It returns `''` before a completed paint, while rendering is deferred or
355
+ zero-sized, after disconnect, or when the browser cannot encode the snapshot. `refreshTheme()` —
356
+ redraws canvas content after an upstream design-token or color-scheme change; called automatically
357
+ on theme changes, exposed for a consumer that needs to force a redraw manually. `matrixGeometry: Readonly<LyraHeatmapMatrixGeometryChangeDetail> | undefined` — the gutter/cell geometry the last matrix-mode draw actually painted with,
354
358
  in CSS pixels; `undefined` in calendar mode. Lets a light-DOM consumer line up with the canvas
355
359
  without hardcoding the same numbers `row-label-width`/`col-label-height`'s `"auto"` resolution would
356
360
  otherwise keep private. For the case that motivated it — a frozen header or gutter on a tall or wide
@@ -46,6 +46,13 @@ trap, Escape/backdrop dismissal, scroll lock, and focus return.
46
46
  - `minZoom: number = 0.5`, `maxZoom: number = 4`, `zoomStep: number = 0.25` (attributes `min-zoom`/
47
47
  `max-zoom`/`zoom-step`) — pure pass-throughs to the embedded `<lr-pan-zoom>`, which does the
48
48
  normalizing.
49
+ - `fit: LyraImageFit = 'actual'` (reflected) — opt-in base sizing policy for the current image,
50
+ reusing `<lr-image-viewer>`'s `contain`/`width`/`actual` vocabulary. The default preserves the
51
+ existing natural-size behavior. `contain` fits both landscape and tall images inside the stage;
52
+ `width` fills its inline size. CSS recalculates either policy when the stage is resized or a
53
+ delayed image source finishes loading, so navigation and opening do not require consumer timers.
54
+ Fit is the base zoom policy: an explicit user zoom remains until navigation or a reset, and
55
+ changing the theme does not mutate the lightbox's zoom property.
49
56
  - `accessibleLabel: string | null = null` (attribute `aria-label`) — the panel's accessible name,
50
57
  overriding the localized `lightboxLabel`.
51
58
 
@@ -102,6 +109,10 @@ photo content.
102
109
  - zoom/pan reset on navigation is imperative (`resetView()` from `updated()`), not a binding; the
103
110
  frame element is reused across navigations rather than recreated, so a keyboard user who tabbed
104
111
  into the viewport keeps focus.
112
+ - fit sizing is CSS-driven inside the stable frame. The rendered DOM image is not copied or
113
+ measured by the lightbox, so stale load events cannot apply a previous image's size. The fit
114
+ policy covers the painted image only; the lightbox's DOM caption, toolbar, legend-like actions,
115
+ and tooltip content remain outside that image surface.
105
116
  - scope for v1: no per-image slotted content (data-driven via `images` only), no dot indicators, no
106
117
  visual open/close animation, no click-image-to-navigate, no touch-swipe. Lifecycle phases are
107
118
  still observable through the before/after events and methods above.
@@ -115,6 +115,18 @@ omittedCount, truncatedLabelCount, truncated }` result for the latest assignment
115
115
  roving tabindex: a 100-row interactive legend contributes 100 tab stops, exactly as a 100-series
116
116
  `lr-chart` legend does. Each interactive row also grows to the shared `--lr-icon-button-size`
117
117
  hit-area floor (WCAG 2.5.8), which the panel's existing `max-block-size` and scrolling contain.
118
+ - `legendControlRole: 'button' | 'checkbox' = 'button'` (attribute `legend-control-role`,
119
+ reflected) — how each `legendInteractive` row's toggle presents itself to assistive tech; inert
120
+ while `legendInteractive` is unset, exactly like the toggle itself. `'button'` is byte-identical
121
+ to every legend rendered before this property existed: `<button aria-pressed>`. `'checkbox'`
122
+ renders the SAME `<button>` element with its implicit role overridden to `role="checkbox"` and
123
+ `aria-checked` in place of `aria-pressed` — the swatch, the label, the click handler and the
124
+ platform's own Enter/Space activation are unchanged, so `hiddenCategories`, the cancelable
125
+ `lr-map-legend-toggle` veto, `group` sections and `legendCollapsible` all compose with either
126
+ role. `aria-checked` tracks the same visibility flag `aria-pressed` does, inverted from
127
+ `hiddenCategories`: a hidden category renders `aria-checked="false"`. Prefer `'checkbox'` when the
128
+ legend reads as a checklist of independent show/hide toggles; prefer the `'button'` default when
129
+ it reads as a set of filtering actions. An unsupported value normalizes back to `'button'`.
118
130
  - `legendCollapsible: boolean = false` (attribute `legend-collapsible`, reflected) — opt-in: renders
119
131
  a `legend-disclosure` `button` inside the panel that collapses the key down to its header, so a
120
132
  large legend stops permanently covering part of the map. Unset, the panel renders exactly what it
@@ -509,10 +521,13 @@ container in the tree, so `legend` withholds `aria-controls` rather than leaving
509
521
  idref.
510
522
  Under `legendInteractive`, a row carrying a `value` wraps its swatch and label in a
511
523
  `legend-toggle` `button` with `aria-pressed` rendered as the literal `"true"`/`"false"` — never
512
- omitted, because a missing attribute reports "not a toggle button" rather than "unpressed". The
513
- button's accessible name is its own visible label (caller-supplied data, so deliberately not
514
- localized), scoped by the legend's own localized group name; no `aria-label` restates the state,
515
- which would make assistive tech announce it twice. A hidden row's button additionally carries the
524
+ omitted, because a missing attribute reports "not a toggle button" rather than "unpressed". Setting
525
+ `legendControlRole="checkbox"` renders the SAME `button` with `role="checkbox"` and `aria-checked`
526
+ (also always the literal `"true"`/`"false"`) in place of `aria-pressed`, and nothing else about the
527
+ row changes. The button's accessible name is its own visible label (caller-supplied data, so
528
+ deliberately not localized), scoped by the legend's own localized group name; no `aria-label`
529
+ restates the state, which would make assistive tech announce it twice. A hidden row's button
530
+ additionally carries the
516
531
  `legend-toggle-hidden` token — state lives in the part name, so `::part(legend-toggle-hidden)` is a
517
532
  reachable hook — and dims only its `aria-hidden` swatch while re-colouring the label through the
518
533
  quiet text token, so the label keeps AA contrast rather than fading with the whole button. In
@@ -27,6 +27,10 @@ import to `LyraPanZoom`); `lr-zoomable-frame` now means the mapped iframe compon
27
27
  `zoomStep: number = 0.25` — bounded, finite zoom configuration
28
28
  - `src: string = ''` and `alt: string = ''` — optional safe image source. A rejected URL is treated
29
29
  as absent and the default slot renders; no empty or unsafe `<img>` replaces that fallback.
30
+ - `fit: LyraImageFit = 'actual'` (reflected) — base sizing policy for an image supplied through
31
+ `src`, using the same `contain`/`width`/`actual` vocabulary as `<lr-image-viewer>`. `actual`
32
+ preserves the historical natural-size layout; the other modes resolve against the viewport and
33
+ update with its allocation, including when an image loads after the frame first renders.
30
34
  - `accessibleLabel: string | null` (attribute `aria-label`) — a declarative host label remains on
31
35
  the host while the focusable viewport receives the localized inspection-surface purpose name.
32
36
  A property-only value names the viewport and updates reactively without creating a host attribute. This avoids cloning one author label onto both the outer component and nested `role="group"`. An explicitly empty direct property remains empty; a present host attribute, including an empty one, leaves the viewport's localized purpose name intact.
package/llms/shared.md CHANGED
@@ -1177,7 +1177,12 @@ code. See each control's own reference page for its exact pair.
1177
1177
  | `--lr-icon-button-size-scope` | one subtree | the wrapper you want affected |
1178
1178
  | `--lr-icon-button-size` | one element | the icon-only control itself |
1179
1179
 
1180
- `--lr-theme-icon-button-size` wins wherever both ancestor inputs are set. `--lr-icon-button-size`
1180
+ `--lr-icon-button-size-scope` wins wherever both ancestor inputs are set — the narrower scope
1181
+ takes precedence, and it has to: the shipped `design-tokens.css` declares
1182
+ `--lr-theme-icon-button-size` on `:root`, and a `var()` chain only falls through for a property
1183
+ that is unset *everywhere*, not merely shadowed nearer the element. Reading the theme tier first
1184
+ therefore made this knob inert for anyone loading that stylesheet (a real 18.1.0 defect, fixed in
1185
+ 18.2.0). `--lr-icon-button-size`
1181
1186
  is **element-scoped on purpose** and is not a wrapper knob: every component re-declares it on its
1182
1187
  own host so the touch-target floor can apply per element, so a value set on a wrapper is replaced
1183
1188
  at the first component in between and never reaches anything nested inside one. That behaviour is
package/llms/tokens.md CHANGED
@@ -55,8 +55,10 @@ look arbitrary rather than systematic. Reach through a subtree with `--lr-theme-
55
55
  `--lr-theme-otp-input-segment-size`, or `--lr-theme-popover-viewport-clamp` instead.
56
56
  `--lr-icon-button-size` additionally has a dedicated subtree-scoped input,
57
57
  `--lr-icon-button-size-scope`, which an ancestor rule can set without reaching for the
58
- application-wide `--lr-theme-icon-button-size`; the theme input still wins over it when both
59
- are set. Every other `--lr-<component>-*` token including
58
+ application-wide `--lr-theme-icon-button-size`. The subtree input wins where both are set,
59
+ because the shipped `design-tokens.css` declares the theme tier on `:root` and a var() chain
60
+ only falls through for a property that is unset everywhere. Every other `--lr-<component>-*`
61
+ token — including
60
62
  the rest of `lr-icon-button`'s own (`-radius`, `-background`, `-color`, `-border`, and their
61
63
  `-hover`/`-active` variants) — is not re-declared anywhere in the shared layer and inherits
62
64
  normally from an ancestor.
@@ -178,7 +180,7 @@ normally from an ancestor.
178
180
  | `--lr-graph-cat-7` | `--lr-theme-graph-cat-7` | `#52d6e8` | dark: `var(--lr-theme-graph-cat-7, #79e2ef)`<br>forcedColors: `Highlight` |
179
181
  | `--lr-graph-cat-8` | `--lr-theme-graph-cat-8` | `#c9d1d9` | dark: `var(--lr-theme-graph-cat-8, #e4e7eb)`<br>forcedColors: `LinkText` |
180
182
  | `--lr-hover-brightness` | `--lr-theme-hover-brightness` | `1.08` | — |
181
- | `--lr-icon-button-size` | `--lr-theme-icon-button-size` | `var(--lr-icon-button-size-scope, 2.5rem)` | — |
183
+ | `--lr-icon-button-size` | `--lr-theme-icon-button-size` | `2.5rem` | — |
182
184
  | `--lr-layer-base` | `--lr-theme-z-index-base` | `0` | — |
183
185
  | `--lr-layer-content` | `--lr-theme-z-index-content` | `1` | — |
184
186
  | `--lr-layer-dropdown` | `--lr-theme-z-index-dropdown` | `900` | — |
package/llms-full.txt CHANGED
@@ -1229,7 +1229,12 @@ code. See each control's own reference page for its exact pair.
1229
1229
  | `--lr-icon-button-size-scope` | one subtree | the wrapper you want affected |
1230
1230
  | `--lr-icon-button-size` | one element | the icon-only control itself |
1231
1231
 
1232
- `--lr-theme-icon-button-size` wins wherever both ancestor inputs are set. `--lr-icon-button-size`
1232
+ `--lr-icon-button-size-scope` wins wherever both ancestor inputs are set — the narrower scope
1233
+ takes precedence, and it has to: the shipped `design-tokens.css` declares
1234
+ `--lr-theme-icon-button-size` on `:root`, and a `var()` chain only falls through for a property
1235
+ that is unset *everywhere*, not merely shadowed nearer the element. Reading the theme tier first
1236
+ therefore made this knob inert for anyone loading that stylesheet (a real 18.1.0 defect, fixed in
1237
+ 18.2.0). `--lr-icon-button-size`
1233
1238
  is **element-scoped on purpose** and is not a wrapper knob: every component re-declares it on its
1234
1239
  own host so the touch-target floor can apply per element, so a value set on a wrapper is replaced
1235
1240
  at the first component in between and never reaches anything nested inside one. That behaviour is
@@ -13697,9 +13702,13 @@ color?: string; label?: string; partOfRamp?: boolean }`: a discrete legend key r
13697
13702
  "no data" color next to an N-step ramp) to exclude just that stop from the comparison; defaults to
13698
13703
  `true`. A caption-only stop (no `color`) is already excluded regardless of this flag.
13699
13704
 
13700
- **Getters/methods:** `refreshTheme()` redraws canvas content after an upstream design-token or
13701
- color-scheme change; called automatically on theme changes, exposed for a consumer that needs to
13702
- force a redraw manually. `matrixGeometry: Readonly<LyraHeatmapMatrixGeometryChangeDetail> | undefined` — the gutter/cell geometry the last matrix-mode draw actually painted with,
13705
+ **Getters/methods:** `exportData('png')` returns a PNG data URL for the most recently completed
13706
+ canvas paint. It includes the painted axes, cells, focus/selection/annotation overlays, and frozen
13707
+ label bands while `stickyLabels` is enabled; the DOM legend, tooltip, and accessible-cell buttons
13708
+ are deliberately excluded. It returns `''` before a completed paint, while rendering is deferred or
13709
+ zero-sized, after disconnect, or when the browser cannot encode the snapshot. `refreshTheme()` —
13710
+ redraws canvas content after an upstream design-token or color-scheme change; called automatically
13711
+ on theme changes, exposed for a consumer that needs to force a redraw manually. `matrixGeometry: Readonly<LyraHeatmapMatrixGeometryChangeDetail> | undefined` — the gutter/cell geometry the last matrix-mode draw actually painted with,
13703
13712
  in CSS pixels; `undefined` in calendar mode. Lets a light-DOM consumer line up with the canvas
13704
13713
  without hardcoding the same numbers `row-label-width`/`col-label-height`'s `"auto"` resolution would
13705
13714
  otherwise keep private. For the case that motivated it — a frozen header or gutter on a tall or wide
@@ -24824,6 +24833,11 @@ extension?: string }`. Descriptor labels/descriptions are consumer-supplied, alr
24824
24833
  copy. `formatId` must be nonempty and unique; malformed options and later duplicates are omitted
24825
24834
  first-wins before menu state, focus reconciliation, or export events. Custom format ids are
24826
24835
  event-only; no custom encoder is bundled
24836
+ - `size?: LyraSize` — optional density on the shared `2xs` through `xl` ladder, including the
24837
+ `small`/`medium`/`large` aliases. It changes trigger and menu-row typography and padding while
24838
+ retaining the shared 40px minimum hit-area floor. Unset preserves the established geometry
24839
+ - `appearance?: LyraExportButtonAppearance` — `outlined` or `quiet` trigger treatment. Unset
24840
+ preserves the established surface, border, and text colors
24827
24841
  - `disabled: boolean = false` (reflected) — also disables every `[part="menu-item"]` button, not just
24828
24842
  the trigger
24829
24843
  - `loading: boolean = false` (reflected) — controlled busy state for an async or server-generated
@@ -27360,6 +27374,18 @@ omittedCount, truncatedLabelCount, truncated }` result for the latest assignment
27360
27374
  roving tabindex: a 100-row interactive legend contributes 100 tab stops, exactly as a 100-series
27361
27375
  `lr-chart` legend does. Each interactive row also grows to the shared `--lr-icon-button-size`
27362
27376
  hit-area floor (WCAG 2.5.8), which the panel's existing `max-block-size` and scrolling contain.
27377
+ - `legendControlRole: 'button' | 'checkbox' = 'button'` (attribute `legend-control-role`,
27378
+ reflected) — how each `legendInteractive` row's toggle presents itself to assistive tech; inert
27379
+ while `legendInteractive` is unset, exactly like the toggle itself. `'button'` is byte-identical
27380
+ to every legend rendered before this property existed: `<button aria-pressed>`. `'checkbox'`
27381
+ renders the SAME `<button>` element with its implicit role overridden to `role="checkbox"` and
27382
+ `aria-checked` in place of `aria-pressed` — the swatch, the label, the click handler and the
27383
+ platform's own Enter/Space activation are unchanged, so `hiddenCategories`, the cancelable
27384
+ `lr-map-legend-toggle` veto, `group` sections and `legendCollapsible` all compose with either
27385
+ role. `aria-checked` tracks the same visibility flag `aria-pressed` does, inverted from
27386
+ `hiddenCategories`: a hidden category renders `aria-checked="false"`. Prefer `'checkbox'` when the
27387
+ legend reads as a checklist of independent show/hide toggles; prefer the `'button'` default when
27388
+ it reads as a set of filtering actions. An unsupported value normalizes back to `'button'`.
27363
27389
  - `legendCollapsible: boolean = false` (attribute `legend-collapsible`, reflected) — opt-in: renders
27364
27390
  a `legend-disclosure` `button` inside the panel that collapses the key down to its header, so a
27365
27391
  large legend stops permanently covering part of the map. Unset, the panel renders exactly what it
@@ -27754,10 +27780,13 @@ container in the tree, so `legend` withholds `aria-controls` rather than leaving
27754
27780
  idref.
27755
27781
  Under `legendInteractive`, a row carrying a `value` wraps its swatch and label in a
27756
27782
  `legend-toggle` `button` with `aria-pressed` rendered as the literal `"true"`/`"false"` — never
27757
- omitted, because a missing attribute reports "not a toggle button" rather than "unpressed". The
27758
- button's accessible name is its own visible label (caller-supplied data, so deliberately not
27759
- localized), scoped by the legend's own localized group name; no `aria-label` restates the state,
27760
- which would make assistive tech announce it twice. A hidden row's button additionally carries the
27783
+ omitted, because a missing attribute reports "not a toggle button" rather than "unpressed". Setting
27784
+ `legendControlRole="checkbox"` renders the SAME `button` with `role="checkbox"` and `aria-checked`
27785
+ (also always the literal `"true"`/`"false"`) in place of `aria-pressed`, and nothing else about the
27786
+ row changes. The button's accessible name is its own visible label (caller-supplied data, so
27787
+ deliberately not localized), scoped by the legend's own localized group name; no `aria-label`
27788
+ restates the state, which would make assistive tech announce it twice. A hidden row's button
27789
+ additionally carries the
27761
27790
  `legend-toggle-hidden` token — state lives in the part name, so `::part(legend-toggle-hidden)` is a
27762
27791
  reachable hook — and dims only its `aria-hidden` swatch while re-colouring the label through the
27763
27792
  quiet text token, so the label keeps AA contrast rather than fading with the whole button. In
@@ -28527,6 +28556,10 @@ import to `LyraPanZoom`); `lr-zoomable-frame` now means the mapped iframe compon
28527
28556
  `zoomStep: number = 0.25` — bounded, finite zoom configuration
28528
28557
  - `src: string = ''` and `alt: string = ''` — optional safe image source. A rejected URL is treated
28529
28558
  as absent and the default slot renders; no empty or unsafe `<img>` replaces that fallback.
28559
+ - `fit: LyraImageFit = 'actual'` (reflected) — base sizing policy for an image supplied through
28560
+ `src`, using the same `contain`/`width`/`actual` vocabulary as `<lr-image-viewer>`. `actual`
28561
+ preserves the historical natural-size layout; the other modes resolve against the viewport and
28562
+ update with its allocation, including when an image loads after the frame first renders.
28530
28563
  - `accessibleLabel: string | null` (attribute `aria-label`) — a declarative host label remains on
28531
28564
  the host while the focusable viewport receives the localized inspection-surface purpose name.
28532
28565
  A property-only value names the viewport and updates reactively without creating a host attribute. This avoids cloning one author label onto both the outer component and nested `role="group"`. An explicitly empty direct property remains empty; a present host attribute, including an empty one, leaves the viewport's localized purpose name intact.
@@ -29514,6 +29547,13 @@ trap, Escape/backdrop dismissal, scroll lock, and focus return.
29514
29547
  - `minZoom: number = 0.5`, `maxZoom: number = 4`, `zoomStep: number = 0.25` (attributes `min-zoom`/
29515
29548
  `max-zoom`/`zoom-step`) — pure pass-throughs to the embedded `<lr-pan-zoom>`, which does the
29516
29549
  normalizing.
29550
+ - `fit: LyraImageFit = 'actual'` (reflected) — opt-in base sizing policy for the current image,
29551
+ reusing `<lr-image-viewer>`'s `contain`/`width`/`actual` vocabulary. The default preserves the
29552
+ existing natural-size behavior. `contain` fits both landscape and tall images inside the stage;
29553
+ `width` fills its inline size. CSS recalculates either policy when the stage is resized or a
29554
+ delayed image source finishes loading, so navigation and opening do not require consumer timers.
29555
+ Fit is the base zoom policy: an explicit user zoom remains until navigation or a reset, and
29556
+ changing the theme does not mutate the lightbox's zoom property.
29517
29557
  - `accessibleLabel: string | null = null` (attribute `aria-label`) — the panel's accessible name,
29518
29558
  overriding the localized `lightboxLabel`.
29519
29559
 
@@ -29570,6 +29610,10 @@ photo content.
29570
29610
  - zoom/pan reset on navigation is imperative (`resetView()` from `updated()`), not a binding; the
29571
29611
  frame element is reused across navigations rather than recreated, so a keyboard user who tabbed
29572
29612
  into the viewport keeps focus.
29613
+ - fit sizing is CSS-driven inside the stable frame. The rendered DOM image is not copied or
29614
+ measured by the lightbox, so stale load events cannot apply a previous image's size. The fit
29615
+ policy covers the painted image only; the lightbox's DOM caption, toolbar, legend-like actions,
29616
+ and tooltip content remain outside that image surface.
29573
29617
  - scope for v1: no per-image slotted content (data-driven via `images` only), no dot indicators, no
29574
29618
  visual open/close animation, no click-image-to-navigate, no touch-swipe. Lifecycle phases are
29575
29619
  still observable through the before/after events and methods above.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aceshooting/lyra-ui",
3
- "version": "18.1.0",
3
+ "version": "18.3.0",
4
4
  "description": "Free, independent Lit web components: an open-source alternative to Shoelace and Web Awesome with accessible forms, dashboards, charts, and agent UI.",
5
5
  "keywords": [
6
6
  "web-components",