@waggylabs/yumekit 0.5.0-beta.76 → 0.5.0-beta.81

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 (43) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/dist/components/y-avatar/y-avatar.d.ts +3 -2
  3. package/dist/components/y-avatar-group.js +17 -8
  4. package/dist/components/y-avatar.d.ts +3 -2
  5. package/dist/components/y-avatar.js +17 -8
  6. package/dist/components/y-dock/y-dock.d.ts +1 -0
  7. package/dist/components/y-dock.d.ts +1 -0
  8. package/dist/components/y-dock.js +7 -3
  9. package/dist/components/y-drawer.js +4 -4
  10. package/dist/components/y-droplist/y-droplist.d.ts +8 -0
  11. package/dist/components/y-droplist.d.ts +8 -0
  12. package/dist/components/y-droplist.js +16 -2
  13. package/dist/components/y-gallery.js +35 -12
  14. package/dist/components/y-progress.js +1 -0
  15. package/dist/components/y-theme.js +23 -23
  16. package/dist/index.js +103 -52
  17. package/dist/react.d.ts +150 -19
  18. package/dist/styles/blue-dark.css +22 -0
  19. package/dist/styles/blue-light.css +22 -0
  20. package/dist/styles/brown-dark.css +22 -0
  21. package/dist/styles/brown-light.css +22 -0
  22. package/dist/styles/green-dark.css +22 -0
  23. package/dist/styles/green-light.css +22 -0
  24. package/dist/styles/indigo-dark.css +22 -0
  25. package/dist/styles/indigo-light.css +22 -0
  26. package/dist/styles/olive-dark.css +22 -0
  27. package/dist/styles/olive-light.css +22 -0
  28. package/dist/styles/orange-dark.css +22 -0
  29. package/dist/styles/orange-light.css +22 -0
  30. package/dist/styles/pink-dark.css +22 -0
  31. package/dist/styles/pink-light.css +22 -0
  32. package/dist/styles/purple-dark.css +22 -0
  33. package/dist/styles/purple-light.css +22 -0
  34. package/dist/styles/red-dark.css +22 -0
  35. package/dist/styles/red-light.css +22 -0
  36. package/dist/styles/teal-dark.css +22 -0
  37. package/dist/styles/teal-light.css +22 -0
  38. package/dist/styles/variables.css +65 -24
  39. package/dist/styles/yellow-dark.css +22 -0
  40. package/dist/styles/yellow-light.css +22 -0
  41. package/dist/yumekit.min.js +1 -1
  42. package/llm.txt +48 -5
  43. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -53,6 +53,8 @@ Delete any empty sections before publishing.
53
53
 
54
54
  - New `y-paginator` component — page navigation control with a configurable button window.
55
55
 
56
+ - New `y-animate` component — a declarative wrapper that applies CSS-based entrance animations to its slotted children.
57
+
56
58
  ### Changed
57
59
 
58
60
  - **Icon rename — `comp-*` prefix dropped.** All 26 component-illustrating icons renamed. Two resolved collisions: `comp-menu` → `droplist` and `comp-tag` → `chip`.
@@ -90,7 +92,7 @@ Delete any empty sections before publishing.
90
92
 
91
93
  | Old name | New name | Glyph |
92
94
  | ---------- | ---------------------- | -------------------------- |
93
- | `ai` | `robot` | Microchip / CPU |
95
+ | `ai` | `robot` | Robot Head |
94
96
  | `ban` | `circle-slash` | Circle with diagonal slash |
95
97
  | `chart` | `waveform` | ECG / pulse waveform |
96
98
  | `close` | `x` | × mark |
@@ -113,6 +115,12 @@ Delete any empty sections before publishing.
113
115
 
114
116
  - **Breaking** `y-stack`: refocused as a flexbox-only primitive. Migration: `<y-stack mode="grid" …>` → `<y-grid …>`; `<y-stack mode="masonry" …>` → `<y-masonry …>`. The `mode` and `columns` attributes and the related `--component-stack-*` variables are removed.
115
117
 
118
+ ### Fixed
119
+
120
+ - `y-avatar`: when the image at `src` fails to load, the component now falls back to the initials rendering rather than displaying the browser's broken-image graphic.
121
+
122
+ - Orphaned CSS custom properties across several components now resolve to real design tokens instead of only their inline fallbacks. `y-dialog`, `y-banner`, `y-droplist`, `y-gallery`, `y-breadcrumbs`, `y-dock`, `y-input`, `y-progress`, `y-slider`, `y-stepper`, and `y-table` referenced `--component-*` variables that were never defined in the token pipeline; these are now themeable. Also fixed `y-gallery`'s broken `--neutral-black-translucent` fallback and stale `--y-color-*` references in the `y-droplist` stories.
123
+
116
124
  ### Security
117
125
 
118
126
  - **Breaking** `y-appbar` / `y-sidebar`: nav-item `icon` no longer accepts raw SVG markup — only registered icon names. Use `registerIcon` / `registerIcons` for custom glyphs.
@@ -1,5 +1,6 @@
1
1
  export class YumeAvatar extends HTMLElement {
2
2
  static get observedAttributes(): string[];
3
+ _imgFailed: boolean;
3
4
  attributeChangedCallback(name: any, oldValue: any, newValue: any): void;
4
5
  set alt(val: string);
5
6
  /** Initials fallback text when no src is provided (default "AN"). */
@@ -17,8 +18,8 @@ export class YumeAvatar extends HTMLElement {
17
18
  /** Image URL. When set, renders an <img> instead of initials. */
18
19
  get src(): string;
19
20
  render(): void;
20
- _buildAvatar(): HTMLElement;
21
- _buildStyleSheet(dimensions: any, borderRadius: any, bgColor: any, textColor: any): CSSStyleSheet;
21
+ _buildAvatar(showImg: any): HTMLElement;
22
+ _buildStyleSheet(showImg: any, dimensions: any, borderRadius: any, bgColor: any, textColor: any): CSSStyleSheet;
22
23
  _getDimensions(size: any): any;
23
24
  _getInitials(alt: any): any;
24
25
  }
@@ -12,11 +12,14 @@ class YumeAvatar extends HTMLElement {
12
12
  constructor() {
13
13
  super();
14
14
  this.attachShadow({ mode: "open" });
15
+ this._imgFailed = false;
15
16
  this.render();
16
17
  }
17
18
 
18
19
  attributeChangedCallback(name, oldValue, newValue) {
19
- if (oldValue !== newValue) this.render();
20
+ if (oldValue === newValue) return;
21
+ if (name === "src") this._imgFailed = false;
22
+ this.render();
20
23
  }
21
24
 
22
25
  // -------------------------------------------------------------------------
@@ -54,31 +57,37 @@ class YumeAvatar extends HTMLElement {
54
57
  const dimensions = this._getDimensions(this.size);
55
58
  const borderRadius = `var(--component-avatar-border-radius-${this.shape}, 9999px)`;
56
59
  const [bgColor, textColor] = getColorVarPair(this.color);
60
+ const showImg = !!this.src && !this._imgFailed;
57
61
 
58
- this.shadowRoot.adoptedStyleSheets = [this._buildStyleSheet(dimensions, borderRadius, bgColor, textColor)];
59
- this.shadowRoot.replaceChildren(this._buildAvatar());
62
+ this.shadowRoot.adoptedStyleSheets = [this._buildStyleSheet(showImg, dimensions, borderRadius, bgColor, textColor)];
63
+ this.shadowRoot.replaceChildren(this._buildAvatar(showImg));
60
64
  }
61
65
 
62
66
  // -------------------------------------------------------------------------
63
67
  // Private
64
68
  // -------------------------------------------------------------------------
65
69
 
66
- _buildAvatar() {
67
- if (this.src) {
68
- return createElement("img", {
70
+ _buildAvatar(showImg) {
71
+ if (showImg) {
72
+ const img = createElement("img", {
69
73
  src: this.src,
70
74
  alt: this.alt,
71
75
  part: "avatar",
72
76
  });
77
+ img.addEventListener("error", () => {
78
+ this._imgFailed = true;
79
+ this.render();
80
+ }, { once: true });
81
+ return img;
73
82
  }
74
83
  return createElement("div", { class: "avatar", part: "avatar" }, [
75
84
  createElement("h5", null, [this._getInitials(this.alt)]),
76
85
  ]);
77
86
  }
78
87
 
79
- _buildStyleSheet(dimensions, borderRadius, bgColor, textColor) {
88
+ _buildStyleSheet(showImg, dimensions, borderRadius, bgColor, textColor) {
80
89
  const sheet = new CSSStyleSheet();
81
- const css = this.src
90
+ const css = showImg
82
91
  ? `
83
92
  :host {
84
93
  display: inline-block;
@@ -1,5 +1,6 @@
1
1
  export class YumeAvatar extends HTMLElement {
2
2
  static get observedAttributes(): string[];
3
+ _imgFailed: boolean;
3
4
  attributeChangedCallback(name: any, oldValue: any, newValue: any): void;
4
5
  set alt(val: string);
5
6
  /** Initials fallback text when no src is provided (default "AN"). */
@@ -17,8 +18,8 @@ export class YumeAvatar extends HTMLElement {
17
18
  /** Image URL. When set, renders an <img> instead of initials. */
18
19
  get src(): string;
19
20
  render(): void;
20
- _buildAvatar(): HTMLElement;
21
- _buildStyleSheet(dimensions: any, borderRadius: any, bgColor: any, textColor: any): CSSStyleSheet;
21
+ _buildAvatar(showImg: any): HTMLElement;
22
+ _buildStyleSheet(showImg: any, dimensions: any, borderRadius: any, bgColor: any, textColor: any): CSSStyleSheet;
22
23
  _getDimensions(size: any): any;
23
24
  _getInitials(alt: any): any;
24
25
  }
@@ -12,11 +12,14 @@ class YumeAvatar extends HTMLElement {
12
12
  constructor() {
13
13
  super();
14
14
  this.attachShadow({ mode: "open" });
15
+ this._imgFailed = false;
15
16
  this.render();
16
17
  }
17
18
 
18
19
  attributeChangedCallback(name, oldValue, newValue) {
19
- if (oldValue !== newValue) this.render();
20
+ if (oldValue === newValue) return;
21
+ if (name === "src") this._imgFailed = false;
22
+ this.render();
20
23
  }
21
24
 
22
25
  // -------------------------------------------------------------------------
@@ -54,31 +57,37 @@ class YumeAvatar extends HTMLElement {
54
57
  const dimensions = this._getDimensions(this.size);
55
58
  const borderRadius = `var(--component-avatar-border-radius-${this.shape}, 9999px)`;
56
59
  const [bgColor, textColor] = getColorVarPair(this.color);
60
+ const showImg = !!this.src && !this._imgFailed;
57
61
 
58
- this.shadowRoot.adoptedStyleSheets = [this._buildStyleSheet(dimensions, borderRadius, bgColor, textColor)];
59
- this.shadowRoot.replaceChildren(this._buildAvatar());
62
+ this.shadowRoot.adoptedStyleSheets = [this._buildStyleSheet(showImg, dimensions, borderRadius, bgColor, textColor)];
63
+ this.shadowRoot.replaceChildren(this._buildAvatar(showImg));
60
64
  }
61
65
 
62
66
  // -------------------------------------------------------------------------
63
67
  // Private
64
68
  // -------------------------------------------------------------------------
65
69
 
66
- _buildAvatar() {
67
- if (this.src) {
68
- return createElement("img", {
70
+ _buildAvatar(showImg) {
71
+ if (showImg) {
72
+ const img = createElement("img", {
69
73
  src: this.src,
70
74
  alt: this.alt,
71
75
  part: "avatar",
72
76
  });
77
+ img.addEventListener("error", () => {
78
+ this._imgFailed = true;
79
+ this.render();
80
+ }, { once: true });
81
+ return img;
73
82
  }
74
83
  return createElement("div", { class: "avatar", part: "avatar" }, [
75
84
  createElement("h5", null, [this._getInitials(this.alt)]),
76
85
  ]);
77
86
  }
78
87
 
79
- _buildStyleSheet(dimensions, borderRadius, bgColor, textColor) {
88
+ _buildStyleSheet(showImg, dimensions, borderRadius, bgColor, textColor) {
80
89
  const sheet = new CSSStyleSheet();
81
- const css = this.src
90
+ const css = showImg
82
91
  ? `
83
92
  :host {
84
93
  display: inline-block;
@@ -25,6 +25,7 @@ export class YumeDock extends HTMLElement {
25
25
  _buildBar(): HTMLElement;
26
26
  _buildItem(item: any): HTMLElement;
27
27
  _buildStyles(): HTMLStyleElement;
28
+ _getDefaultFontSize(): any;
28
29
  _handleItemClick(item: any): void;
29
30
  _setupBreakpoint(): void;
30
31
  _setupItemKeyboard(bar: any): void;
@@ -25,6 +25,7 @@ export class YumeDock extends HTMLElement {
25
25
  _buildBar(): HTMLElement;
26
26
  _buildItem(item: any): HTMLElement;
27
27
  _buildStyles(): HTMLStyleElement;
28
+ _getDefaultFontSize(): any;
28
29
  _handleItemClick(item: any): void;
29
30
  _setupBreakpoint(): void;
30
31
  _setupItemKeyboard(bar: any): void;
@@ -516,8 +516,7 @@ class YumeDock extends HTMLElement {
516
516
  const pos = this.position;
517
517
  const sz = this.size;
518
518
  const heightVar = `var(--component-dock-height, var(--component-dock-height-${sz}))`;
519
- const fontSize =
520
- sz === "small" ? "10px" : sz === "large" ? "13px" : "11px";
519
+ const fontSizeVar = `var(--component-dock-font-size-${sz}, ${this._getDefaultFontSize()})`;
521
520
  style.textContent = `
522
521
  :host {
523
522
  display: block;
@@ -560,7 +559,7 @@ class YumeDock extends HTMLElement {
560
559
  cursor: pointer;
561
560
  color: var(--component-dock-color);
562
561
  font-family: inherit;
563
- font-size: ${fontSize};
562
+ font-size: ${fontSizeVar};
564
563
  min-width: 48px;
565
564
  outline: none;
566
565
  transition: color 0.15s ease;
@@ -594,6 +593,11 @@ class YumeDock extends HTMLElement {
594
593
  return style;
595
594
  }
596
595
 
596
+ _getDefaultFontSize() {
597
+ const map = { small: "10px", medium: "11px", large: "13px" };
598
+ return map[this.size] || map.medium;
599
+ }
600
+
597
601
  _handleItemClick(item) {
598
602
  if (!item.href) return;
599
603
 
@@ -185,7 +185,7 @@ class YumeDrawer extends HTMLElement {
185
185
  position: absolute;
186
186
  top: 0; left: 0; right: 0; bottom: 0;
187
187
  background: rgba(0, 0, 0, 0);
188
- transition: background var(--drawer-transition-duration, 0.3s) ease;
188
+ transition: background var(--component-drawer-transition-duration, 0.3s) ease;
189
189
  }
190
190
  .overlay.open {
191
191
  background: rgba(0, 0, 0, 0.4);
@@ -202,14 +202,14 @@ class YumeDrawer extends HTMLElement {
202
202
  flex-direction: column;
203
203
  border: none;
204
204
  border-radius: var(--component-drawer-border-radius, 0);
205
- transition: transform var(--drawer-transition-duration, 0.3s) ease;
205
+ transition: transform var(--component-drawer-transition-duration, 0.3s) ease;
206
206
  }
207
207
 
208
208
  .drawer-panel[data-position="left"],
209
209
  .drawer-panel[data-position="right"] {
210
210
  top: 0;
211
211
  bottom: 0;
212
- width: var(--drawer-width, 300px);
212
+ width: var(--component-drawer-width, 300px);
213
213
  flex-direction: row;
214
214
  }
215
215
  .drawer-panel[data-position="left"] {
@@ -227,7 +227,7 @@ class YumeDrawer extends HTMLElement {
227
227
  .drawer-panel[data-position="bottom"] {
228
228
  left: 0;
229
229
  right: 0;
230
- height: var(--drawer-height, 300px);
230
+ height: var(--component-drawer-height, 300px);
231
231
  }
232
232
  .drawer-panel[data-position="top"] {
233
233
  top: 0;
@@ -268,6 +268,14 @@ export class YumeDroplist extends HTMLElement {
268
268
  _findListForElement(el: any): any;
269
269
  _findSwapTarget(e: any): Element;
270
270
  _flip(snapshot: any): void;
271
+ /**
272
+ * Pick the element to mount drag-time overlays (preview, float ghost) into.
273
+ * Prefer the nearest `<y-theme>` ancestor so the overlay inherits the theme's
274
+ * CSS custom properties — `y-theme` sets them as inline styles on its host,
275
+ * so they only cascade to descendants. Falls back to `document.body` when no
276
+ * `<y-theme>` is in scope.
277
+ */
278
+ _getOverlayHost(): any;
271
279
  /**
272
280
  * Returns the zero-based index at which the ghost is currently projected
273
281
  * to be inserted (counting only non-ghost children before the ghost).
@@ -268,6 +268,14 @@ export class YumeDroplist extends HTMLElement {
268
268
  _findListForElement(el: any): any;
269
269
  _findSwapTarget(e: any): Element;
270
270
  _flip(snapshot: any): void;
271
+ /**
272
+ * Pick the element to mount drag-time overlays (preview, float ghost) into.
273
+ * Prefer the nearest `<y-theme>` ancestor so the overlay inherits the theme's
274
+ * CSS custom properties — `y-theme` sets them as inline styles on its host,
275
+ * so they only cascade to descendants. Falls back to `document.body` when no
276
+ * `<y-theme>` is in scope.
277
+ */
278
+ _getOverlayHost(): any;
271
279
  /**
272
280
  * Returns the zero-based index at which the ghost is currently projected
273
281
  * to be inserted (counting only non-ghost children before the ghost).
@@ -919,7 +919,7 @@ class YumeDroplist extends HTMLElement {
919
919
  return;
920
920
  }
921
921
 
922
- document.body.appendChild(preview);
922
+ this._getOverlayHost().appendChild(preview);
923
923
  this._dragPreview = preview;
924
924
  _previewOwner = this;
925
925
 
@@ -1192,6 +1192,20 @@ class YumeDroplist extends HTMLElement {
1192
1192
  }
1193
1193
  }
1194
1194
 
1195
+ /**
1196
+ * Pick the element to mount drag-time overlays (preview, float ghost) into.
1197
+ * Prefer the nearest `<y-theme>` ancestor so the overlay inherits the theme's
1198
+ * CSS custom properties — `y-theme` sets them as inline styles on its host,
1199
+ * so they only cascade to descendants. Falls back to `document.body` when no
1200
+ * `<y-theme>` is in scope.
1201
+ */
1202
+ _getOverlayHost() {
1203
+ // `this.closest()` is overridden as a public coordinate-lookup API on
1204
+ // y-droplist, so reach for the native traversal via the prototype.
1205
+ const theme = Element.prototype.closest.call(this, "y-theme");
1206
+ return theme || document.body;
1207
+ }
1208
+
1195
1209
  /**
1196
1210
  * Returns the zero-based index at which the ghost is currently projected
1197
1211
  * to be inserted (counting only non-ghost children before the ghost).
@@ -1728,7 +1742,7 @@ class YumeDroplist extends HTMLElement {
1728
1742
  this._positionFloatGhost(reference);
1729
1743
 
1730
1744
  if (!this._ghost.parentNode) {
1731
- document.body.appendChild(this._ghost);
1745
+ this._getOverlayHost().appendChild(this._ghost);
1732
1746
  }
1733
1747
  } else {
1734
1748
  if (
@@ -531,8 +531,11 @@ class YumeGallery extends HTMLElement {
531
531
  });
532
532
  if (!this.dispatchEvent(event)) return;
533
533
 
534
- const item_el = this.shadowRoot.querySelector(`.item[data-index="${index}"]`);
535
- this._previouslyFocused = item_el?.querySelector(".item-btn") || item_el;
534
+ const item_el = this.shadowRoot.querySelector(
535
+ `.item[data-index="${index}"]`,
536
+ );
537
+ this._previouslyFocused =
538
+ item_el?.querySelector(".item-btn") || item_el;
536
539
  this._expandedIndex = index;
537
540
  this._showExpandedView();
538
541
  document.addEventListener("keydown", this._onKeyDown);
@@ -753,7 +756,7 @@ class YumeGallery extends HTMLElement {
753
756
  const closeBtn = this._createNavButton(
754
757
  "expand-close",
755
758
  "Close image viewer",
756
- "close",
759
+ "x",
757
760
  "expand-close-icon",
758
761
  );
759
762
  const prevBtn = this._createNavButton(
@@ -811,7 +814,7 @@ class YumeGallery extends HTMLElement {
811
814
  content: "";
812
815
  position: absolute;
813
816
  inset: 0;
814
- background: var(--component-gallery-thumbnail-overlay-color, var(--neutral-black-translucent, rgba(0,0,0,0.12)));
817
+ background: var(--component-gallery-thumbnail-overlay-color, rgba(0, 0, 0, 0.12));
815
818
  opacity: 0;
816
819
  transition: opacity 0.2s ease;
817
820
  pointer-events: none;
@@ -941,14 +944,28 @@ class YumeGallery extends HTMLElement {
941
944
  }
942
945
 
943
946
  _createItemWrapper(data, index) {
944
- const attrs = { class: "item", part: "item", role: "listitem", "data-index": String(index) };
945
- const img = createElement("img", { src: data.src, alt: data.alt, part: "item-img", draggable: "false" });
947
+ const attrs = {
948
+ class: "item",
949
+ part: "item",
950
+ role: "listitem",
951
+ "data-index": String(index),
952
+ };
953
+ const img = createElement("img", {
954
+ src: data.src,
955
+ alt: data.alt,
956
+ part: "item-img",
957
+ draggable: "false",
958
+ });
946
959
 
947
960
  if (this.expandable) {
948
- const btn = createElement("button", {
949
- class: "item-btn",
950
- "aria-label": `View image: ${data.alt || `Image ${index + 1}`}`,
951
- }, [img]);
961
+ const btn = createElement(
962
+ "button",
963
+ {
964
+ class: "item-btn",
965
+ "aria-label": `View image: ${data.alt || `Image ${index + 1}`}`,
966
+ },
967
+ [img],
968
+ );
952
969
  btn.addEventListener("click", () => this.open(index));
953
970
  return createElement("div", attrs, [btn]);
954
971
  }
@@ -1020,7 +1037,9 @@ class YumeGallery extends HTMLElement {
1020
1037
  if (!data) return;
1021
1038
 
1022
1039
  this._items.push(data);
1023
- gallery.appendChild(this._createItemWrapper(data, this._items.length - 1));
1040
+ gallery.appendChild(
1041
+ this._createItemWrapper(data, this._items.length - 1),
1042
+ );
1024
1043
  });
1025
1044
  }
1026
1045
 
@@ -1060,7 +1079,11 @@ class YumeGallery extends HTMLElement {
1060
1079
 
1061
1080
  if (gapMap[gap]) return gapMap[gap];
1062
1081
 
1063
- if (typeof CSS !== "undefined" && CSS.supports && CSS.supports("gap", gap)) {
1082
+ if (
1083
+ typeof CSS !== "undefined" &&
1084
+ CSS.supports &&
1085
+ CSS.supports("gap", gap)
1086
+ ) {
1064
1087
  return gap;
1065
1088
  }
1066
1089
 
@@ -313,6 +313,7 @@ class YumeProgress extends HTMLElement {
313
313
  }
314
314
  set values(val) {
315
315
  if (val === null || val === undefined) this.removeAttribute("values");
316
+ else if (typeof val === "string") this.setAttribute("values", val);
316
317
  else this.setAttribute("values", JSON.stringify(val));
317
318
  }
318
319