@rogieking/figui3 6.16.0 → 6.18.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
@@ -2845,10 +2845,16 @@ class FigPopup extends HTMLDialogElement {
2845
2845
  if (closedby === "none" || closedby === "closerequest") return;
2846
2846
  const target = event.target;
2847
2847
  if (!(target instanceof Node)) return;
2848
+
2849
+ // Prefer composedPath so slotted light-DOM content (e.g. fig-select options)
2850
+ // counts as inside — Node.contains() is false for slotted nodes.
2851
+ const path =
2852
+ typeof event.composedPath === "function" ? event.composedPath() : [];
2853
+ if (path.includes(this)) return;
2848
2854
  if (this.contains(target)) return;
2849
2855
 
2850
2856
  const anchor = this.resolveAnchor();
2851
- if (anchor?.contains && anchor.contains(target)) return;
2857
+ if (anchor && (path.includes(anchor) || anchor.contains?.(target))) return;
2852
2858
 
2853
2859
  if (this.isInsideDescendantPopup(target)) return;
2854
2860
 
@@ -7139,7 +7145,20 @@ class FigField extends HTMLElement {
7139
7145
  !(node instanceof Element && node.classList.contains("fig-field-chevron")),
7140
7146
  );
7141
7147
 
7142
- this.#toggleable = !!(this.input && "open" in this.input);
7148
+ // Popup/menu hosts also expose `open`, but that is overlay state — not a
7149
+ // fig-field disclosure. Only treat true expand/collapse children as toggleable.
7150
+ const inputTag = this.input?.localName ?? "";
7151
+ const popupOpenHost =
7152
+ inputTag === "fig-select" ||
7153
+ inputTag === "fig-menu" ||
7154
+ inputTag === "fig-dropdown" ||
7155
+ inputTag === "fig-tooltip" ||
7156
+ (this.input instanceof HTMLDialogElement);
7157
+ this.#toggleable = !!(
7158
+ this.input &&
7159
+ "open" in this.input &&
7160
+ !popupOpenHost
7161
+ );
7143
7162
 
7144
7163
  if (this.#toggleable && this.label) {
7145
7164
  if (!this.#chevron || !this.#chevron.isConnected) {
@@ -7152,12 +7171,21 @@ class FigField extends HTMLElement {
7152
7171
 
7153
7172
  this.#chevron.addEventListener("click", this.#boundToggle);
7154
7173
  this.label.addEventListener("click", this.#boundToggle);
7155
- } else if (this.input && this.label) {
7156
- const nativeInputs = this.input.querySelectorAll("input, select, textarea");
7157
- // A label with a `for` target already focuses and activates its control.
7158
- // Only use the composite fallback when there is no single native target.
7159
- if (nativeInputs.length !== 1) {
7160
- this.label.addEventListener("click", this.#boundFocus);
7174
+ } else {
7175
+ if (this.#chevron) {
7176
+ this.#chevron.removeEventListener("click", this.#boundToggle);
7177
+ this.#chevron.remove();
7178
+ this.#chevron = null;
7179
+ }
7180
+ if (this.input && this.label) {
7181
+ const nativeInputs = this.input.querySelectorAll(
7182
+ "input, select, textarea",
7183
+ );
7184
+ // A label with a `for` target already focuses and activates its control.
7185
+ // Only use the composite fallback when there is no single native target.
7186
+ if (nativeInputs.length !== 1) {
7187
+ this.label.addEventListener("click", this.#boundFocus);
7188
+ }
7161
7189
  }
7162
7190
  }
7163
7191
 
@@ -17186,11 +17214,40 @@ class FigMenuItem extends HTMLElement {
17186
17214
  }
17187
17215
  customElements.define("fig-menu-item", FigMenuItem);
17188
17216
 
17217
+ /**
17218
+ * Visual divider between menu item groups.
17219
+ * @attr {string} label - Optional group label shown in secondary text under the line.
17220
+ */
17189
17221
  class FigMenuSeparator extends HTMLElement {
17222
+ static get observedAttributes() {
17223
+ return ["label"];
17224
+ }
17225
+
17226
+ get label() {
17227
+ return this.getAttribute("label") ?? "";
17228
+ }
17229
+
17230
+ set label(value) {
17231
+ if (value == null || value === "") this.removeAttribute("label");
17232
+ else this.setAttribute("label", String(value));
17233
+ }
17234
+
17190
17235
  connectedCallback() {
17236
+ this.#sync();
17237
+ }
17238
+
17239
+ attributeChangedCallback(name, oldValue, newValue) {
17240
+ if (oldValue === newValue) return;
17241
+ this.#sync();
17242
+ }
17243
+
17244
+ #sync() {
17191
17245
  if (!this.hasAttribute("role")) {
17192
17246
  this.setAttribute("role", "separator");
17193
17247
  }
17248
+ const label = this.label.trim();
17249
+ if (label) this.setAttribute("aria-label", label);
17250
+ else this.removeAttribute("aria-label");
17194
17251
  }
17195
17252
  }
17196
17253
  customElements.define("fig-menu-separator", FigMenuSeparator);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "6.16.0",
3
+ "version": "6.18.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",