@rogieking/figui3 6.31.1 → 6.32.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.
package/fig.js CHANGED
@@ -13440,8 +13440,8 @@ figDefineElement("fig-video", FigVideo);
13440
13440
  /**
13441
13441
  * <fig-card> — Media card with optional link, selection chrome, and truncated label.
13442
13442
  *
13443
- * Composes a generated `fig-image` when `src` is set. Without `src`, authored
13444
- * children remain direct children and generated label content is appended.
13443
+ * Composes a generated `fig-image` when `src` is set. Attribute-driven labels
13444
+ * render in a generated `fig-footer`; authored footers remain untouched.
13445
13445
  * Selection is attribute-only (`selected`); apps own toggle/group logic.
13446
13446
  * When `href` is set (and not disabled), content wraps in a real `<a>`.
13447
13447
  *
@@ -13481,7 +13481,7 @@ class FigCard extends HTMLElement {
13481
13481
  }
13482
13482
 
13483
13483
  #linkEl = null;
13484
- #textWrap = null;
13484
+ #footerEl = null;
13485
13485
  #imageEl = null;
13486
13486
  #labelEl = null;
13487
13487
  #sublabelEl = null;
@@ -13492,10 +13492,10 @@ class FigCard extends HTMLElement {
13492
13492
  (node) =>
13493
13493
  node instanceof Element &&
13494
13494
  (node.matches(
13495
- "fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated])",
13495
+ "fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated]), fig-footer:not([data-generated])",
13496
13496
  ) ||
13497
13497
  node.querySelector(
13498
- "fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated])",
13498
+ "fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated]), fig-footer:not([data-generated])",
13499
13499
  )),
13500
13500
  ),
13501
13501
  );
@@ -13554,10 +13554,10 @@ class FigCard extends HTMLElement {
13554
13554
  return;
13555
13555
  }
13556
13556
 
13557
- this.querySelectorAll(":scope > .fig-card-text[data-generated]").forEach(
13557
+ this.querySelectorAll(":scope > fig-footer[data-generated]").forEach(
13558
13558
  (element) => element.remove(),
13559
13559
  );
13560
- if (this.#textWrap?.parentElement === this) this.#textWrap = null;
13560
+ if (this.#footerEl?.parentElement === this) this.#footerEl = null;
13561
13561
 
13562
13562
  const authored = this.#findAuthoredMedia();
13563
13563
  this.#usesAuthoredMedia = Boolean(authored);
@@ -13591,7 +13591,7 @@ class FigCard extends HTMLElement {
13591
13591
 
13592
13592
  if (authored && authored.parentElement !== this.#linkEl) {
13593
13593
  this.#linkEl
13594
- .querySelectorAll(":scope > [data-generated]:not(.fig-card-text)")
13594
+ .querySelectorAll(":scope > [data-generated]:not(fig-footer)")
13595
13595
  .forEach((el) => el.remove());
13596
13596
  this.#linkEl.prepend(authored);
13597
13597
  this.#imageEl = null;
@@ -13617,32 +13617,32 @@ class FigCard extends HTMLElement {
13617
13617
  }
13618
13618
  }
13619
13619
 
13620
- if (!this.#textWrap || !this.#textWrap.isConnected) {
13621
- this.#textWrap = this.#linkEl.querySelector(":scope > .fig-card-text");
13622
- if (this.#textWrap?.tagName.toLowerCase() !== "div") {
13623
- const text = document.createElement("div");
13624
- text.className = "fig-card-text";
13625
- text.setAttribute("data-generated", "");
13626
- if (this.#textWrap) {
13627
- while (this.#textWrap.firstChild) {
13628
- text.appendChild(this.#textWrap.firstChild);
13629
- }
13630
- this.#textWrap.replaceWith(text);
13631
- } else {
13632
- this.#linkEl.appendChild(text);
13633
- }
13634
- this.#textWrap = text;
13635
- }
13636
- if (!this.#textWrap) {
13637
- this.#textWrap = document.createElement("div");
13638
- this.#textWrap.className = "fig-card-text";
13639
- this.#textWrap.setAttribute("data-generated", "");
13640
- this.#linkEl.appendChild(this.#textWrap);
13620
+ const hasGeneratedLabels = Boolean(
13621
+ this.#labelText() || this.#sublabelText(),
13622
+ );
13623
+ if (!hasGeneratedLabels) {
13624
+ this.#linkEl
13625
+ .querySelector(":scope > fig-footer[data-generated]")
13626
+ ?.remove();
13627
+ this.#footerEl = null;
13628
+ this.#labelEl = null;
13629
+ this.#sublabelEl = null;
13630
+ return;
13631
+ }
13632
+
13633
+ if (!this.#footerEl || !this.#footerEl.isConnected) {
13634
+ this.#footerEl = this.#linkEl.querySelector(
13635
+ ":scope > fig-footer[data-generated]",
13636
+ );
13637
+ if (!this.#footerEl) {
13638
+ this.#footerEl = document.createElement("fig-footer");
13639
+ this.#footerEl.setAttribute("data-generated", "");
13640
+ this.#linkEl.appendChild(this.#footerEl);
13641
13641
  }
13642
13642
  }
13643
13643
 
13644
13644
  if (!this.#labelEl || !this.#labelEl.isConnected) {
13645
- this.#labelEl = this.#textWrap.querySelector(
13645
+ this.#labelEl = this.#footerEl.querySelector(
13646
13646
  ":scope > .fig-card-label[data-generated]",
13647
13647
  );
13648
13648
  if (!this.#labelEl) {
@@ -13654,12 +13654,12 @@ class FigCard extends HTMLElement {
13654
13654
  this.#labelEl.className = "fig-card-label";
13655
13655
  this.#labelEl.setAttribute("data-generated", "");
13656
13656
  }
13657
- this.#textWrap.appendChild(this.#labelEl);
13657
+ this.#footerEl.appendChild(this.#labelEl);
13658
13658
  }
13659
13659
  }
13660
13660
 
13661
13661
  if (!this.#sublabelEl || !this.#sublabelEl.isConnected) {
13662
- this.#sublabelEl = this.#textWrap.querySelector(
13662
+ this.#sublabelEl = this.#footerEl.querySelector(
13663
13663
  ":scope > .fig-card-sublabel[data-generated]",
13664
13664
  );
13665
13665
  if (!this.#sublabelEl) {
@@ -13683,9 +13683,9 @@ class FigCard extends HTMLElement {
13683
13683
  if (staleLink) {
13684
13684
  staleLink
13685
13685
  .querySelectorAll(
13686
- "fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated])",
13686
+ "fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated]), fig-footer:not([data-generated])",
13687
13687
  )
13688
- .forEach((media) => this.insertBefore(media, staleLink));
13688
+ .forEach((element) => this.insertBefore(element, staleLink));
13689
13689
  staleLink.remove();
13690
13690
  }
13691
13691
  this.querySelectorAll(":scope > [data-generated]").forEach((element) =>
@@ -13696,13 +13696,18 @@ class FigCard extends HTMLElement {
13696
13696
  this.#imageEl = null;
13697
13697
  this.#usesAuthoredMedia = true;
13698
13698
 
13699
- this.#textWrap = document.createElement("div");
13700
- this.#textWrap.className = "fig-card-text";
13701
- this.#textWrap.setAttribute("data-generated", "");
13699
+ this.#footerEl = null;
13700
+ this.#labelEl = null;
13701
+ this.#sublabelEl = null;
13702
+
13703
+ if (!this.#labelText() && !this.#sublabelText()) return;
13704
+
13705
+ this.#footerEl = document.createElement("fig-footer");
13706
+ this.#footerEl.setAttribute("data-generated", "");
13702
13707
  this.#labelEl = document.createElement("label");
13703
13708
  this.#labelEl.className = "fig-card-label";
13704
13709
  this.#labelEl.setAttribute("data-generated", "");
13705
- this.#textWrap.appendChild(this.#labelEl);
13710
+ this.#footerEl.appendChild(this.#labelEl);
13706
13711
 
13707
13712
  const sublabel = this.#sublabelText();
13708
13713
  this.#sublabelEl = null;
@@ -13710,9 +13715,9 @@ class FigCard extends HTMLElement {
13710
13715
  this.#sublabelEl = document.createElement("label");
13711
13716
  this.#sublabelEl.className = "fig-card-sublabel";
13712
13717
  this.#sublabelEl.setAttribute("data-generated", "");
13713
- this.#textWrap.appendChild(this.#sublabelEl);
13718
+ this.#footerEl.appendChild(this.#sublabelEl);
13714
13719
  }
13715
- this.appendChild(this.#textWrap);
13720
+ this.appendChild(this.#footerEl);
13716
13721
  }
13717
13722
 
13718
13723
  #sync() {
@@ -13798,8 +13803,8 @@ class FigCard extends HTMLElement {
13798
13803
  this.#sublabelEl.hidden = !sublabel;
13799
13804
  }
13800
13805
 
13801
- if (this.#textWrap) {
13802
- this.#textWrap.hidden = !label && !sublabel;
13806
+ if (this.#footerEl) {
13807
+ this.#footerEl.hidden = !label && !sublabel;
13803
13808
  }
13804
13809
  }
13805
13810
 
@@ -17084,19 +17089,22 @@ figDefineElement("fig-spinner", FigSpinner);
17084
17089
  * A styled visual preview layer for arbitrary content such as images, canvas,
17085
17090
  * video, SVG, or custom rendered surfaces.
17086
17091
  * @attr {string} fit - CSS object-fit value for direct media children
17092
+ * @attr {string} aspect-ratio - CSS aspect-ratio value
17087
17093
  */
17088
17094
  class FigPreview extends HTMLElement {
17089
17095
  static get observedAttributes() {
17090
- return ["fit"];
17096
+ return ["fit", "aspect-ratio"];
17091
17097
  }
17092
17098
 
17093
17099
  connectedCallback() {
17094
17100
  this.#syncFit();
17101
+ this.#syncAspectRatio();
17095
17102
  }
17096
17103
 
17097
17104
  attributeChangedCallback(name, oldValue, newValue) {
17098
17105
  if (oldValue === newValue) return;
17099
17106
  if (name === "fit") this.#syncFit();
17107
+ if (name === "aspect-ratio") this.#syncAspectRatio();
17100
17108
  }
17101
17109
 
17102
17110
  #syncFit() {
@@ -17107,6 +17115,15 @@ class FigPreview extends HTMLElement {
17107
17115
  this.style.removeProperty("--fig-preview-fit");
17108
17116
  }
17109
17117
  }
17118
+
17119
+ #syncAspectRatio() {
17120
+ const aspectRatio = this.getAttribute("aspect-ratio");
17121
+ if (aspectRatio) {
17122
+ this.style.setProperty("--fig-preview-aspect-ratio", aspectRatio);
17123
+ } else {
17124
+ this.style.removeProperty("--fig-preview-aspect-ratio");
17125
+ }
17126
+ }
17110
17127
  }
17111
17128
  figDefineElement("fig-preview", FigPreview);
17112
17129
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "6.31.1",
3
+ "version": "6.32.0",
4
4
  "description": "A lightweight web components library for building Figma plugin and widget UIs with native look and feel",
5
5
  "author": "Rogie King",
6
6
  "license": "MIT",