@aceshooting/lyra-ui 10.0.1 → 11.0.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 (59) hide show
  1. package/CHANGELOG.md +188 -0
  2. package/custom-elements.json +1 -1
  3. package/design-tokens.json +13 -0
  4. package/dist/cli/migrate-wa.mjs +164 -1
  5. package/dist/cli/migration-contract.json +1 -1
  6. package/dist/components/charts/chart/box-plot.class.d.ts +27 -0
  7. package/dist/components/charts/chart/box-plot.class.js +14 -4
  8. package/dist/components/charts/chart/box-plot.styles.js +28 -0
  9. package/dist/components/charts/chart/chart.class.d.ts +27 -0
  10. package/dist/components/charts/chart/chart.class.js +15 -5
  11. package/dist/components/charts/chart/chart.styles.js +28 -0
  12. package/dist/components/data/heatmap/heatmap.class.d.ts +35 -2
  13. package/dist/components/data/heatmap/heatmap.class.js +2 -2
  14. package/dist/components/forms/combobox/combobox.class.d.ts +71 -3
  15. package/dist/components/forms/combobox/combobox.class.js +4 -2
  16. package/dist/components/forms/combobox/combobox.styles.js +9 -0
  17. package/dist/components/forms/date-picker/date-picker.class.d.ts +46 -0
  18. package/dist/components/forms/date-picker/date-picker.class.js +15 -3
  19. package/dist/components/forms/date-picker/date-picker.styles.js +46 -0
  20. package/dist/components/media/flag/flag.class.d.ts +3 -1
  21. package/dist/components/media/flag/flag.class.js +1 -1
  22. package/dist/components/media/map/map.class.d.ts +39 -2
  23. package/dist/components/media/map/map.class.js +1 -1
  24. package/dist/components/overlays/dialog/dialog.class.d.ts +20 -0
  25. package/dist/components/overlays/overlay/popover.class.d.ts +19 -3
  26. package/dist/components/overlays/overlay/popover.class.js +1 -1
  27. package/dist/custom-elements-jsx.d.ts +27 -14
  28. package/dist/internal/package-metadata.d.ts +1 -1
  29. package/dist/internal/package-metadata.js +1 -1
  30. package/dist/internal/tokens.styles.js +1 -0
  31. package/dist/lyra.d.ts +1 -1
  32. package/dist/svelte.d.ts +27 -14
  33. package/dist/vue.d.ts +27 -14
  34. package/llms/components/lr-bar-chart.md +4 -3
  35. package/llms/components/lr-box-plot.md +14 -3
  36. package/llms/components/lr-bubble-chart.md +4 -3
  37. package/llms/components/lr-chart.md +13 -3
  38. package/llms/components/lr-combobox.md +42 -6
  39. package/llms/components/lr-date-input.md +22 -2
  40. package/llms/components/lr-date-picker.md +23 -3
  41. package/llms/components/lr-dialog.md +2 -1
  42. package/llms/components/lr-doughnut-chart.md +4 -3
  43. package/llms/components/lr-flag.md +10 -3
  44. package/llms/components/lr-heatmap.md +20 -2
  45. package/llms/components/lr-histogram.md +4 -3
  46. package/llms/components/lr-line-chart.md +4 -3
  47. package/llms/components/lr-map.md +21 -4
  48. package/llms/components/lr-option.md +41 -5
  49. package/llms/components/lr-pie-chart.md +4 -3
  50. package/llms/components/lr-polar-area-chart.md +4 -3
  51. package/llms/components/lr-popover.md +20 -1
  52. package/llms/components/lr-radar-chart.md +4 -3
  53. package/llms/components/lr-scatter-chart.md +4 -3
  54. package/llms/tokens.md +15 -1
  55. package/llms-full.txt +197 -26
  56. package/package.json +1 -1
  57. package/vscode-css-data.json +56 -0
  58. package/vscode-html-data.json +115 -18
  59. package/web-types.json +162 -21
@@ -1625,6 +1625,19 @@
1625
1625
  },
1626
1626
  "focus": {
1627
1627
  "ring": {
1628
+ "$root": {
1629
+ "$type": "string",
1630
+ "$value": "var(--lr-focus-ring-width) solid var(--lr-focus-ring-color)",
1631
+ "$description": "Composite focus-ring outline shorthand, derived from the width and color parts. Mirrors the ready-made outline value Web Awesome exposes as --wa-focus-ring so a migrating consumer has a one-to-one target instead of hand-expanding every site. Offset stays separate because outline-offset is its own property.",
1632
+ "$extensions": {
1633
+ "com.aceshooting.lyra": {
1634
+ "cssCustomProperty": "--lr-focus-ring",
1635
+ "cssType": "string",
1636
+ "scope": "shared",
1637
+ "group": "focus"
1638
+ }
1639
+ }
1640
+ },
1628
1641
  "color": {
1629
1642
  "$type": "string",
1630
1643
  "$value": "var(--lr-theme-color-focus, var(--lr-color-brand))",
@@ -2744,6 +2744,110 @@ function migrateLocalText(original, contract, options) {
2744
2744
  };
2745
2745
  }
2746
2746
 
2747
+ /**
2748
+ * Finds `wa-*`/`sl-*` references in the four places `migrateText()` deliberately does not rewrite,
2749
+ * so they can at least be reported. See the call site for why each one is dangerous when silent.
2750
+ *
2751
+ * Scoped narrowly on purpose: every pattern here targets a context the tag rewriter provably skips
2752
+ * (CSS-in-JS template bodies, `::slotted()`, a selector string reached through a receiver, and
2753
+ * custom-property names), so a reference is never both rewritten and warned about.
2754
+ */
2755
+ export function scanUnrewrittenUpstreamReferences(text) {
2756
+ const found = [];
2757
+ const seen = new Set();
2758
+ const push = (offset, upstreamTag, member, code, target, message) => {
2759
+ const key = `${offset}:${code}`;
2760
+ if (seen.has(key)) return;
2761
+ seen.add(key);
2762
+ found.push({ offset, upstreamTag, member, code, target, message });
2763
+ };
2764
+ const TAG = /(?<![\w-])(?<tag>(?:wa|sl)-[a-z][a-z0-9-]*)(?![\w-])/g;
2765
+
2766
+ // 1. Tag selectors inside a `css` tagged template. Lit is this library's own idiom, so
2767
+ // `static styles = css\`\`` is exactly where a migrating consumer's tag selectors live --
2768
+ // "standalone CSS is in scope but CSS-in-JS is not" inverts the likelihood.
2769
+ for (const block of text.matchAll(/\bcss`/g)) {
2770
+ const bodyStart = block.index + block[0].length;
2771
+ const bodyEnd = text.indexOf('`', bodyStart);
2772
+ if (bodyEnd === -1) continue;
2773
+ const body = text.slice(bodyStart, bodyEnd);
2774
+ for (const match of body.matchAll(TAG)) {
2775
+ const tag = match.groups.tag;
2776
+ push(
2777
+ bodyStart + match.index,
2778
+ tag,
2779
+ 'css-template',
2780
+ 'CSS_IN_JS_SELECTOR_REVIEW',
2781
+ tag,
2782
+ `\`${tag}\` appears in a css\`\` template and was NOT rewritten. A rule keyed on a tag that no longer exists matches nothing, silently. Rename the selector by hand.`,
2783
+ );
2784
+ }
2785
+ }
2786
+
2787
+ // 2. ::slotted(wa-*) anywhere, including standalone CSS.
2788
+ for (const match of text.matchAll(/::slotted\(\s*([^)]*)\)/g)) {
2789
+ for (const inner of match[1].matchAll(TAG)) {
2790
+ const tag = inner.groups.tag;
2791
+ push(
2792
+ match.index + match[0].indexOf(inner.groups.tag),
2793
+ tag,
2794
+ '::slotted',
2795
+ 'SLOTTED_SELECTOR_REVIEW',
2796
+ tag,
2797
+ `\`::slotted(${tag})\` was NOT rewritten and will match nothing after the migration. Rename it by hand.`,
2798
+ );
2799
+ }
2800
+ }
2801
+
2802
+ // 3. Selector strings reached through a `this`-rooted receiver. The rewriter anchors on a bare or
2803
+ // `document.`-prefixed call, so `this.querySelectorAll('wa-option')` and
2804
+ // `this.shadowRoot?.querySelector('wa-card')` -- the two commonest forms inside a component --
2805
+ // slipped through and would start returning null.
2806
+ //
2807
+ // Deliberately restricted to `this`, `this.shadowRoot` and `this.renderRoot` rather than any
2808
+ // receiver. The rewriter refuses a SHADOWED `document`/`querySelector` binding on purpose (a
2809
+ // local named `document` is provably not a DOM query), and warning there would be a false
2810
+ // positive on correct code. `this` is the one receiver that can never be a local binding, so
2811
+ // a query through it is always a real DOM query.
2812
+ const CALL = /\bthis(?:\s*\??\.\s*(?:shadowRoot|renderRoot))?\s*\??\.\s*(?:querySelector|querySelectorAll|closest|matches)\s*(?:<[^>\n]+>)?\(\s*(['"`])(?<selector>[^'"`]*)\1/g;
2813
+ for (const match of text.matchAll(CALL)) {
2814
+ const selectorOffset = match.index + match[0].lastIndexOf(match.groups.selector);
2815
+ for (const inner of match.groups.selector.matchAll(TAG)) {
2816
+ const tag = inner.groups.tag;
2817
+ push(
2818
+ selectorOffset + inner.index,
2819
+ tag,
2820
+ 'selector-string',
2821
+ 'SELECTOR_STRING_REVIEW',
2822
+ tag,
2823
+ `\`${tag}\` appears in a DOM selector string that was NOT rewritten. The query will return null after the migration rather than throwing. Rename it by hand.`,
2824
+ );
2825
+ }
2826
+ }
2827
+
2828
+ // 4. Upstream custom properties. Never auto-rewritten -- see the call site.
2829
+ // A name the file also DECLARES is the consumer's own property that merely happens to share
2830
+ // the prefix, not an upstream token they are consuming; warning on it would be a false
2831
+ // positive. Same "reads but never declares" discriminator check-manifest-coverage.mjs uses.
2832
+ const declaredHere = new Set(
2833
+ [...text.matchAll(/(--(?:wa|sl)-[a-z0-9-]+)\s*:/g)].map((match) => match[1]),
2834
+ );
2835
+ for (const match of text.matchAll(/--(?<ecosystem>wa|sl)-[a-z0-9-]+/g)) {
2836
+ const token = match[0];
2837
+ if (declaredHere.has(token)) continue;
2838
+ push(
2839
+ match.index,
2840
+ `${match.groups.ecosystem}-tokens`,
2841
+ 'custom-property',
2842
+ 'UPSTREAM_TOKEN_REVIEW',
2843
+ token,
2844
+ `\`${token}\` is an upstream design token with no automatic Lyra equivalent, and was left as-is. A var() naming a token that no longer exists falls back to its second argument, or to nothing -- silently. Map it by hand against llms/tokens.md; note the spacing scales are offset by one step, so renaming by name alone tightens every gap.`,
2845
+ );
2846
+ }
2847
+
2848
+ return found;
2849
+ }
2850
+
2747
2851
  export function migrateText(original, contract, options = {}) {
2748
2852
  if (options.origin) return migrateLocalText(original, contract, options);
2749
2853
  const file = options.file ?? '<memory>';
@@ -3394,6 +3498,39 @@ export function migrateText(original, contract, options = {}) {
3394
3498
  });
3395
3499
  }
3396
3500
 
3501
+ // ---------------------------------------------------------------------------------------------
3502
+ // Reference classes this codemod does NOT rewrite. Each one fails SILENTLY at runtime after a
3503
+ // migration: a CSS rule keyed on a tag that no longer exists simply matches nothing, ::slotted()
3504
+ // likewise, querySelector returns null, and a var() naming a removed token falls back to whatever
3505
+ // literal is in its second argument -- or to nothing. None of it throws, none of it fails a build,
3506
+ // and a typechecker cannot see inside a template literal. Leaving them unwarned meant `--check`
3507
+ // reported a clean migration over visibly broken styling, which is the actual defect: the tool is
3508
+ // documented as a CI gate, so silence there is certification.
3509
+ //
3510
+ // These are warnings, never rewrites. For tokens that is a deliberate refusal rather than
3511
+ // laziness: the two spacing scales are offset by one step (Web Awesome `m` is 1rem, Lyra `m` is
3512
+ // 0.75rem), so a blind --wa-X -> --lr-X rename silently tightens every gap, while mapping by
3513
+ // value has no target for 1.5rem or 2.5rem. Naming each occurrence is worth more than a guess.
3514
+ //
3515
+ // Filtered against the rewrite ranges this pass actually produced, so a reference the inventory
3516
+ // DOES map (a `--wa-old-color` with a declared `--lr-*` target, say) is never both rewritten and
3517
+ // warned about. Deriving that from the edits rather than from a second copy of the inventory
3518
+ // keeps it correct for free as the inventory grows.
3519
+ const rewrittenRanges = edits.map((edit) => [edit.start, edit.end]);
3520
+ const wasRewritten = (offset) =>
3521
+ rewrittenRanges.some(([start, end]) => offset >= start && offset < end);
3522
+ for (const scan of scanUnrewrittenUpstreamReferences(original)) {
3523
+ if (wasRewritten(scan.offset)) continue;
3524
+ warn(
3525
+ scan.offset,
3526
+ scan.upstreamTag,
3527
+ scan.member,
3528
+ scan.code,
3529
+ scan.target,
3530
+ scan.message,
3531
+ );
3532
+ }
3533
+
3397
3534
  const content = finalizeEdits(original, edits);
3398
3535
  changes.sort((left, right) => left.line - right.line || left.column - right.column || left.action.localeCompare(right.action));
3399
3536
  warnings.sort((left, right) => left.line - right.line || left.column - right.column || left.warningCode.localeCompare(right.warningCode));
@@ -3753,6 +3890,32 @@ export function run(argv) {
3753
3890
  }
3754
3891
  }
3755
3892
 
3756
- if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
3893
+ /**
3894
+ * Whether this module was invoked as the CLI rather than imported as a library.
3895
+ *
3896
+ * Compares REALPATHS. Under pnpm, `node_modules/.bin/lyra-ui-migrate` resolves into a package
3897
+ * directory that is a symlink into the virtual store, so the path the shim passes as `argv[1]`
3898
+ * (`<cwd>/node_modules/@aceshooting/lyra-ui/dist/cli/migrate-wa.mjs`) and this module's own
3899
+ * `import.meta.url` (`<cwd>/node_modules/.pnpm/@aceshooting+lyra-ui@<version>_<peer-suffix>/...`)
3900
+ * never match literally. The former raw comparison therefore evaluated false on every pnpm install:
3901
+ * `run()` never executed, so the CLI printed nothing, rewrote nothing, wrote no report -- and exited
3902
+ * 0. That made the documented `--check` CI gate pass unconditionally, which is worse than having no
3903
+ * gate, because it is trusted. npm and yarn were unaffected, which is how it survived.
3904
+ *
3905
+ * Falls back to the literal comparison only if a realpath cannot be taken (a deleted or
3906
+ * permission-denied entry), which keeps the import-as-a-library case correct either way.
3907
+ */
3908
+ function invokedAsCli() {
3909
+ const invoked = process.argv[1];
3910
+ if (!invoked) return false;
3911
+ const here = fileURLToPath(import.meta.url);
3912
+ try {
3913
+ return fs.realpathSync(invoked) === fs.realpathSync(here);
3914
+ } catch {
3915
+ return path.resolve(invoked) === here;
3916
+ }
3917
+ }
3918
+
3919
+ if (invokedAsCli()) {
3757
3920
  process.exitCode = run(process.argv.slice(2));
3758
3921
  }