@rogieking/figui3 8.9.28 → 8.9.29

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
@@ -600,7 +600,10 @@ class FigButton extends HTMLElement {
600
600
  #a11yAttributes = ["aria-label", "aria-labelledby", "aria-describedby", "title"];
601
601
  #boundHandleControlKeydown = this.#handleControlKeydown.bind(this);
602
602
  #boundHandleClick = this.#handleClick.bind(this);
603
- #boundHandleSlotChange = () => this.#syncSlottedControlDisabled();
603
+ #boundHandleSlotChange = () => {
604
+ this.#syncSlottedControlDisabled();
605
+ this.#syncSelectChevron();
606
+ };
604
607
  #boundHandleFocus = () => {
605
608
  if (this.button?.matches(":focus-visible")) {
606
609
  this.setAttribute("data-focus-visible", "");
@@ -653,14 +656,22 @@ class FigButton extends HTMLElement {
653
656
  :host([size="large"][icon]) .fig-button-control {
654
657
  padding: 0;
655
658
  }
659
+ :host([type="select"]) .fig-button-control {
660
+ gap: var(--spacer-1);
661
+ }
656
662
  `;
663
+ const prependSlot = document.createElement("slot");
664
+ prependSlot.name = "prepend";
665
+ const defaultSlot = document.createElement("slot");
666
+ const appendSlot = document.createElement("slot");
667
+ appendSlot.name = "append";
657
668
  const control = figCreateElement(
658
669
  controlTag,
659
670
  {
660
671
  className: "fig-button-control",
661
672
  type: isControlWrapper ? null : "button",
662
673
  },
663
- document.createElement("slot"),
674
+ [prependSlot, defaultSlot, appendSlot],
664
675
  );
665
676
  this.shadowRoot.replaceChildren(style, control);
666
677
 
@@ -670,9 +681,10 @@ class FigButton extends HTMLElement {
670
681
  this.button.addEventListener("blur", this.#boundHandleBlur);
671
682
  }
672
683
 
673
- const slot = this.shadowRoot.querySelector("slot");
674
- slot?.removeEventListener("slotchange", this.#boundHandleSlotChange);
675
- slot?.addEventListener("slotchange", this.#boundHandleSlotChange);
684
+ this.shadowRoot.querySelectorAll("slot").forEach((slot) => {
685
+ slot.removeEventListener("slotchange", this.#boundHandleSlotChange);
686
+ slot.addEventListener("slotchange", this.#boundHandleSlotChange);
687
+ });
676
688
  this.removeEventListener("keydown", this.#boundHandleControlKeydown);
677
689
  this.addEventListener("keydown", this.#boundHandleControlKeydown);
678
690
 
@@ -681,6 +693,7 @@ class FigButton extends HTMLElement {
681
693
  this.getAttribute("selected") !== "false";
682
694
 
683
695
  this.#syncButtonAttributes();
696
+ this.#syncSelectChevron();
684
697
  }
685
698
 
686
699
  get type() {
@@ -767,6 +780,29 @@ class FigButton extends HTMLElement {
767
780
  this.setAttribute("aria-pressed", pressed ? "true" : "false");
768
781
  this.button.setAttribute("aria-pressed", pressed ? "true" : "false");
769
782
  }
783
+ #syncSelectChevron() {
784
+ const selector =
785
+ ':scope > fig-icon[slot="append"][data-generated="select-chevron"]';
786
+ const generatedIcons = Array.from(this.querySelectorAll(selector));
787
+ const generated = generatedIcons[0];
788
+ generatedIcons.slice(1).forEach((icon) => icon.remove());
789
+ if (this.type !== "select") {
790
+ generated?.remove();
791
+ return;
792
+ }
793
+ const authoredAppend = this.querySelector(
794
+ ':scope > [slot="append"]:not([data-generated])',
795
+ );
796
+ if (authoredAppend) {
797
+ generated?.remove();
798
+ return;
799
+ }
800
+ if (generated) return;
801
+ const chevron = createFigIcon("chevron", { size: "small" });
802
+ chevron.setAttribute("slot", "append");
803
+ chevron.setAttribute("data-generated", "select-chevron");
804
+ this.append(chevron);
805
+ }
770
806
  #syncA11yAttributes() {
771
807
  if (!this.button) return;
772
808
  if (!(this.button instanceof HTMLButtonElement)) return;
@@ -835,6 +871,7 @@ class FigButton extends HTMLElement {
835
871
  break;
836
872
  }
837
873
  this.#syncButtonAttributes();
874
+ this.#syncSelectChevron();
838
875
  break;
839
876
  }
840
877
  case "disabled":
@@ -851,9 +888,9 @@ class FigButton extends HTMLElement {
851
888
  }
852
889
  disconnectedCallback() {
853
890
  this.removeEventListener("keydown", this.#boundHandleControlKeydown);
854
- this.shadowRoot
855
- ?.querySelector("slot")
856
- ?.removeEventListener("slotchange", this.#boundHandleSlotChange);
891
+ this.shadowRoot?.querySelectorAll("slot").forEach((slot) => {
892
+ slot.removeEventListener("slotchange", this.#boundHandleSlotChange);
893
+ });
857
894
  }
858
895
  }
859
896
  figDefineElement("fig-button", FigButton);
@@ -11673,6 +11710,7 @@ class FigComboInput extends HTMLElement {
11673
11710
  ];
11674
11711
 
11675
11712
  #boundHandleDropdownInput = this.#handleDropdownInput.bind(this);
11713
+ #boundHandleDropdownChange = this.#handleDropdownChange.bind(this);
11676
11714
  #boundHandleTextInput = this.#handleTextInput.bind(this);
11677
11715
  #boundHandleTextChange = this.#handleTextChange.bind(this);
11678
11716
 
@@ -11737,21 +11775,6 @@ class FigComboInput extends HTMLElement {
11737
11775
  placeholder,
11738
11776
  value: currentValue,
11739
11777
  });
11740
- const icon = figCreateSvgElement(
11741
- "svg",
11742
- {
11743
- width: "16",
11744
- height: "16",
11745
- viewBox: "0 0 16 16",
11746
- fill: "none",
11747
- },
11748
- figCreateSvgElement("path", {
11749
- d: "M5.87868 7.12132L8 9.24264L10.1213 7.12132",
11750
- stroke: "currentColor",
11751
- "stroke-opacity": "0.9",
11752
- "stroke-linecap": "round",
11753
- }),
11754
- );
11755
11778
  const button = figCreateElement(
11756
11779
  "fig-button",
11757
11780
  {
@@ -11759,7 +11782,6 @@ class FigComboInput extends HTMLElement {
11759
11782
  variant: "input",
11760
11783
  icon: true,
11761
11784
  },
11762
- icon,
11763
11785
  );
11764
11786
  if (!this.#usesCustomDropdown) {
11765
11787
  button.appendChild(
@@ -11799,25 +11821,36 @@ class FigComboInput extends HTMLElement {
11799
11821
  #setupListeners() {
11800
11822
  this.#teardownListeners();
11801
11823
  this.#dropdown?.addEventListener("input", this.#boundHandleDropdownInput);
11824
+ this.#dropdown?.addEventListener("change", this.#boundHandleDropdownChange);
11802
11825
  this.#input?.addEventListener("input", this.#boundHandleTextInput);
11803
11826
  this.#input?.addEventListener("change", this.#boundHandleTextChange);
11804
11827
  }
11805
11828
 
11806
11829
  #teardownListeners() {
11807
11830
  this.#dropdown?.removeEventListener("input", this.#boundHandleDropdownInput);
11831
+ this.#dropdown?.removeEventListener("change", this.#boundHandleDropdownChange);
11808
11832
  this.#input?.removeEventListener("input", this.#boundHandleTextInput);
11809
11833
  this.#input?.removeEventListener("change", this.#boundHandleTextChange);
11810
11834
  }
11811
11835
 
11812
11836
  #handleDropdownInput(e) {
11813
11837
  e.stopPropagation();
11838
+ this.#syncDropdownValue(e);
11839
+ this.#emitInput();
11840
+ }
11841
+
11842
+ #handleDropdownChange(e) {
11843
+ e.stopPropagation();
11844
+ this.#syncDropdownValue(e);
11845
+ this.#emitChange();
11846
+ }
11847
+
11848
+ #syncDropdownValue(e) {
11814
11849
  const val = e.target.closest("fig-dropdown")?.value ?? "";
11815
11850
  this.#internalUpdate = true;
11816
11851
  this.setAttribute("value", val);
11817
11852
  this.#internalUpdate = false;
11818
11853
  if (this.#input) this.#input.setAttribute("value", val);
11819
- this.#emitInput();
11820
- this.#emitChange();
11821
11854
  }
11822
11855
 
11823
11856
  #handleTextInput(e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "8.9.28",
3
+ "version": "8.9.29",
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",