@aceshooting/lyra-ui 25.1.0 → 25.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.
@@ -2,4 +2,4 @@
2
2
  * Generated from package.json by scripts/generate-package-metadata.mjs.
3
3
  * Run `pnpm package-metadata` after changing package identity or version.
4
4
  */
5
- export declare const LYRA_PACKAGE_NAME:'@aceshooting/lyra-ui';export declare const LYRA_PACKAGE_VERSION:'25.1.0';
5
+ export declare const LYRA_PACKAGE_NAME:'@aceshooting/lyra-ui';export declare const LYRA_PACKAGE_VERSION:'25.3.0';
@@ -1 +1 @@
1
- const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="25.1.0";export{LYRA_PACKAGE_NAME,LYRA_PACKAGE_VERSION};
1
+ const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="25.3.0";export{LYRA_PACKAGE_NAME,LYRA_PACKAGE_VERSION};
@@ -701,8 +701,10 @@ synchronous and fires no `input`/`change`/`lr-change` event.
701
701
  - `aria-required` reflects `required` immediately; `aria-invalid`, by contrast, only reflects
702
702
  **after the field has been touched** (first `blur`) — a `required` field with a validity error
703
703
  doesn't look invalid to assistive tech before that, by design (avoids flashing invalid styling on
704
- first render). Blurring the input (Tab away) now also closes an open listbox, the same as a
705
- native `<select>`'s popup, not just a click outside or Escape.
704
+ first render). Moving focus outside the combobox trigger (Tab away) closes an open listbox,
705
+ the same as a native `<select>`'s popup. Moving from the input to its clear button retains the
706
+ filter until the button activates; clearing returns focus to the input without changing whether
707
+ the listbox is open.
706
708
  - `dotColor`/`sub`/`group` are read from light-DOM `<lr-option>` children as before, but are also
707
709
  first-class fields on `ComboboxSourceRow` for the async `source` path — an async lookup can drive
708
710
  the same grouped/dot/sub-text rendering a static option list can.
@@ -99,7 +99,7 @@ readonly LyraLocaleEntry[]`, `LyraLocaleEntry { tag: string; label?: string; cou
99
99
  unset, selection commits synchronously without loading a catalog. Set it to `loadLyraLocale` from
100
100
  `@aceshooting/lyra-ui/locale-loader.js` to import the selected built-in catalog before committing.
101
101
  The loader accepts exact shipped canonical tags (equivalent casing/underscores normalize), shares
102
- concurrent requests, and permits retry after a failed import. `en` needs no import; an unshipped
102
+ concurrent requests, and clears its promise cache after rejection. `en` needs no import; an unshipped
103
103
  regional tag rejects instead of claiming a translation. Importing the helper does not load a catalog
104
104
  or select the page locale. Supply an explicit `locales` list to offer catalogs before registration.
105
105
 
@@ -114,7 +114,11 @@ picker.localeLoader = loadLyraLocale;
114
114
  The unset callback preserves synchronous selection. A vetoed request never invokes the loader.
115
115
  While loading, the previous value stays committed and the trigger exposes `aria-busy`; a visible
116
116
  localized status and light-DOM announcement explain progress. Failure retains the value and offers
117
- Retry through a fresh request. An open listbox places above or below the full control and its
117
+ Retry through a fresh callback invocation. Browsers may cache failed native module fetches, so
118
+ Retry does not guarantee another network request. Retain the current locale and failure guidance;
119
+ if a native import remains failed after connectivity returns, offer a user-initiated page reload
120
+ after preserving unsaved work, or use an application-owned recoverable `localeLoader` transport.
121
+ The picker never reloads automatically. An open listbox places above or below the full control and its
118
122
  failure guidance, including when `top-layer` is enabled, so it cannot cover Retry. Dismissing and
119
123
  reopening the listbox retains the failure guidance and the reachable retry action.
120
124
  New selection, host value/catalog/loader writes, reset, disablement,
@@ -218,6 +222,12 @@ A compact header can set `trigger-display="flag"` and
218
222
  Import `@aceshooting/lyra-ui/components/media/flag/flag-peer.js` to register the optional flag
219
223
  resolver. Menu labels stay visible; a per-entry `country` override also reaches the compact trigger.
220
224
 
225
+ Option rows keep at least the medium control height (`--lr-form-control-height-m`, normally
226
+ `2.25rem`), including `option-display="label"` and a small flag trigger. Larger control tiers,
227
+ coarse-pointer control heights, larger text, and the optional tag line can grow the rows beyond
228
+ that floor. The listbox keeps its scrolling height limit; `size` does not make language rows
229
+ smaller than the medium floor.
230
+
221
231
  ```html
222
232
  <lr-locale-picker label="Language"></lr-locale-picker>
223
233
  <script type="module">
@@ -228,6 +228,9 @@ heatmap?: LyraMapHeatmapOptions; cluster?: LyraMapClusterOptions }`. `sourceId`
228
228
  fill is that faint. Deriving one from the other measured 1.41:1 against a light basemap — under
229
229
  WCAG 1.4.11's 3:1 floor for graphical objects. A `var(--lr-…)` reference is resolved against the
230
230
  host before it reaches MapLibre, which paints to a WebGL canvas and never sees the CSS cascade.
231
+ Data-layer, choropleth, cluster, and heatmap paint colors also accept modern CSS color functions
232
+ such as `color()`, `oklch()`, and `color-mix()`; Lyra resolves them to MapLibre-compatible sRGB
233
+ on application and theme repaint. An invalid explicit color falls back to the layer tone.
231
234
  The component
232
235
  assigns collision-free private MapLibre ids for those resources: `sourceId` is the stable
233
236
  declarative reconciliation key, **not** an id to retrieve from `map`. This prevents a data layer
@@ -248,7 +251,8 @@ heatmap?: LyraMapHeatmapOptions; cluster?: LyraMapClusterOptions }`. `sourceId`
248
251
  down to the layer ids and the point layer's filter.**
249
252
 
250
253
  `cluster?: LyraMapClusterOptions { radius?: number; maxZoom?: number; radiusSteps?: [number,
251
- number][]; colorSteps?: [number, string][]; countFont?: string[] }` turns the entry's source into a
254
+ number][]; colorSteps?: [number, string][]; strokeColor?: string; countFont?: string[]; countColor?: string;
255
+ countHaloColor?: string; countHaloWidth?: number }` turns the entry's source into a
252
256
  natively clustered one — `cluster`/`clusterRadius` (default 50)/`clusterMaxZoom` (default 14) on
253
257
  the source, plus a `${sourceId}-cluster` circle filtered on `has('point_count')`, a
254
258
  `${sourceId}-cluster-count` label, and a `${sourceId}-circle` layer for the points that stayed
@@ -261,10 +265,20 @@ number][]; colorSteps?: [number, string][]; countFont?: string[] }` turns the en
261
265
  resolution, where a `var(--lr-…)` reference in a `colorSteps` entry is resolved against the host
262
266
  before it reaches MapLibre (which paints to a WebGL canvas and never sees the CSS cascade), so a
263
267
  retheme moves the cluster breaks with everything else. No fill or line layer is created for a
264
- clustered entry, because MapLibre's clustering keeps point features only. The count
265
- label needs glyphs: a style that declares none gets the graduated circles without the numbers
268
+ clustered entry, because MapLibre's clustering keeps point features only. The cluster's optional
269
+ `strokeColor` overrides only the aggregate circle outline; omitted, invalid,
270
+ or removed values use the entry's `strokeColor`, then `color`, then `tone`. Individual points keep
271
+ the entry's own paint. The override accepts CSS colors and live host token references and updates
272
+ without rebuilding a retained clustered source. The count label needs glyphs: a style that
273
+ declares none gets the graduated circles without the numbers
266
274
  (adding a text layer against a glyph-less style paints nothing and only emits peer errors), and
267
275
  `countFont` names the font stack when your style's glyph source lacks MapLibre's spec default.
276
+ `countColor` overrides the on-tone label foreground, which is useful when `colorSteps` mixes light
277
+ and dark circles. `countHaloColor` adds an outline for contrast; `countHaloWidth` defaults to 1
278
+ CSS pixel with a halo color and is bounded to 0–3 (one quarter of the 12px label size). An
279
+ explicit width of 0 disables the outline. Both count colors accept CSS colors or `var(--lr-…)`
280
+ references resolved against the host on theme repaint. Omitting or removing these options
281
+ restores the previous on-tone label and halo-free default.
268
282
  Cluster options are baked into the source at creation time by MapLibre and have no setter, so
269
283
  changing them (or `kind`) rebuilds that one entry's source and layers; every other update still
270
284
  reconciles in place.
@@ -127,6 +127,16 @@ If the import fails, leave the native disclosure visible and usable.
127
127
  - `anchor: Element | null = null` (property only) — positioning-only direct anchor, taking priority
128
128
  over `for` and the interaction owner but never receiving click listeners or generated ARIA; a
129
129
  `showAt()` virtual anchor still wins
130
+ - `interactionBoundary: Element | null = null` (property only) — additional light-dismiss
131
+ containment for DOM anchoring. Pointer presses within this connected element and its composed
132
+ descendants keep the popup open, so a collection's own activation handler can change `.anchor`
133
+ without a hide/show cycle. Automatic DOM anchor tracking remains active. The boundary must belong
134
+ to the popover's document; detached or foreign-document elements are ignored. It supplies no
135
+ positioning, activation, generated ARIA, or focus return. Changes apply live, and configuration
136
+ persists across close and reconnect. Containment uses the event's composed path; when the
137
+ collection lives inside a closed shadow tree, supply its exposed host. Unset, existing dismissal
138
+ behavior is unchanged. Virtual `showAt()` anchors use only their independent per-call
139
+ `options.interactionBoundary`.
130
140
  - `withoutArrow: boolean = false` (attribute `without-arrow`, reflected) — suppresses the arrow
131
141
  that otherwise points at the anchor.
132
142
  - `arrowPlacement: 'anchor'|'start'|'end'|'center' = 'anchor'` (attribute `arrow-placement`) —
@@ -297,7 +297,8 @@ cell: (row) => unknown }` — `cell` is required for every `editTrigger` except
297
297
  - `groupLabel?: (key: string | number, rows: readonly T[]) => unknown` (attribute: false) — custom group
298
298
  header content; without it, the group key is rendered as text
299
299
  - `expandedContent?: (row: T) => unknown` (attribute: false) — enables a leading expand toggle and
300
- renders a full-width detail row beneath expanded records. The returned content renders inside
300
+ renders a full-width detail row beneath expanded records. The visually empty toggle-column
301
+ header has the localized accessible name `details` (overridable through `.strings`). The returned content renders inside
301
302
  the component's shadow root, behind the `expanded-cell` part — page CSS cannot reach it, and
302
303
  `::part(expanded-cell)` only reaches the wrapping `<td>` itself, not the descendants this
303
304
  callback returns (the same `::part()` limitation a column's `cell(row)` anchors run into, see
@@ -274,7 +274,9 @@ registers nothing.
274
274
  - Optional-peer tags are skipped by default. `optionalPeers: ['dompurify', 'postal-mime']` enables
275
275
  a tag only when the allowlist contains **all** packages recorded for it; `optionalPeers: 'all'`
276
276
  is for an installation that deliberately provides the entire peer set. A failed import clears
277
- its marker and in-flight cache, so a later scan or insertion can retry it.
277
+ its marker and in-flight cache, so a later scan or insertion can invoke the loader again.
278
+ Browser caching of failed native module fetches can still prevent a new network request;
279
+ clearing the loader cache does not clear the browser's module map.
278
280
 
279
281
  ```ts
280
282
  import { start, stop } from "@aceshooting/lyra-ui/autoloader.js";
@@ -95,12 +95,17 @@ ships with Lyra. A delta's own registered-key list reports only its own authored
95
95
 
96
96
  **Optional lazy loading.** `loadLyraLocale(tag)` from `@aceshooting/lyra-ui/locale-loader.js`
97
97
  loads one complete built-in catalog without selecting the page locale. Tags that canonicalize to
98
- the same shipped catalog identity share one in-flight/completed import; failure permits retry. `en`
98
+ the same shipped catalog identity share one in-flight/completed import. Rejection clears the
99
+ helper's promise cache, but browsers may retain failed module fetches: another call need not make
100
+ a new network request. `en`
99
101
  resolves without an import. A tag with no exact shipped identity, such as an unshipped regional
100
102
  variant, rejects instead of quietly loading another language. The optional loader is outside the
101
103
  default component and localization graphs. Assign it to `lr-locale-picker.localeLoader` with an
102
104
  explicit offered locale list to use the picker's loading, failure/retry and stale-selection
103
- protection; see the forms guide.
105
+ protection; see the forms guide. Keep the current locale and failure guidance when loading fails.
106
+ If a native import remains failed after connectivity returns, a user-initiated reload can recover;
107
+ preserve unsaved work first. A custom `localeLoader` can use an application-owned recoverable
108
+ transport. The helper neither reloads the page nor changes module URLs to bypass browser caching.
104
109
 
105
110
  **Lookup order for a tag.** Every message resolves through one chain, and `Intl.PluralRules`
106
111
  category selection walks the same chain, so the two can never disagree:
@@ -829,10 +829,13 @@ The token grammar rejects CSS-wide keywords, control characters, unsafe punctuat
829
829
 
830
830
  **Saved styles and the no-flash bootstrap.** getLyraStyle() re-reads storage on each call, so a value written by another tab is visible. If storage is unavailable, the runtime reports its last applied style and continues applying changes without persistence. lyraThemeBootstrap is a self-contained IIFE string for a script in head before stylesheets; it restores the saved style before first paint. createLyraThemeBootstrap({ storageKey }) produces the same string for an application-owned key. Both runtime and bootstrap safely read v1 records using mode: "auto", surface, and tokens, translating them to the current style axes. Keep this reader when migrating old saved preferences; new writes use the current style record.
831
831
 
832
- The bootstrap string can be inlined with the application's CSP nonce or hash:
832
+ Inline the bootstrap after an early UTF-8 declaration and before stylesheets, with the application's
833
+ CSP nonce or hash. Keep the complete charset declaration within the HTML document's first 1024
834
+ bytes; build plugins must not prepend the bootstrap ahead of it.
833
835
 
834
836
  ~~~html
835
837
  <head>
838
+ <meta charset="utf-8" />
836
839
  <script>
837
840
  /* server-inlines lyraThemeBootstrap here */
838
841
  </script>
@@ -840,7 +843,7 @@ The bootstrap string can be inlined with the application's CSP nonce or hash:
840
843
  </head>
841
844
  ~~~
842
845
 
843
- For a strict CSP that disallows inline scripts, the package also publishes theme-bootstrap.js, a classic script asset with identical bytes. Load it synchronously before stylesheets. Its optional data-lr-theme-storage-key and data-lr-theme-attributes attributes select an application-owned storage key or mode-attribute list; values are validated and fall back to defaults when invalid.
846
+ For a strict CSP that disallows inline scripts, the package also publishes theme-bootstrap.js, a classic script asset with identical bytes. Load it synchronously after the charset declaration and before stylesheets. Its optional data-lr-theme-storage-key and data-lr-theme-attributes attributes select an application-owned storage key or mode-attribute list; values are validated and fall back to defaults when invalid.
844
847
 
845
848
  **Migrating the retired theme facade.** New code uses setLyraStyle() and getLyraStyle(). Map old auto mode to system, an old surface reference color to accentBackground, and an old token map to overrides; review custom CSS colors that share a gemstone name before choosing a named accent. Replace preset definitions with a LyraLook plus explicit style choices. Replace selectors for data-lr-theme-preset with the actual axis they need, such as data-lr-look="shadcn". Import looks/shadcn.css in place of the removed fixed themes/shadcn.css facade and select the look with setLyraStyle({ look: "shadcn" }) or a scoped data-lr-look attribute. Listen for lr-style-change and read event.detail.style and event.detail.changed; the old theme and preset events are no longer emitted. For the complete project-by-project sequence, see [Upgrading from v23 to v24](v23-to-v24-migration.md).
846
849
 
package/llms/shared.md CHANGED
@@ -273,7 +273,9 @@ registers nothing.
273
273
  - Optional-peer tags are skipped by default. `optionalPeers: ['dompurify', 'postal-mime']` enables
274
274
  a tag only when the allowlist contains **all** packages recorded for it; `optionalPeers: 'all'`
275
275
  is for an installation that deliberately provides the entire peer set. A failed import clears
276
- its marker and in-flight cache, so a later scan or insertion can retry it.
276
+ its marker and in-flight cache, so a later scan or insertion can invoke the loader again.
277
+ Browser caching of failed native module fetches can still prevent a new network request;
278
+ clearing the loader cache does not clear the browser's module map.
277
279
 
278
280
  ```ts
279
281
  import { start, stop } from "@aceshooting/lyra-ui/autoloader.js";
@@ -1637,10 +1639,13 @@ The token grammar rejects CSS-wide keywords, control characters, unsafe punctuat
1637
1639
 
1638
1640
  **Saved styles and the no-flash bootstrap.** getLyraStyle() re-reads storage on each call, so a value written by another tab is visible. If storage is unavailable, the runtime reports its last applied style and continues applying changes without persistence. lyraThemeBootstrap is a self-contained IIFE string for a script in head before stylesheets; it restores the saved style before first paint. createLyraThemeBootstrap({ storageKey }) produces the same string for an application-owned key. Both runtime and bootstrap safely read v1 records using mode: "auto", surface, and tokens, translating them to the current style axes. Keep this reader when migrating old saved preferences; new writes use the current style record.
1639
1641
 
1640
- The bootstrap string can be inlined with the application's CSP nonce or hash:
1642
+ Inline the bootstrap after an early UTF-8 declaration and before stylesheets, with the application's
1643
+ CSP nonce or hash. Keep the complete charset declaration within the HTML document's first 1024
1644
+ bytes; build plugins must not prepend the bootstrap ahead of it.
1641
1645
 
1642
1646
  ~~~html
1643
1647
  <head>
1648
+ <meta charset="utf-8" />
1644
1649
  <script>
1645
1650
  /* server-inlines lyraThemeBootstrap here */
1646
1651
  </script>
@@ -1648,7 +1653,7 @@ The bootstrap string can be inlined with the application's CSP nonce or hash:
1648
1653
  </head>
1649
1654
  ~~~
1650
1655
 
1651
- For a strict CSP that disallows inline scripts, the package also publishes theme-bootstrap.js, a classic script asset with identical bytes. Load it synchronously before stylesheets. Its optional data-lr-theme-storage-key and data-lr-theme-attributes attributes select an application-owned storage key or mode-attribute list; values are validated and fall back to defaults when invalid.
1656
+ For a strict CSP that disallows inline scripts, the package also publishes theme-bootstrap.js, a classic script asset with identical bytes. Load it synchronously after the charset declaration and before stylesheets. Its optional data-lr-theme-storage-key and data-lr-theme-attributes attributes select an application-owned storage key or mode-attribute list; values are validated and fall back to defaults when invalid.
1652
1657
 
1653
1658
  **Migrating the retired theme facade.** New code uses setLyraStyle() and getLyraStyle(). Map old auto mode to system, an old surface reference color to accentBackground, and an old token map to overrides; review custom CSS colors that share a gemstone name before choosing a named accent. Replace preset definitions with a LyraLook plus explicit style choices. Replace selectors for data-lr-theme-preset with the actual axis they need, such as data-lr-look="shadcn". Import looks/shadcn.css in place of the removed fixed themes/shadcn.css facade and select the look with setLyraStyle({ look: "shadcn" }) or a scoped data-lr-look attribute. Listen for lr-style-change and read event.detail.style and event.detail.changed; the old theme and preset events are no longer emitted. For the complete project-by-project sequence, see [Upgrading from v23 to v24](v23-to-v24-migration.md).
1654
1659
 
@@ -2146,12 +2151,17 @@ ships with Lyra. A delta's own registered-key list reports only its own authored
2146
2151
 
2147
2152
  **Optional lazy loading.** `loadLyraLocale(tag)` from `@aceshooting/lyra-ui/locale-loader.js`
2148
2153
  loads one complete built-in catalog without selecting the page locale. Tags that canonicalize to
2149
- the same shipped catalog identity share one in-flight/completed import; failure permits retry. `en`
2154
+ the same shipped catalog identity share one in-flight/completed import. Rejection clears the
2155
+ helper's promise cache, but browsers may retain failed module fetches: another call need not make
2156
+ a new network request. `en`
2150
2157
  resolves without an import. A tag with no exact shipped identity, such as an unshipped regional
2151
2158
  variant, rejects instead of quietly loading another language. The optional loader is outside the
2152
2159
  default component and localization graphs. Assign it to `lr-locale-picker.localeLoader` with an
2153
2160
  explicit offered locale list to use the picker's loading, failure/retry and stale-selection
2154
- protection; see the forms guide.
2161
+ protection; see the forms guide. Keep the current locale and failure guidance when loading fails.
2162
+ If a native import remains failed after connectivity returns, a user-initiated reload can recover;
2163
+ preserve unsaved work first. A custom `localeLoader` can use an application-owned recoverable
2164
+ transport. The helper neither reloads the page nor changes module URLs to bypass browser caching.
2155
2165
 
2156
2166
  **Lookup order for a tag.** Every message resolves through one chain, and `Intl.PluralRules`
2157
2167
  category selection walks the same chain, so the two can never disagree:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aceshooting/lyra-ui",
3
- "version": "25.1.0",
3
+ "version": "25.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",