@waggylabs/yumekit 0.5.0 → 0.5.1-beta.3

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 (99) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/CONTRIBUTING.md +1 -1
  3. package/dist/components/y-appbar.js +27 -15
  4. package/dist/components/y-banner.js +27 -15
  5. package/dist/components/y-breadcrumbs.js +25 -13
  6. package/dist/components/y-break/y-break.d.ts +1 -1
  7. package/dist/components/y-break.d.ts +1 -1
  8. package/dist/components/y-break.js +30 -18
  9. package/dist/components/y-button.js +3 -3
  10. package/dist/components/y-checkbox.js +25 -13
  11. package/dist/components/y-code/tokenizer.d.ts +2 -0
  12. package/dist/components/y-code/y-code.d.ts +70 -0
  13. package/dist/components/y-code.d.ts +70 -0
  14. package/dist/components/y-code.js +2450 -0
  15. package/dist/components/y-color.js +95 -14
  16. package/dist/components/y-colorpicker.js +95 -14
  17. package/dist/components/y-data-grid/y-data-grid.d.ts +260 -0
  18. package/dist/components/y-data-grid.d.ts +260 -0
  19. package/dist/components/y-data-grid.js +11848 -0
  20. package/dist/components/y-date.js +98 -17
  21. package/dist/components/y-datepicker.js +98 -17
  22. package/dist/components/y-dock.js +25 -13
  23. package/dist/components/y-droplist/y-droplist.d.ts +8 -0
  24. package/dist/components/y-droplist.d.ts +8 -0
  25. package/dist/components/y-droplist.js +50 -4
  26. package/dist/components/y-gallery.js +25 -13
  27. package/dist/components/y-help/y-help.d.ts +143 -0
  28. package/dist/components/y-help.d.ts +143 -0
  29. package/dist/components/y-help.js +4025 -0
  30. package/dist/components/y-icon/y-icon.d.ts +7 -2
  31. package/dist/components/y-icon.d.ts +7 -2
  32. package/dist/components/y-icon.js +25 -13
  33. package/dist/components/y-menu.js +25 -13
  34. package/dist/components/y-paginator/y-paginator.d.ts +17 -0
  35. package/dist/components/y-paginator.d.ts +17 -0
  36. package/dist/components/y-paginator.js +270 -18
  37. package/dist/components/y-popover/y-popover.d.ts +163 -0
  38. package/dist/components/y-popover.d.ts +163 -0
  39. package/dist/components/y-popover.js +2155 -0
  40. package/dist/components/y-rating/y-rating.d.ts +2 -2
  41. package/dist/components/y-rating.d.ts +2 -2
  42. package/dist/components/y-rating.js +47 -14
  43. package/dist/components/y-select/y-select.d.ts +11 -0
  44. package/dist/components/y-select.d.ts +11 -0
  45. package/dist/components/y-select.js +96 -15
  46. package/dist/components/y-shape/y-shape.d.ts +39 -0
  47. package/dist/components/y-shape.d.ts +39 -0
  48. package/dist/components/y-shape.js +302 -0
  49. package/dist/components/y-sidebar.js +27 -15
  50. package/dist/components/y-splitter.js +25 -13
  51. package/dist/components/y-stepper/y-stepper.d.ts +16 -0
  52. package/dist/components/y-stepper.d.ts +16 -0
  53. package/dist/components/y-stepper.js +124 -21
  54. package/dist/components/y-tabs.js +25 -13
  55. package/dist/components/y-tag.js +2 -6
  56. package/dist/components/y-theme.js +23 -23
  57. package/dist/components/y-toast.js +25 -13
  58. package/dist/components/y-tree-item.js +25 -13
  59. package/dist/components/y-tree.js +25 -13
  60. package/dist/icons/all-filled.d.ts +1 -0
  61. package/dist/icons/all-filled.js +362 -0
  62. package/dist/icons/all.js +7 -3
  63. package/dist/icons/registry.d.ts +2 -0
  64. package/dist/icons/registry.js +6 -1
  65. package/dist/index.d.ts +3 -0
  66. package/dist/index.js +11765 -6150
  67. package/dist/modules/floating.d.ts +126 -0
  68. package/dist/modules/floating.js +285 -0
  69. package/dist/modules/floating.test.js +180 -0
  70. package/dist/modules/helpers.d.ts +15 -7
  71. package/dist/modules/helpers.js +18 -15
  72. package/dist/modules/helpers.test.js +61 -0
  73. package/dist/react.d.ts +127 -2
  74. package/dist/styles/blue-dark.css +5 -0
  75. package/dist/styles/blue-light.css +5 -0
  76. package/dist/styles/brown-dark.css +5 -0
  77. package/dist/styles/brown-light.css +5 -0
  78. package/dist/styles/green-dark.css +5 -0
  79. package/dist/styles/green-light.css +5 -0
  80. package/dist/styles/indigo-dark.css +5 -0
  81. package/dist/styles/indigo-light.css +5 -0
  82. package/dist/styles/olive-dark.css +5 -0
  83. package/dist/styles/olive-light.css +5 -0
  84. package/dist/styles/orange-dark.css +5 -0
  85. package/dist/styles/orange-light.css +5 -0
  86. package/dist/styles/pink-dark.css +5 -0
  87. package/dist/styles/pink-light.css +5 -0
  88. package/dist/styles/purple-dark.css +5 -0
  89. package/dist/styles/purple-light.css +5 -0
  90. package/dist/styles/red-dark.css +5 -0
  91. package/dist/styles/red-light.css +5 -0
  92. package/dist/styles/teal-dark.css +5 -0
  93. package/dist/styles/teal-light.css +5 -0
  94. package/dist/styles/variables.css +46 -0
  95. package/dist/styles/yellow-dark.css +5 -0
  96. package/dist/styles/yellow-light.css +5 -0
  97. package/dist/yumekit.min.js +1 -1
  98. package/llm.txt +335 -9
  99. package/package.json +2 -1
package/CHANGELOG.md CHANGED
@@ -31,7 +31,45 @@ Delete any empty sections before publishing.
31
31
  <!-- ### Security -->
32
32
  <!-- Vulnerability patches or hardening changes -->
33
33
 
34
- ## [0.5.0]
34
+ ## [0.5.1]
35
+
36
+ ### Added
37
+
38
+ - New `y-data-grid` component — interactive grid for large or dynamic datasets with client- or server-side sorting, filtering, and pagination, single/multi row selection, inline cell editing, nested row grouping with aggregates, multi-column header groups, virtual scrolling, an optional per-column header menu (filter, sort, visibility, reorder), and a sticky header.
39
+
40
+ - New `y-popover` component — target-anchored floating panel with rich slotted content, composable triggers (`click` / `hover` / `focus` / `context-menu` / `manual`), flip-on-collision positioning, optional modal mode with focus trap, and an opt-in `portal` mode that renders into `<body>` to escape ancestor stacking contexts.
41
+
42
+ - New `y-help` component — guided product-tour / onboarding overlay. Walks users through an ordered list of steps with a dimmed SVG highlight, anchored tooltip, prev/next controls, overlay-edge arrows, and keyboard shortcuts.
43
+
44
+ - New `y-code` component — code-block container with line numbers, copy-to-clipboard (block and per-line), `max-lines` collapse, and an optional filename header. Built-in tokenizer covers JavaScript, TypeScript, JSON, CSS, Python, Bash, and HTML; emits Prism-compatible classes so existing Prism stylesheets layer on cleanly, or pipe an external highlighter's output through the sanitized `highlighted` slot.
45
+
46
+ - New `y-shape` component — presentational container that clips its slotted content into a geometric shape (rectangle, circle, ellipse, star, heart, chat-bubble, times, cross, or a custom `polygon`) via CSS `clip-path`. Suitable for avatar masks, decorative panels, and non-rectangular skeletons.
47
+
48
+ - `y-stepper` — `responsive` and `responsive-breakpoint` attributes; auto-flips horizontal layouts to vertical below the breakpoint (600px default). Enabled by default; set `responsive="false"` to opt out.
49
+
50
+ - Filled icon variants for `y-icon` via a new `weight="filled"` value, with automatic fallback to the line icon when no filled version is registered. 116 filled icons ship under `icons/all-filled.js` (also pulled in by `icons/all.js`); the remaining component-illustration icons fall back to their line versions.
51
+
52
+ ### Changed
53
+
54
+ - Custom color support expanded to the browser-native color functions — `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()`, and `color()` — in addition to `#hex`, `rgb()`/`rgba()`, and `hsl()`/`hsla()`. The shared `isSafeCssColor` gate now also tightens its argument allowlist (rejecting semicolons, braces, angle brackets, and nested functions). Applies anywhere a `color` accepts a custom value, including `y-badge`, `y-select`, `y-popover`, `y-button`, `y-tag`, `y-icon`, and `y-rating`.
55
+
56
+ - `y-rating` — selected icons now swap in the registered `filled` weight variant instead of just thickening the line stroke, falling back to the thick stroke when no filled variant is available.
57
+
58
+ - `y-paginator` — page-button list now auto-shrinks to fit the host width, growing back when space allows.
59
+
60
+ - `y-select` — new opt-in `portal` attribute renders the dropdown into `<body>` so it escapes scrollable or clipped ancestors (e.g. inside a data-grid cell editor).
61
+
62
+ - **Breaking** `y-break`: `inset` values renamed from `"sm"` / `"md"` / `"lg"` to `"small"` / `"medium"` / `"large"` to match the size scale used by every other component. Spacing mapping is unchanged (`small` → `--spacing-x-small`, `medium` → `--spacing-medium`, `large` → `--spacing-x-large`), so visual output is identical after the find-and-replace.
63
+
64
+ ### Fixed
65
+
66
+ - `y-button` — no longer throws when `color` is set to an unrecognized value that isn't a valid custom color; it now falls back to the `base` theme instead of crashing while reading the color-token map.
67
+
68
+ - `y-droplist` — touch drag now works reliably on iOS Safari and Chrome Android. `touch-action: none` is applied to the press target at decoration time instead of from inside `pointerdown`, so mobile browsers stop preempting the press as a scroll gesture.
69
+
70
+ - Corrected the arrow direction on the `left-from-bracket`, `right-from-bracket`, and `left-to-bracket` icons, which previously pointed the wrong way relative to their bracket (the `*-from-*` arrows now exit the bracket and the `*-to-*` arrow enters it).
71
+
72
+ ## [0.5.0] - 2026-05-25
35
73
 
36
74
  ### Added
37
75
 
package/CONTRIBUTING.md CHANGED
@@ -87,7 +87,7 @@ if (this.querySelector('[slot="icon"]')) { ... }
87
87
 
88
88
  The DOM-element, icon, and slot rules above exist primarily to keep user-controlled values out of `innerHTML` template strings, where attribute interpolation can break out of the surrounding quote. Building the shadow tree with `_el` and writing values through `setAttribute` makes that breakout impossible — the entire string becomes a single attribute value, no matter what quotes or angle brackets it contains. Two shared helpers cover the cases where `_el` alone isn't enough:
89
89
 
90
- - **CSS color literals (`isSafeCssColor` from `src/modules/helpers.js`).** When a component paints a user-supplied color into any CSS context — an inline `style` attribute, a `<style>` block built via `replaceSync`, or a CSS variable — gate the value through `isSafeCssColor` first. It accepts only `#hex`, `rgb()`/`rgba()`, and `hsl()`/`hsla()` literals; everything else (including named colors, `var(...)`, `currentColor`, and anything containing whitespace, semicolons, or braces) is rejected. Fall back to a semantic theme default when the check fails. `y-badge` and `y-select` (per-option `color`) follow this pattern.
90
+ - **CSS color literals (`isSafeCssColor` from `src/modules/helpers.js`).** When a component paints a user-supplied color into any CSS context — an inline `style` attribute, a `<style>` block built via `replaceSync`, or a CSS variable — gate the value through `isSafeCssColor` first. It accepts `#hex` and the browser-native color functions (`rgb()`/`rgba()`, `hsl()`/`hsla()`, `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()`, `color()`); the function body may contain only the characters those forms use, so named colors, `var(...)`, `currentColor`, nested functions, and anything with semicolons, braces, or angle brackets are rejected. Fall back to a semantic theme default when the check fails. `y-badge` and `y-select` (per-option `color`) follow this pattern.
91
91
 
92
92
  - **SVG markup (`getSanitizedIcon` / `sanitizeSvg` from `src/modules/svg-sanitizer.js`).** Any time you would render an SVG that originated outside the bundled icon set — e.g. anything coming back from `getIcon(name)` where `name` could resolve to a `registerIcon` payload — run it through the shared sanitizer first. `<y-icon>` is the simplest path; if you need raw markup, call `getSanitizedIcon(name)` and inject the returned string. The sanitizer strips every element and attribute outside the SVG allowlist (no `<script>`, no `onload`, no `xlink:href`, …) and memoizes results per icon name.
93
93
 
@@ -1,4 +1,4 @@
1
- import { contrastTextColor, createElement, resolveAnchor, isNavItemActive, buildNavItemIcon, navigateFrom } from '../../modules/helpers.js';
1
+ import { contrastTextColor, isSafeCssColor, createElement, resolveAnchor, isNavItemActive, buildNavItemIcon, navigateFrom } from '../../modules/helpers.js';
2
2
 
3
3
  class YumeButton extends HTMLElement {
4
4
  static get observedAttributes() {
@@ -519,12 +519,12 @@ class YumeButton extends HTMLElement {
519
519
  const { color, size, styleType } = this;
520
520
  const colorVars = this._getColorVarsMap();
521
521
 
522
- if (!colorVars[color] && color && (color.startsWith("#") || color.startsWith("rgb") || color.startsWith("hsl"))) {
522
+ if (!colorVars[color] && isSafeCssColor(color)) {
523
523
  this._applyCustomColorStyles(color, styleType, size);
524
524
  return;
525
525
  }
526
526
 
527
- const vars = colorVars[color];
527
+ const vars = colorVars[color] || colorVars.base;
528
528
 
529
529
  const styleVars = {
530
530
  outlined: {
@@ -784,7 +784,11 @@ class YumeIcon extends HTMLElement {
784
784
  this.setAttribute("size", val);
785
785
  }
786
786
 
787
- /** Stroke weight: "thin" | "regular" | "thick". */
787
+ /**
788
+ * Weight: "x-thin" | "thin" | "regular" (default) | "thick" | "x-thick" set
789
+ * the stroke width of line icons; "filled" swaps in the filled variant
790
+ * (falling back to the line icon when no filled variant is registered).
791
+ */
788
792
  get weight() {
789
793
  return this.getAttribute("weight") || "regular";
790
794
  }
@@ -798,9 +802,10 @@ class YumeIcon extends HTMLElement {
798
802
  // -------------------------------------------------------------------------
799
803
 
800
804
  render() {
801
- const svg = getSanitizedIcon(this.name);
805
+ const svg = getSanitizedIcon(this._resolveIconName());
802
806
  const sizeVal = this._getSize(this.size);
803
807
  const colorVal = this.color ? this._getColor(this.color) : "inherit";
808
+ // "filled" maps to no stroke width, so the filled variant ignores weight.
804
809
  const weightVal = this._getWeight(this.weight);
805
810
 
806
811
  this._updateAria();
@@ -809,7 +814,7 @@ class YumeIcon extends HTMLElement {
809
814
  wrapper.innerHTML = svg;
810
815
 
811
816
  this.shadowRoot.adoptedStyleSheets = [
812
- this._buildStyleSheet(sizeVal, colorVal, weightVal),
817
+ this._buildStyleSheet(sizeVal, colorVal, weightVal, this.weight === "filled"),
813
818
  ];
814
819
  this.shadowRoot.replaceChildren(wrapper);
815
820
  }
@@ -818,7 +823,7 @@ class YumeIcon extends HTMLElement {
818
823
  // Private
819
824
  // -------------------------------------------------------------------------
820
825
 
821
- _buildStyleSheet(sizeVal, colorVal, weightVal) {
826
+ _buildStyleSheet(sizeVal, colorVal, weightVal, isFilled = false) {
822
827
  const sheet = new CSSStyleSheet();
823
828
  sheet.replaceSync(`
824
829
  :host {
@@ -834,6 +839,12 @@ class YumeIcon extends HTMLElement {
834
839
  width: 100%;
835
840
  height: 100%;
836
841
  }
842
+ ${isFilled ? `.icon-wrapper svg {
843
+ /* Line icons render a ~1px stroke that extends past their path;
844
+ scale filled icons up so they read at the same optical size. */
845
+ transform: scale(1.1);
846
+ transform-origin: center;
847
+ }` : ""}
837
848
  ${this._getWeightCSS(weightVal)}
838
849
  `);
839
850
  return sheet;
@@ -850,14 +861,7 @@ class YumeIcon extends HTMLElement {
850
861
  help: "var(--help-content--, #5405ff)",
851
862
  };
852
863
  if (map[color]) return map[color];
853
- if (
854
- color &&
855
- (color.startsWith("#") ||
856
- color.startsWith("rgb") ||
857
- color.startsWith("hsl"))
858
- ) {
859
- return color;
860
- }
864
+ if (isSafeCssColor(color)) return color;
861
865
  return map.base;
862
866
  }
863
867
 
@@ -889,6 +893,14 @@ class YumeIcon extends HTMLElement {
889
893
  .icon-wrapper svg * { stroke-width: ${weightVal} !important; }`;
890
894
  }
891
895
 
896
+ _resolveIconName() {
897
+ if (this.weight === "filled") {
898
+ const filled = `${this.name}-fill`;
899
+ if (getSanitizedIcon(filled)) return filled;
900
+ }
901
+ return this.name;
902
+ }
903
+
892
904
  _updateAria() {
893
905
  if (this.label) {
894
906
  this.setAttribute("role", "img");
@@ -1,4 +1,4 @@
1
- import { contrastTextColor, createElement } from '../../modules/helpers.js';
1
+ import { contrastTextColor, isSafeCssColor, createElement } from '../../modules/helpers.js';
2
2
 
3
3
  class YumeButton extends HTMLElement {
4
4
  static get observedAttributes() {
@@ -519,12 +519,12 @@ class YumeButton extends HTMLElement {
519
519
  const { color, size, styleType } = this;
520
520
  const colorVars = this._getColorVarsMap();
521
521
 
522
- if (!colorVars[color] && color && (color.startsWith("#") || color.startsWith("rgb") || color.startsWith("hsl"))) {
522
+ if (!colorVars[color] && isSafeCssColor(color)) {
523
523
  this._applyCustomColorStyles(color, styleType, size);
524
524
  return;
525
525
  }
526
526
 
527
- const vars = colorVars[color];
527
+ const vars = colorVars[color] || colorVars.base;
528
528
 
529
529
  const styleVars = {
530
530
  outlined: {
@@ -784,7 +784,11 @@ class YumeIcon extends HTMLElement {
784
784
  this.setAttribute("size", val);
785
785
  }
786
786
 
787
- /** Stroke weight: "thin" | "regular" | "thick". */
787
+ /**
788
+ * Weight: "x-thin" | "thin" | "regular" (default) | "thick" | "x-thick" set
789
+ * the stroke width of line icons; "filled" swaps in the filled variant
790
+ * (falling back to the line icon when no filled variant is registered).
791
+ */
788
792
  get weight() {
789
793
  return this.getAttribute("weight") || "regular";
790
794
  }
@@ -798,9 +802,10 @@ class YumeIcon extends HTMLElement {
798
802
  // -------------------------------------------------------------------------
799
803
 
800
804
  render() {
801
- const svg = getSanitizedIcon(this.name);
805
+ const svg = getSanitizedIcon(this._resolveIconName());
802
806
  const sizeVal = this._getSize(this.size);
803
807
  const colorVal = this.color ? this._getColor(this.color) : "inherit";
808
+ // "filled" maps to no stroke width, so the filled variant ignores weight.
804
809
  const weightVal = this._getWeight(this.weight);
805
810
 
806
811
  this._updateAria();
@@ -809,7 +814,7 @@ class YumeIcon extends HTMLElement {
809
814
  wrapper.innerHTML = svg;
810
815
 
811
816
  this.shadowRoot.adoptedStyleSheets = [
812
- this._buildStyleSheet(sizeVal, colorVal, weightVal),
817
+ this._buildStyleSheet(sizeVal, colorVal, weightVal, this.weight === "filled"),
813
818
  ];
814
819
  this.shadowRoot.replaceChildren(wrapper);
815
820
  }
@@ -818,7 +823,7 @@ class YumeIcon extends HTMLElement {
818
823
  // Private
819
824
  // -------------------------------------------------------------------------
820
825
 
821
- _buildStyleSheet(sizeVal, colorVal, weightVal) {
826
+ _buildStyleSheet(sizeVal, colorVal, weightVal, isFilled = false) {
822
827
  const sheet = new CSSStyleSheet();
823
828
  sheet.replaceSync(`
824
829
  :host {
@@ -834,6 +839,12 @@ class YumeIcon extends HTMLElement {
834
839
  width: 100%;
835
840
  height: 100%;
836
841
  }
842
+ ${isFilled ? `.icon-wrapper svg {
843
+ /* Line icons render a ~1px stroke that extends past their path;
844
+ scale filled icons up so they read at the same optical size. */
845
+ transform: scale(1.1);
846
+ transform-origin: center;
847
+ }` : ""}
837
848
  ${this._getWeightCSS(weightVal)}
838
849
  `);
839
850
  return sheet;
@@ -850,14 +861,7 @@ class YumeIcon extends HTMLElement {
850
861
  help: "var(--help-content--, #5405ff)",
851
862
  };
852
863
  if (map[color]) return map[color];
853
- if (
854
- color &&
855
- (color.startsWith("#") ||
856
- color.startsWith("rgb") ||
857
- color.startsWith("hsl"))
858
- ) {
859
- return color;
860
- }
864
+ if (isSafeCssColor(color)) return color;
861
865
  return map.base;
862
866
  }
863
867
 
@@ -889,6 +893,14 @@ class YumeIcon extends HTMLElement {
889
893
  .icon-wrapper svg * { stroke-width: ${weightVal} !important; }`;
890
894
  }
891
895
 
896
+ _resolveIconName() {
897
+ if (this.weight === "filled") {
898
+ const filled = `${this.name}-fill`;
899
+ if (getSanitizedIcon(filled)) return filled;
900
+ }
901
+ return this.name;
902
+ }
903
+
892
904
  _updateAria() {
893
905
  if (this.label) {
894
906
  this.setAttribute("role", "img");
@@ -1,4 +1,4 @@
1
- import { createElement } from '../../modules/helpers.js';
1
+ import { createElement, isSafeCssColor } from '../../modules/helpers.js';
2
2
 
3
3
  /**
4
4
  * Icon registry — a runtime map of icon names to SVG markup strings.
@@ -226,7 +226,11 @@ class YumeIcon extends HTMLElement {
226
226
  this.setAttribute("size", val);
227
227
  }
228
228
 
229
- /** Stroke weight: "thin" | "regular" | "thick". */
229
+ /**
230
+ * Weight: "x-thin" | "thin" | "regular" (default) | "thick" | "x-thick" set
231
+ * the stroke width of line icons; "filled" swaps in the filled variant
232
+ * (falling back to the line icon when no filled variant is registered).
233
+ */
230
234
  get weight() {
231
235
  return this.getAttribute("weight") || "regular";
232
236
  }
@@ -240,9 +244,10 @@ class YumeIcon extends HTMLElement {
240
244
  // -------------------------------------------------------------------------
241
245
 
242
246
  render() {
243
- const svg = getSanitizedIcon(this.name);
247
+ const svg = getSanitizedIcon(this._resolveIconName());
244
248
  const sizeVal = this._getSize(this.size);
245
249
  const colorVal = this.color ? this._getColor(this.color) : "inherit";
250
+ // "filled" maps to no stroke width, so the filled variant ignores weight.
246
251
  const weightVal = this._getWeight(this.weight);
247
252
 
248
253
  this._updateAria();
@@ -251,7 +256,7 @@ class YumeIcon extends HTMLElement {
251
256
  wrapper.innerHTML = svg;
252
257
 
253
258
  this.shadowRoot.adoptedStyleSheets = [
254
- this._buildStyleSheet(sizeVal, colorVal, weightVal),
259
+ this._buildStyleSheet(sizeVal, colorVal, weightVal, this.weight === "filled"),
255
260
  ];
256
261
  this.shadowRoot.replaceChildren(wrapper);
257
262
  }
@@ -260,7 +265,7 @@ class YumeIcon extends HTMLElement {
260
265
  // Private
261
266
  // -------------------------------------------------------------------------
262
267
 
263
- _buildStyleSheet(sizeVal, colorVal, weightVal) {
268
+ _buildStyleSheet(sizeVal, colorVal, weightVal, isFilled = false) {
264
269
  const sheet = new CSSStyleSheet();
265
270
  sheet.replaceSync(`
266
271
  :host {
@@ -276,6 +281,12 @@ class YumeIcon extends HTMLElement {
276
281
  width: 100%;
277
282
  height: 100%;
278
283
  }
284
+ ${isFilled ? `.icon-wrapper svg {
285
+ /* Line icons render a ~1px stroke that extends past their path;
286
+ scale filled icons up so they read at the same optical size. */
287
+ transform: scale(1.1);
288
+ transform-origin: center;
289
+ }` : ""}
279
290
  ${this._getWeightCSS(weightVal)}
280
291
  `);
281
292
  return sheet;
@@ -292,14 +303,7 @@ class YumeIcon extends HTMLElement {
292
303
  help: "var(--help-content--, #5405ff)",
293
304
  };
294
305
  if (map[color]) return map[color];
295
- if (
296
- color &&
297
- (color.startsWith("#") ||
298
- color.startsWith("rgb") ||
299
- color.startsWith("hsl"))
300
- ) {
301
- return color;
302
- }
306
+ if (isSafeCssColor(color)) return color;
303
307
  return map.base;
304
308
  }
305
309
 
@@ -331,6 +335,14 @@ class YumeIcon extends HTMLElement {
331
335
  .icon-wrapper svg * { stroke-width: ${weightVal} !important; }`;
332
336
  }
333
337
 
338
+ _resolveIconName() {
339
+ if (this.weight === "filled") {
340
+ const filled = `${this.name}-fill`;
341
+ if (getSanitizedIcon(filled)) return filled;
342
+ }
343
+ return this.name;
344
+ }
345
+
334
346
  _updateAria() {
335
347
  if (this.label) {
336
348
  this.setAttribute("role", "img");
@@ -9,7 +9,7 @@ export class YumeBreak extends HTMLElement {
9
9
  /** Convenience icon name rendered in the center when no slotted content is present. */
10
10
  get icon(): string;
11
11
  set inset(val: string);
12
- /** Outer end padding token: "none" | "sm" | "md" | "lg". */
12
+ /** Outer end padding token: "none" (default) | "small" | "medium" | "large". */
13
13
  get inset(): string;
14
14
  set label(val: string);
15
15
  /** Convenience text label rendered in the center when no slotted content is present. */
@@ -9,7 +9,7 @@ export class YumeBreak extends HTMLElement {
9
9
  /** Convenience icon name rendered in the center when no slotted content is present. */
10
10
  get icon(): string;
11
11
  set inset(val: string);
12
- /** Outer end padding token: "none" | "sm" | "md" | "lg". */
12
+ /** Outer end padding token: "none" (default) | "small" | "medium" | "large". */
13
13
  get inset(): string;
14
14
  set label(val: string);
15
15
  /** Convenience text label rendered in the center when no slotted content is present. */
@@ -1,4 +1,4 @@
1
- import { createElement } from '../../modules/helpers.js';
1
+ import { createElement, isSafeCssColor } from '../../modules/helpers.js';
2
2
 
3
3
  /**
4
4
  * Icon registry — a runtime map of icon names to SVG markup strings.
@@ -226,7 +226,11 @@ class YumeIcon extends HTMLElement {
226
226
  this.setAttribute("size", val);
227
227
  }
228
228
 
229
- /** Stroke weight: "thin" | "regular" | "thick". */
229
+ /**
230
+ * Weight: "x-thin" | "thin" | "regular" (default) | "thick" | "x-thick" set
231
+ * the stroke width of line icons; "filled" swaps in the filled variant
232
+ * (falling back to the line icon when no filled variant is registered).
233
+ */
230
234
  get weight() {
231
235
  return this.getAttribute("weight") || "regular";
232
236
  }
@@ -240,9 +244,10 @@ class YumeIcon extends HTMLElement {
240
244
  // -------------------------------------------------------------------------
241
245
 
242
246
  render() {
243
- const svg = getSanitizedIcon(this.name);
247
+ const svg = getSanitizedIcon(this._resolveIconName());
244
248
  const sizeVal = this._getSize(this.size);
245
249
  const colorVal = this.color ? this._getColor(this.color) : "inherit";
250
+ // "filled" maps to no stroke width, so the filled variant ignores weight.
246
251
  const weightVal = this._getWeight(this.weight);
247
252
 
248
253
  this._updateAria();
@@ -251,7 +256,7 @@ class YumeIcon extends HTMLElement {
251
256
  wrapper.innerHTML = svg;
252
257
 
253
258
  this.shadowRoot.adoptedStyleSheets = [
254
- this._buildStyleSheet(sizeVal, colorVal, weightVal),
259
+ this._buildStyleSheet(sizeVal, colorVal, weightVal, this.weight === "filled"),
255
260
  ];
256
261
  this.shadowRoot.replaceChildren(wrapper);
257
262
  }
@@ -260,7 +265,7 @@ class YumeIcon extends HTMLElement {
260
265
  // Private
261
266
  // -------------------------------------------------------------------------
262
267
 
263
- _buildStyleSheet(sizeVal, colorVal, weightVal) {
268
+ _buildStyleSheet(sizeVal, colorVal, weightVal, isFilled = false) {
264
269
  const sheet = new CSSStyleSheet();
265
270
  sheet.replaceSync(`
266
271
  :host {
@@ -276,6 +281,12 @@ class YumeIcon extends HTMLElement {
276
281
  width: 100%;
277
282
  height: 100%;
278
283
  }
284
+ ${isFilled ? `.icon-wrapper svg {
285
+ /* Line icons render a ~1px stroke that extends past their path;
286
+ scale filled icons up so they read at the same optical size. */
287
+ transform: scale(1.1);
288
+ transform-origin: center;
289
+ }` : ""}
279
290
  ${this._getWeightCSS(weightVal)}
280
291
  `);
281
292
  return sheet;
@@ -292,14 +303,7 @@ class YumeIcon extends HTMLElement {
292
303
  help: "var(--help-content--, #5405ff)",
293
304
  };
294
305
  if (map[color]) return map[color];
295
- if (
296
- color &&
297
- (color.startsWith("#") ||
298
- color.startsWith("rgb") ||
299
- color.startsWith("hsl"))
300
- ) {
301
- return color;
302
- }
306
+ if (isSafeCssColor(color)) return color;
303
307
  return map.base;
304
308
  }
305
309
 
@@ -331,6 +335,14 @@ class YumeIcon extends HTMLElement {
331
335
  .icon-wrapper svg * { stroke-width: ${weightVal} !important; }`;
332
336
  }
333
337
 
338
+ _resolveIconName() {
339
+ if (this.weight === "filled") {
340
+ const filled = `${this.name}-fill`;
341
+ if (getSanitizedIcon(filled)) return filled;
342
+ }
343
+ return this.name;
344
+ }
345
+
334
346
  _updateAria() {
335
347
  if (this.label) {
336
348
  this.setAttribute("role", "img");
@@ -351,13 +363,13 @@ if (!customElements.get("y-icon")) {
351
363
  const VALID_ORIENTATIONS = new Set(["horizontal", "vertical"]);
352
364
  const VALID_ALIGNMENTS = new Set(["start", "center", "end"]);
353
365
  const VALID_VARIANTS = new Set(["solid", "dashed", "dotted"]);
354
- const VALID_INSETS = new Set(["none", "sm", "md", "lg"]);
366
+ const VALID_INSETS = new Set(["none", "small", "medium", "large"]);
355
367
 
356
368
  const INSET_TOKENS = {
357
369
  none: "0",
358
- sm: "var(--spacing-x-small)",
359
- md: "var(--spacing-medium)",
360
- lg: "var(--spacing-x-large)",
370
+ small: "var(--spacing-x-small)",
371
+ medium: "var(--spacing-medium)",
372
+ large: "var(--spacing-x-large)",
361
373
  };
362
374
 
363
375
  class YumeBreak extends HTMLElement {
@@ -409,7 +421,7 @@ class YumeBreak extends HTMLElement {
409
421
  else this.removeAttribute("icon");
410
422
  }
411
423
 
412
- /** Outer end padding token: "none" | "sm" | "md" | "lg". */
424
+ /** Outer end padding token: "none" (default) | "small" | "medium" | "large". */
413
425
  get inset() {
414
426
  const v = this.getAttribute("inset");
415
427
  return VALID_INSETS.has(v) ? v : "none";
@@ -1,4 +1,4 @@
1
- import { contrastTextColor } from '../../modules/helpers.js';
1
+ import { contrastTextColor, isSafeCssColor } from '../../modules/helpers.js';
2
2
 
3
3
  class YumeButton extends HTMLElement {
4
4
  static get observedAttributes() {
@@ -519,12 +519,12 @@ class YumeButton extends HTMLElement {
519
519
  const { color, size, styleType } = this;
520
520
  const colorVars = this._getColorVarsMap();
521
521
 
522
- if (!colorVars[color] && color && (color.startsWith("#") || color.startsWith("rgb") || color.startsWith("hsl"))) {
522
+ if (!colorVars[color] && isSafeCssColor(color)) {
523
523
  this._applyCustomColorStyles(color, styleType, size);
524
524
  return;
525
525
  }
526
526
 
527
- const vars = colorVars[color];
527
+ const vars = colorVars[color] || colorVars.base;
528
528
 
529
529
  const styleVars = {
530
530
  outlined: {
@@ -1,4 +1,4 @@
1
- import { createElement } from '../../modules/helpers.js';
1
+ import { createElement, isSafeCssColor } from '../../modules/helpers.js';
2
2
 
3
3
  /**
4
4
  * Icon registry — a runtime map of icon names to SVG markup strings.
@@ -226,7 +226,11 @@ class YumeIcon extends HTMLElement {
226
226
  this.setAttribute("size", val);
227
227
  }
228
228
 
229
- /** Stroke weight: "thin" | "regular" | "thick". */
229
+ /**
230
+ * Weight: "x-thin" | "thin" | "regular" (default) | "thick" | "x-thick" set
231
+ * the stroke width of line icons; "filled" swaps in the filled variant
232
+ * (falling back to the line icon when no filled variant is registered).
233
+ */
230
234
  get weight() {
231
235
  return this.getAttribute("weight") || "regular";
232
236
  }
@@ -240,9 +244,10 @@ class YumeIcon extends HTMLElement {
240
244
  // -------------------------------------------------------------------------
241
245
 
242
246
  render() {
243
- const svg = getSanitizedIcon(this.name);
247
+ const svg = getSanitizedIcon(this._resolveIconName());
244
248
  const sizeVal = this._getSize(this.size);
245
249
  const colorVal = this.color ? this._getColor(this.color) : "inherit";
250
+ // "filled" maps to no stroke width, so the filled variant ignores weight.
246
251
  const weightVal = this._getWeight(this.weight);
247
252
 
248
253
  this._updateAria();
@@ -251,7 +256,7 @@ class YumeIcon extends HTMLElement {
251
256
  wrapper.innerHTML = svg;
252
257
 
253
258
  this.shadowRoot.adoptedStyleSheets = [
254
- this._buildStyleSheet(sizeVal, colorVal, weightVal),
259
+ this._buildStyleSheet(sizeVal, colorVal, weightVal, this.weight === "filled"),
255
260
  ];
256
261
  this.shadowRoot.replaceChildren(wrapper);
257
262
  }
@@ -260,7 +265,7 @@ class YumeIcon extends HTMLElement {
260
265
  // Private
261
266
  // -------------------------------------------------------------------------
262
267
 
263
- _buildStyleSheet(sizeVal, colorVal, weightVal) {
268
+ _buildStyleSheet(sizeVal, colorVal, weightVal, isFilled = false) {
264
269
  const sheet = new CSSStyleSheet();
265
270
  sheet.replaceSync(`
266
271
  :host {
@@ -276,6 +281,12 @@ class YumeIcon extends HTMLElement {
276
281
  width: 100%;
277
282
  height: 100%;
278
283
  }
284
+ ${isFilled ? `.icon-wrapper svg {
285
+ /* Line icons render a ~1px stroke that extends past their path;
286
+ scale filled icons up so they read at the same optical size. */
287
+ transform: scale(1.1);
288
+ transform-origin: center;
289
+ }` : ""}
279
290
  ${this._getWeightCSS(weightVal)}
280
291
  `);
281
292
  return sheet;
@@ -292,14 +303,7 @@ class YumeIcon extends HTMLElement {
292
303
  help: "var(--help-content--, #5405ff)",
293
304
  };
294
305
  if (map[color]) return map[color];
295
- if (
296
- color &&
297
- (color.startsWith("#") ||
298
- color.startsWith("rgb") ||
299
- color.startsWith("hsl"))
300
- ) {
301
- return color;
302
- }
306
+ if (isSafeCssColor(color)) return color;
303
307
  return map.base;
304
308
  }
305
309
 
@@ -331,6 +335,14 @@ class YumeIcon extends HTMLElement {
331
335
  .icon-wrapper svg * { stroke-width: ${weightVal} !important; }`;
332
336
  }
333
337
 
338
+ _resolveIconName() {
339
+ if (this.weight === "filled") {
340
+ const filled = `${this.name}-fill`;
341
+ if (getSanitizedIcon(filled)) return filled;
342
+ }
343
+ return this.name;
344
+ }
345
+
334
346
  _updateAria() {
335
347
  if (this.label) {
336
348
  this.setAttribute("role", "img");
@@ -0,0 +1,2 @@
1
+ export function isSupportedLanguage(language: any): any;
2
+ export function tokenize(language: any, source: any): any;