@aceshooting/lyra-ui 25.2.0 → 25.3.1

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.2.0';
5
+ export declare const LYRA_PACKAGE_NAME:'@aceshooting/lyra-ui';export declare const LYRA_PACKAGE_VERSION:'25.3.1';
@@ -1 +1 @@
1
- const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="25.2.0";export{LYRA_PACKAGE_NAME,LYRA_PACKAGE_VERSION};
1
+ const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="25.3.1";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 `--lr-size-3rem` (normally `3rem`, or 48px at a 16px root size),
226
+ including `option-display="label"`, compact density, and a small flag trigger. Block padding is
227
+ `--lr-space-s`; long native labels wrap and rows grow with the text. Larger medium/current control
228
+ height tokens and the optional tag line can also grow rows beyond that floor. The listbox keeps
229
+ its scrolling height limit; `size` controls the trigger rather than shrinking language choices.
230
+
221
231
  ```html
222
232
  <lr-locale-picker label="Language"></lr-locale-picker>
223
233
  <script type="module">
@@ -265,6 +265,10 @@ has `aria-haspopup="menu"`, explicit `aria-expanded="true|false"`, the transient
265
265
  `submenu-open` state, and a logical-direction chevron. Its submenu is named from the parent's
266
266
  accessible label unless the submenu supplies its own `aria-label` or non-default `label`.
267
267
 
268
+ Submenus prefer the inline end of their parent and flip to the other side when necessary. When
269
+ neither side has enough space, they can open above or below the parent, keeping their labels
270
+ readable within the viewport instead of shrinking to the remaining strip beside a wide menu.
271
+
268
272
  The into-branch and back-out arrow keys swap under RTL. Enter/Space and the into key open and focus
269
273
  the first child; the back-out key and Escape close only the innermost branch and return focus to its
270
274
  parent row. Pointer hover uses an intent delay, outside pointer dismissal closes the branch, and at
@@ -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:
@@ -505,7 +505,8 @@ page you are on — that is what keeps two overlapping surfaces reading in the c
505
505
 
506
506
  ### Cascade layers
507
507
 
508
- `theme.css` declares its layer order up front, then puts all of its own tokens in `lr-theme`:
508
+ `theme.css` declares its layer order up front, with base inputs in `lr-theme` and built-in profile
509
+ rules in the `lr-theme-preset` sublayers:
509
510
 
510
511
  ```css
511
512
  @layer lr-base, lr-theme, lr-theme-preset, lr-utilities, lr-overrides;
@@ -513,9 +514,10 @@ page you are on — that is what keeps two overlapping surfaces reading in the c
513
514
 
514
515
  - **`lr-base`** — contains the explicitly scoped native-element rules only when the optional
515
516
  `native.css` asset is imported.
516
- - **`lr-theme`** — where every `--lr-theme-*` token `theme.css` ships is declared.
517
- - **`lr-theme-preset`** — the compatibility layer name that holds optional look stylesheets, such as
518
- [`looks/shadcn.css`](#the-shadcn-look--looksshadcncss). Empty unless one is imported.
517
+ - **`lr-theme`** — contains the base theme inputs and token resolvers.
518
+ - **`lr-theme-preset`** — the compatibility layer name for look, density, surface, accent and mode
519
+ rules. `theme.css` already supplies the built-in Shadcn, Glass and Emerald profile here; optional
520
+ look stylesheets add their own rules to the same sublayers.
519
521
  - **`lr-utilities`** — contains exact `lr-*` classes only when the optional `utilities.css` asset is
520
522
  imported.
521
523
  - **`lr-overrides`** — named so an application can opt its own rules into a defined position
@@ -574,17 +576,25 @@ reason.
574
576
 
575
577
  ### The shadcn look — looks/shadcn.css
576
578
 
577
- Import the base resolver and the optional look stylesheet, then select the look on the scope that should receive it:
579
+ `theme.css` already installs Shadcn as the built-in default and supports explicit
580
+ `data-lr-look="shadcn"` scopes. Import it once; the separate Shadcn sheet is unnecessary for this
581
+ profile:
578
582
 
579
583
  ~~~ts
580
584
  import "@aceshooting/lyra-ui/theme.css";
581
- import "@aceshooting/lyra-ui/looks/shadcn.css";
582
585
  import { setLyraStyle } from "@aceshooting/lyra-ui/theme.js";
583
586
 
584
587
  setLyraStyle({ look: "shadcn" });
585
588
  ~~~
586
589
 
587
- The stylesheet declares values only under data-lr-look="shadcn". It composes with the independent mode, surface, density, and accent axes. For a local region, set data-lr-look="shadcn" on that region or use applyLyraStyleScope(). A nested data-lr-mode="dark" still changes mode without changing the look.
590
+ Shadcn composes with the independent mode, surface, density and accent axes. For a local region,
591
+ set data-lr-look="shadcn" on that region or use applyLyraStyleScope(). A nested data-lr-mode="dark"
592
+ still changes mode without changing the look.
593
+
594
+ The separate `looks/shadcn.css` sheet remains compatible. Besides the same scoped look values, it
595
+ adds legacy `.light` and `.dark` mode aliases inside a Shadcn scope. Import that sheet only when
596
+ those aliases are needed; prefer `data-lr-mode`, `data-lr-theme` or `.lr-light`/`.lr-dark` for new
597
+ code. Explicit Lyra mode selectors on the same element take precedence over the compatibility aliases.
588
598
 
589
599
  The look sets --lr-theme-* inputs, so no component API changes. Its rules use Lyra's named cascade layers: unlayered application rules still win, and runtime accent ramps still take precedence over look values for the roles they paint. Import order between theme.css and looks/shadcn.css does not change the layer order.
590
600
 
@@ -602,7 +612,9 @@ Override the look through an unlayered application rule or the lr-overrides laye
602
612
  }
603
613
  ~~~
604
614
 
605
- The former global themes/shadcn.css facade and its data-lr-theme-preset behavior have been removed. Use looks/shadcn.css and the data-lr-look axis for new styling.
615
+ The former global themes/shadcn.css facade and its data-lr-theme-preset behavior have been removed.
616
+ Use theme.css and the data-lr-look axis for new styling; looks/shadcn.css is needed only for the
617
+ compatibility aliases above.
606
618
 
607
619
  ### Where an override actually reaches
608
620
 
@@ -829,10 +841,13 @@ The token grammar rejects CSS-wide keywords, control characters, unsafe punctuat
829
841
 
830
842
  **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
843
 
832
- The bootstrap string can be inlined with the application's CSP nonce or hash:
844
+ Inline the bootstrap after an early UTF-8 declaration and before stylesheets, with the application's
845
+ CSP nonce or hash. Keep the complete charset declaration within the HTML document's first 1024
846
+ bytes; build plugins must not prepend the bootstrap ahead of it.
833
847
 
834
848
  ~~~html
835
849
  <head>
850
+ <meta charset="utf-8" />
836
851
  <script>
837
852
  /* server-inlines lyraThemeBootstrap here */
838
853
  </script>
@@ -840,9 +855,9 @@ The bootstrap string can be inlined with the application's CSP nonce or hash:
840
855
  </head>
841
856
  ~~~
842
857
 
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.
858
+ 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
859
 
845
- **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).
860
+ **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 theme.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
861
 
847
862
  Historical v1 stored records remain readable by the runtime and bootstrap. The removed JavaScript functions, preset subpaths, preset event, root marker, and fixed stylesheet are not available in the current API.
848
863
 
@@ -894,10 +909,8 @@ mode and accent; the axes compose independently.
894
909
 
895
910
  ```js
896
911
  import '@aceshooting/lyra-ui/theme.css';
897
- import '@aceshooting/lyra-ui/looks/shadcn.css';
898
912
  import '@aceshooting/lyra-ui/looks/material.css';
899
913
  import '@aceshooting/lyra-ui/density.css';
900
- import '@aceshooting/lyra-ui/surfaces/glass.css';
901
914
  import '@aceshooting/lyra-ui/accents.css';
902
915
  import { setLyraStyle, resetLyraStyle, applyLyraStyleScope } from '@aceshooting/lyra-ui/theme.js';
903
916
 
@@ -915,7 +928,8 @@ inherit), without persistence or global events; clearing preserves later author
915
928
  reports requested axes and resolved mode.
916
929
 
917
930
  Set `data-lr-look`, `data-lr-surface`, `data-lr-density`, `data-lr-mode` and `data-lr-accent`
918
- directly if needed. Stylesheet look ids need their sheet; arbitrary ids neither load nor register.
931
+ directly if needed. Shadcn and Lyra are included in `theme.css`; other stylesheet look ids need
932
+ their optional sheet. Arbitrary ids neither load nor register.
919
933
  `defineLyraLook({ id, tokens })` defines a validated immutable runtime look;
920
934
  `lyraLookCss()` from `theme/look-css.js` creates CSS without DOM access. In app-owned shadow roots
921
935
  with local boundaries, install `theme.css` and selected sheets; selectors stop at roots, inheritance
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";
@@ -1313,7 +1315,8 @@ page you are on — that is what keeps two overlapping surfaces reading in the c
1313
1315
 
1314
1316
  ### Cascade layers
1315
1317
 
1316
- `theme.css` declares its layer order up front, then puts all of its own tokens in `lr-theme`:
1318
+ `theme.css` declares its layer order up front, with base inputs in `lr-theme` and built-in profile
1319
+ rules in the `lr-theme-preset` sublayers:
1317
1320
 
1318
1321
  ```css
1319
1322
  @layer lr-base, lr-theme, lr-theme-preset, lr-utilities, lr-overrides;
@@ -1321,9 +1324,10 @@ page you are on — that is what keeps two overlapping surfaces reading in the c
1321
1324
 
1322
1325
  - **`lr-base`** — contains the explicitly scoped native-element rules only when the optional
1323
1326
  `native.css` asset is imported.
1324
- - **`lr-theme`** — where every `--lr-theme-*` token `theme.css` ships is declared.
1325
- - **`lr-theme-preset`** — the compatibility layer name that holds optional look stylesheets, such as
1326
- [`looks/shadcn.css`](#the-shadcn-look--looksshadcncss). Empty unless one is imported.
1327
+ - **`lr-theme`** — contains the base theme inputs and token resolvers.
1328
+ - **`lr-theme-preset`** — the compatibility layer name for look, density, surface, accent and mode
1329
+ rules. `theme.css` already supplies the built-in Shadcn, Glass and Emerald profile here; optional
1330
+ look stylesheets add their own rules to the same sublayers.
1327
1331
  - **`lr-utilities`** — contains exact `lr-*` classes only when the optional `utilities.css` asset is
1328
1332
  imported.
1329
1333
  - **`lr-overrides`** — named so an application can opt its own rules into a defined position
@@ -1382,17 +1386,25 @@ reason.
1382
1386
 
1383
1387
  ### The shadcn look — looks/shadcn.css
1384
1388
 
1385
- Import the base resolver and the optional look stylesheet, then select the look on the scope that should receive it:
1389
+ `theme.css` already installs Shadcn as the built-in default and supports explicit
1390
+ `data-lr-look="shadcn"` scopes. Import it once; the separate Shadcn sheet is unnecessary for this
1391
+ profile:
1386
1392
 
1387
1393
  ~~~ts
1388
1394
  import "@aceshooting/lyra-ui/theme.css";
1389
- import "@aceshooting/lyra-ui/looks/shadcn.css";
1390
1395
  import { setLyraStyle } from "@aceshooting/lyra-ui/theme.js";
1391
1396
 
1392
1397
  setLyraStyle({ look: "shadcn" });
1393
1398
  ~~~
1394
1399
 
1395
- The stylesheet declares values only under data-lr-look="shadcn". It composes with the independent mode, surface, density, and accent axes. For a local region, set data-lr-look="shadcn" on that region or use applyLyraStyleScope(). A nested data-lr-mode="dark" still changes mode without changing the look.
1400
+ Shadcn composes with the independent mode, surface, density and accent axes. For a local region,
1401
+ set data-lr-look="shadcn" on that region or use applyLyraStyleScope(). A nested data-lr-mode="dark"
1402
+ still changes mode without changing the look.
1403
+
1404
+ The separate `looks/shadcn.css` sheet remains compatible. Besides the same scoped look values, it
1405
+ adds legacy `.light` and `.dark` mode aliases inside a Shadcn scope. Import that sheet only when
1406
+ those aliases are needed; prefer `data-lr-mode`, `data-lr-theme` or `.lr-light`/`.lr-dark` for new
1407
+ code. Explicit Lyra mode selectors on the same element take precedence over the compatibility aliases.
1396
1408
 
1397
1409
  The look sets --lr-theme-* inputs, so no component API changes. Its rules use Lyra's named cascade layers: unlayered application rules still win, and runtime accent ramps still take precedence over look values for the roles they paint. Import order between theme.css and looks/shadcn.css does not change the layer order.
1398
1410
 
@@ -1410,7 +1422,9 @@ Override the look through an unlayered application rule or the lr-overrides laye
1410
1422
  }
1411
1423
  ~~~
1412
1424
 
1413
- The former global themes/shadcn.css facade and its data-lr-theme-preset behavior have been removed. Use looks/shadcn.css and the data-lr-look axis for new styling.
1425
+ The former global themes/shadcn.css facade and its data-lr-theme-preset behavior have been removed.
1426
+ Use theme.css and the data-lr-look axis for new styling; looks/shadcn.css is needed only for the
1427
+ compatibility aliases above.
1414
1428
 
1415
1429
  ### Where an override actually reaches
1416
1430
 
@@ -1637,10 +1651,13 @@ The token grammar rejects CSS-wide keywords, control characters, unsafe punctuat
1637
1651
 
1638
1652
  **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
1653
 
1640
- The bootstrap string can be inlined with the application's CSP nonce or hash:
1654
+ Inline the bootstrap after an early UTF-8 declaration and before stylesheets, with the application's
1655
+ CSP nonce or hash. Keep the complete charset declaration within the HTML document's first 1024
1656
+ bytes; build plugins must not prepend the bootstrap ahead of it.
1641
1657
 
1642
1658
  ~~~html
1643
1659
  <head>
1660
+ <meta charset="utf-8" />
1644
1661
  <script>
1645
1662
  /* server-inlines lyraThemeBootstrap here */
1646
1663
  </script>
@@ -1648,9 +1665,9 @@ The bootstrap string can be inlined with the application's CSP nonce or hash:
1648
1665
  </head>
1649
1666
  ~~~
1650
1667
 
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.
1668
+ 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
1669
 
1653
- **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).
1670
+ **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 theme.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
1671
 
1655
1672
  Historical v1 stored records remain readable by the runtime and bootstrap. The removed JavaScript functions, preset subpaths, preset event, root marker, and fixed stylesheet are not available in the current API.
1656
1673
 
@@ -2146,12 +2163,17 @@ ships with Lyra. A delta's own registered-key list reports only its own authored
2146
2163
 
2147
2164
  **Optional lazy loading.** `loadLyraLocale(tag)` from `@aceshooting/lyra-ui/locale-loader.js`
2148
2165
  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`
2166
+ the same shipped catalog identity share one in-flight/completed import. Rejection clears the
2167
+ helper's promise cache, but browsers may retain failed module fetches: another call need not make
2168
+ a new network request. `en`
2150
2169
  resolves without an import. A tag with no exact shipped identity, such as an unshipped regional
2151
2170
  variant, rejects instead of quietly loading another language. The optional loader is outside the
2152
2171
  default component and localization graphs. Assign it to `lr-locale-picker.localeLoader` with an
2153
2172
  explicit offered locale list to use the picker's loading, failure/retry and stale-selection
2154
- protection; see the forms guide.
2173
+ protection; see the forms guide. Keep the current locale and failure guidance when loading fails.
2174
+ If a native import remains failed after connectivity returns, a user-initiated reload can recover;
2175
+ preserve unsaved work first. A custom `localeLoader` can use an application-owned recoverable
2176
+ transport. The helper neither reloads the page nor changes module URLs to bypass browser caching.
2155
2177
 
2156
2178
  **Lookup order for a tag.** Every message resolves through one chain, and `Intl.PluralRules`
2157
2179
  category selection walks the same chain, so the two can never disagree:
@@ -5537,10 +5559,8 @@ mode and accent; the axes compose independently.
5537
5559
 
5538
5560
  ```js
5539
5561
  import '@aceshooting/lyra-ui/theme.css';
5540
- import '@aceshooting/lyra-ui/looks/shadcn.css';
5541
5562
  import '@aceshooting/lyra-ui/looks/material.css';
5542
5563
  import '@aceshooting/lyra-ui/density.css';
5543
- import '@aceshooting/lyra-ui/surfaces/glass.css';
5544
5564
  import '@aceshooting/lyra-ui/accents.css';
5545
5565
  import { setLyraStyle, resetLyraStyle, applyLyraStyleScope } from '@aceshooting/lyra-ui/theme.js';
5546
5566
 
@@ -5558,7 +5578,8 @@ inherit), without persistence or global events; clearing preserves later author
5558
5578
  reports requested axes and resolved mode.
5559
5579
 
5560
5580
  Set `data-lr-look`, `data-lr-surface`, `data-lr-density`, `data-lr-mode` and `data-lr-accent`
5561
- directly if needed. Stylesheet look ids need their sheet; arbitrary ids neither load nor register.
5581
+ directly if needed. Shadcn and Lyra are included in `theme.css`; other stylesheet look ids need
5582
+ their optional sheet. Arbitrary ids neither load nor register.
5562
5583
  `defineLyraLook({ id, tokens })` defines a validated immutable runtime look;
5563
5584
  `lyraLookCss()` from `theme/look-css.js` creates CSS without DOM access. In app-owned shadow roots
5564
5585
  with local boundaries, install `theme.css` and selected sheets; selectors stop at roots, inheritance
package/llms/tokens.md CHANGED
@@ -12,10 +12,13 @@ Every `lr-*` component resolves its styling through this two-layer token system,
12
12
  with a built-in fallback. Other tokens are aliases, computed or environment-backed values,
13
13
  or fixed contract constants. Every component renders correctly with no theme configured.
14
14
 
15
- For a ready-made light/dark base, import `@aceshooting/lyra-ui/theme.css` once and put
16
- `class="lr-light"`/`class="lr-dark"` (or `data-lr-theme="light"`/`"dark"`) on an ancestor.
17
- For the shadcn/ui look, also import `@aceshooting/lyra-ui/looks/shadcn.css` and select
18
- `data-lr-look="shadcn"` on the root or a scoped ancestor; look and mode remain independent.
15
+ Import `@aceshooting/lyra-ui/theme.css` once for the built-in Shadcn, Glass and Emerald profile.
16
+ `theme.css` already includes Shadcn; no separate Shadcn look import is required.
17
+ Select `data-lr-look="shadcn"` on a scoped ancestor when needed. Choose light/dark mode with
18
+ `class="lr-light"`/`class="lr-dark"`, `data-lr-theme`, or the independent `data-lr-mode` axis.
19
+ Other stylesheet looks, such as Material, require their optional `looks/<look>.css` sheet.
20
+ The separate `looks/shadcn.css` sheet remains optional for its scoped `.light`/`.dark`
21
+ compatibility aliases; look and mode remain independent.
19
22
  See [Styles and tokens](./shared/styles-and-tokens.md) for runtime and stylesheet options.
20
23
  Per-component `--lr-<component>-*` custom properties (listed in each component's own section)
21
24
  override a single element without touching the shared layer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aceshooting/lyra-ui",
3
- "version": "25.2.0",
3
+ "version": "25.3.1",
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",
@@ -11832,7 +11832,7 @@
11832
11832
  "istanbul-lib-report": "^3.0.1",
11833
11833
  "istanbul-reports": "^3.2.0",
11834
11834
  "jszip": "^3.10.2",
11835
- "katex": "^0.18.9",
11835
+ "katex": "^0.18.10",
11836
11836
  "libphonenumber-js": "^1.13.14",
11837
11837
  "mammoth": "^1.13.0",
11838
11838
  "maplibre-gl": "^6.11.2",
@@ -11843,10 +11843,10 @@
11843
11843
  "pixelmatch": "^7.2.0",
11844
11844
  "playwright": "^1.63.0",
11845
11845
  "pngjs": "^7.0.0",
11846
- "postal-mime": "^4.0.1",
11846
+ "postal-mime": "^4.0.2",
11847
11847
  "qrcode": "^1.5.4",
11848
11848
  "react": "^19.3.0",
11849
- "shiki": "^4.4.3",
11849
+ "shiki": "^4.5.0",
11850
11850
  "svelte": "^5.57.1",
11851
11851
  "typescript": "^7.0.2",
11852
11852
  "vue": "^3.5.43",