@rogieking/figui3 9.1.6 → 9.2.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.
package/fig.js CHANGED
@@ -607,7 +607,15 @@ class FigButton extends HTMLElement {
607
607
  type;
608
608
  #selected;
609
609
  #slottedDisabledStates = new WeakMap();
610
- #a11yAttributes = ["aria-label", "aria-labelledby", "aria-describedby", "title"];
610
+ #a11yAttributes = [
611
+ "aria-label",
612
+ "aria-labelledby",
613
+ "aria-describedby",
614
+ "aria-haspopup",
615
+ "aria-expanded",
616
+ "aria-controls",
617
+ "title",
618
+ ];
611
619
  #boundHandleControlKeydown = this.#handleControlKeydown.bind(this);
612
620
  #boundHandleClick = this.#handleClick.bind(this);
613
621
  #boundHandleSlotChange = () => {
@@ -867,6 +875,9 @@ class FigButton extends HTMLElement {
867
875
  "aria-label",
868
876
  "aria-labelledby",
869
877
  "aria-describedby",
878
+ "aria-haspopup",
879
+ "aria-expanded",
880
+ "aria-controls",
870
881
  "title",
871
882
  ];
872
883
  }
@@ -905,6 +916,96 @@ class FigButton extends HTMLElement {
905
916
  }
906
917
  figDefineElement("fig-button", FigButton);
907
918
 
919
+ /**
920
+ * A full-width secondary button for opening a property editor or flyout.
921
+ * @attr {string} icon - Required fig-icon name shown before the button label.
922
+ * @attr {boolean} disabled - Whether the trigger is disabled.
923
+ */
924
+ class FigPropertyButton extends FigButton {
925
+ #syncingContract = false;
926
+
927
+ static get observedAttributes() {
928
+ return [
929
+ ...super.observedAttributes,
930
+ "icon",
931
+ "variant",
932
+ "full",
933
+ "align",
934
+ ];
935
+ }
936
+
937
+ connectedCallback() {
938
+ this.#enforceContract();
939
+ super.connectedCallback();
940
+ this.#syncIcon();
941
+ }
942
+
943
+ get icon() {
944
+ return this.getAttribute("icon") || "";
945
+ }
946
+
947
+ set icon(value) {
948
+ if (value === null || value === undefined || value === "") {
949
+ this.removeAttribute("icon");
950
+ } else {
951
+ this.setAttribute("icon", String(value));
952
+ }
953
+ }
954
+
955
+ #enforceContract() {
956
+ if (this.#syncingContract) return;
957
+ this.#syncingContract = true;
958
+ if (this.getAttribute("variant") !== "secondary") {
959
+ this.setAttribute("variant", "secondary");
960
+ }
961
+ if (!this.hasAttribute("full") || this.getAttribute("full") === "false") {
962
+ this.setAttribute("full", "");
963
+ }
964
+ if (this.getAttribute("align") !== "start") {
965
+ this.setAttribute("align", "start");
966
+ }
967
+ this.#syncingContract = false;
968
+ }
969
+
970
+ #syncIcon() {
971
+ const generated = Array.from(
972
+ this.querySelectorAll(
973
+ ':scope > fig-icon[slot="prepend"][data-generated="property-button-icon"]',
974
+ ),
975
+ );
976
+ const iconName = this.icon.trim();
977
+ if (!iconName) {
978
+ generated.forEach((icon) => icon.remove());
979
+ return;
980
+ }
981
+
982
+ let icon = generated.shift();
983
+ generated.forEach((duplicate) => duplicate.remove());
984
+ if (!icon) {
985
+ icon = createFigIcon(iconName);
986
+ icon.setAttribute("slot", "prepend");
987
+ icon.setAttribute("data-generated", "property-button-icon");
988
+ this.prepend(icon);
989
+ } else if (icon.getAttribute("name") !== iconName) {
990
+ icon.setAttribute("name", iconName);
991
+ }
992
+ }
993
+
994
+ attributeChangedCallback(name, oldValue, newValue) {
995
+ if (oldValue === newValue) return;
996
+ if (name === "icon") {
997
+ this.#syncIcon();
998
+ return;
999
+ }
1000
+ if (name === "variant" || name === "full" || name === "align") {
1001
+ this.#enforceContract();
1002
+ return;
1003
+ }
1004
+ super.attributeChangedCallback(name, oldValue, newValue);
1005
+ }
1006
+ }
1007
+ figDefineElement("fig-property-button", FigPropertyButton);
1008
+
908
1009
  /**
909
1010
  * A custom dropdown/select element.
910
1011
  * @attr {string} type - The dropdown type: "select" (default) or "dropdown"
@@ -18446,6 +18547,59 @@ figDefineElement("fig-button-combo", FigButtonCombo);
18446
18547
  class FigInputCombo extends HTMLElement {}
18447
18548
  figDefineElement("fig-input-combo", FigInputCombo);
18448
18549
 
18550
+ /**
18551
+ * A layout primitive for horizontal, vertical, and grid stacks.
18552
+ * @element fig-stack
18553
+ * @attr {string} direction - "horizontal" (default), "vertical", or "grid"
18554
+ * @attr {string} gap - Spacer token ("0"–"6", "2-5", "half" → var(--spacer-*)) or any CSS length
18555
+ * @attr {string} align - Cross-axis alignment: "start", "center", "end", "stretch", "baseline"
18556
+ * @attr {string} justify - Main-axis alignment: "start", "center", "end", "between", "around", "stretch"
18557
+ * @attr {boolean} wrap - Wrap items onto multiple lines (flex directions only)
18558
+ * @attr {boolean} full - Fill the parent's width
18559
+ * @attr {string} columns - Grid only: column count (e.g. "3") or a grid-template-columns value
18560
+ * @attr {string} min-width - Grid only: minimum auto-fill column width (default 5rem)
18561
+ */
18562
+ class FigStack extends HTMLElement {
18563
+ static get observedAttributes() {
18564
+ return ["gap", "columns", "min-width"];
18565
+ }
18566
+
18567
+ connectedCallback() {
18568
+ this.#syncStyles();
18569
+ }
18570
+
18571
+ attributeChangedCallback() {
18572
+ this.#syncStyles();
18573
+ }
18574
+
18575
+ #syncStyles() {
18576
+ const gap = this.getAttribute("gap")?.trim();
18577
+ this.#setProperty(
18578
+ "--fig-stack-gap",
18579
+ gap && /^(\d+(-5)?|half)$/.test(gap) ? `var(--spacer-${gap})` : gap,
18580
+ );
18581
+
18582
+ const columns = this.getAttribute("columns")?.trim();
18583
+ this.#setProperty(
18584
+ "--fig-stack-columns",
18585
+ columns && /^\d+$/.test(columns)
18586
+ ? `repeat(${columns}, minmax(0, 1fr))`
18587
+ : columns,
18588
+ );
18589
+
18590
+ this.#setProperty(
18591
+ "--fig-stack-min-width",
18592
+ this.getAttribute("min-width")?.trim(),
18593
+ );
18594
+ }
18595
+
18596
+ #setProperty(name, value) {
18597
+ if (value) this.style.setProperty(name, value);
18598
+ else this.style.removeProperty(name);
18599
+ }
18600
+ }
18601
+ figDefineElement("fig-stack", FigStack);
18602
+
18449
18603
 
18450
18604
 
18451
18605
  /* Color Tip */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "9.1.6",
3
+ "version": "9.2.1",
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": "SEE LICENSE IN LICENSE",