@rogieking/figui3 11.6.5 → 11.6.7

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
@@ -942,6 +942,13 @@ class FigDropdown extends HTMLElement {
942
942
  #boundHandleSelectInput;
943
943
  #boundHandleSelectChange;
944
944
  #boundHandleSelectKeydown;
945
+ #boundHandleSelectPointerDown;
946
+ #boundHandleSelectBlur;
947
+ #openButton = null;
948
+ #openButtonWasSelected = false;
949
+ #openSelectWasSelected = false;
950
+ #openStateActive = false;
951
+ #openStateFrame = 0;
945
952
 
946
953
  get label() {
947
954
  return this.#label;
@@ -958,6 +965,9 @@ class FigDropdown extends HTMLElement {
958
965
  this.#boundHandleSelectInput = this.#handleSelectInput.bind(this);
959
966
  this.#boundHandleSelectChange = this.#handleSelectChange.bind(this);
960
967
  this.#boundHandleSelectKeydown = this.#handleSelectKeydown.bind(this);
968
+ this.#boundHandleSelectPointerDown =
969
+ this.#handleSelectPointerDown.bind(this);
970
+ this.#boundHandleSelectBlur = this.#clearOpenState.bind(this);
961
971
  this.#boundSlotChange = this.slotChange.bind(this);
962
972
  }
963
973
 
@@ -965,6 +975,87 @@ class FigDropdown extends HTMLElement {
965
975
  this.select.addEventListener("input", this.#boundHandleSelectInput);
966
976
  this.select.addEventListener("change", this.#boundHandleSelectChange);
967
977
  this.select.addEventListener("keydown", this.#boundHandleSelectKeydown);
978
+ this.select.addEventListener(
979
+ "pointerdown",
980
+ this.#boundHandleSelectPointerDown,
981
+ );
982
+ this.select.addEventListener("blur", this.#boundHandleSelectBlur);
983
+ }
984
+
985
+ #markOpenState() {
986
+ const button = this.closest('fig-button[type="select"]');
987
+ if (this.#openStateActive && this.#openButton !== button) {
988
+ this.#clearOpenState();
989
+ }
990
+ if (!this.#openStateActive) {
991
+ this.#openSelectWasSelected =
992
+ this.select.hasAttribute("selected") &&
993
+ this.select.getAttribute("selected") !== "false";
994
+ this.#openStateActive = true;
995
+ }
996
+ this.select.setAttribute("selected", "");
997
+ if (!button) return;
998
+ if (this.#openButton !== button) {
999
+ this.#openButton = button;
1000
+ this.#openButtonWasSelected =
1001
+ button.hasAttribute("selected") &&
1002
+ button.getAttribute("selected") !== "false";
1003
+ }
1004
+ button.setAttribute("selected", "");
1005
+ }
1006
+
1007
+ #clearOpenState() {
1008
+ if (this.#openStateFrame) {
1009
+ cancelAnimationFrame(this.#openStateFrame);
1010
+ this.#openStateFrame = 0;
1011
+ }
1012
+ if (this.#openButton && !this.#openButtonWasSelected) {
1013
+ this.#openButton.removeAttribute("selected");
1014
+ }
1015
+ if (this.#openStateActive && !this.#openSelectWasSelected) {
1016
+ this.select.removeAttribute("selected");
1017
+ }
1018
+ this.#openButton = null;
1019
+ this.#openButtonWasSelected = false;
1020
+ this.#openSelectWasSelected = false;
1021
+ this.#openStateActive = false;
1022
+ }
1023
+
1024
+ #watchOpenState() {
1025
+ if (this.#openStateFrame) cancelAnimationFrame(this.#openStateFrame);
1026
+ let attempts = 0;
1027
+ let sawOpen = false;
1028
+ const check = () => {
1029
+ this.#openStateFrame = 0;
1030
+ if (!this.isConnected) {
1031
+ this.#clearOpenState();
1032
+ return;
1033
+ }
1034
+ let open = false;
1035
+ try {
1036
+ open = this.select.matches(":open");
1037
+ } catch {
1038
+ return;
1039
+ }
1040
+ if (open) sawOpen = true;
1041
+ if (sawOpen && !open) {
1042
+ this.#clearOpenState();
1043
+ return;
1044
+ }
1045
+ attempts += 1;
1046
+ if (sawOpen || attempts < 4) {
1047
+ this.#openStateFrame = requestAnimationFrame(check);
1048
+ } else {
1049
+ this.#clearOpenState();
1050
+ }
1051
+ };
1052
+ this.#openStateFrame = requestAnimationFrame(check);
1053
+ }
1054
+
1055
+ #handleSelectPointerDown(e) {
1056
+ if (e.button !== 0 || this.select.disabled) return;
1057
+ this.#markOpenState();
1058
+ this.#watchOpenState();
968
1059
  }
969
1060
 
970
1061
  #hasPersistentControl(optionEl) {
@@ -1081,6 +1172,7 @@ class FigDropdown extends HTMLElement {
1081
1172
  this.#keepPickerOpen();
1082
1173
  return;
1083
1174
  }
1175
+ this.#clearOpenState();
1084
1176
 
1085
1177
  // Get the value before resetting (use stored value for dropdown type)
1086
1178
  const selectedValue =
@@ -1099,16 +1191,19 @@ class FigDropdown extends HTMLElement {
1099
1191
  }
1100
1192
 
1101
1193
  #handleSelectKeydown(e) {
1102
- if (this.closest('fig-button[type="select"]')) return;
1103
1194
  if (e.key !== "Enter" || e.defaultPrevented) return;
1104
1195
  if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
1105
1196
  if (this.select.disabled || this.select.multiple) return;
1197
+ this.#markOpenState();
1198
+ this.#watchOpenState();
1199
+ if (this.closest('fig-button[type="select"]')) return;
1106
1200
  if (typeof this.select.showPicker !== "function") return;
1107
1201
  e.preventDefault();
1108
1202
  try {
1109
1203
  this.select.showPicker();
1110
1204
  } catch {
1111
1205
  // showPicker can be unavailable during non-user-initiated key events.
1206
+ this.#clearOpenState();
1112
1207
  }
1113
1208
  }
1114
1209
 
@@ -1169,6 +1264,12 @@ class FigDropdown extends HTMLElement {
1169
1264
  this.select.removeEventListener("input", this.#boundHandleSelectInput);
1170
1265
  this.select.removeEventListener("change", this.#boundHandleSelectChange);
1171
1266
  this.select.removeEventListener("keydown", this.#boundHandleSelectKeydown);
1267
+ this.select.removeEventListener(
1268
+ "pointerdown",
1269
+ this.#boundHandleSelectPointerDown,
1270
+ );
1271
+ this.select.removeEventListener("blur", this.#boundHandleSelectBlur);
1272
+ this.#clearOpenState();
1172
1273
  }
1173
1274
  }
1174
1275
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "11.6.5",
3
+ "version": "11.6.7",
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",