@rogieking/figui3 4.4.4 → 4.5.3

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
@@ -3162,6 +3162,15 @@ class FigOptions extends HTMLElement {
3162
3162
  #childControl = null;
3163
3163
  #suppressEvents = false;
3164
3164
 
3165
+ #normalizeChildEventValue(e) {
3166
+ const detailValue = e?.detail;
3167
+ if (typeof detailValue === "string") return detailValue;
3168
+ const fallbackValue =
3169
+ e?.currentTarget?.value ?? e?.target?.value ?? this.getAttribute("value");
3170
+ if (fallbackValue === null || fallbackValue === undefined) return null;
3171
+ return String(fallbackValue);
3172
+ }
3173
+
3165
3174
  connectedCallback() {
3166
3175
  this.#parseOptions();
3167
3176
  this.#renderSegments();
@@ -3252,7 +3261,6 @@ class FigOptions extends HTMLElement {
3252
3261
  if (this.hasAttribute("full")) sc.setAttribute("full", "");
3253
3262
 
3254
3263
  const currentValue = this.getAttribute("value");
3255
- let hasSelection = false;
3256
3264
 
3257
3265
  for (const opt of this.#parsedOptions) {
3258
3266
  const seg = document.createElement("fig-segment");
@@ -3260,7 +3268,6 @@ class FigOptions extends HTMLElement {
3260
3268
  seg.textContent = opt;
3261
3269
  if (currentValue === opt) {
3262
3270
  seg.setAttribute("selected", "true");
3263
- hasSelection = true;
3264
3271
  }
3265
3272
  sc.appendChild(seg);
3266
3273
  }
@@ -3268,18 +3275,32 @@ class FigOptions extends HTMLElement {
3268
3275
  if (currentValue) sc.setAttribute("value", currentValue);
3269
3276
 
3270
3277
  sc.addEventListener("input", (e) => {
3278
+ e.stopPropagation();
3271
3279
  if (this.#suppressEvents) return;
3280
+ const nextValue = this.#normalizeChildEventValue(e);
3281
+ if (nextValue === null) return;
3272
3282
  this.#suppressEvents = true;
3273
- this.setAttribute("value", e.detail);
3283
+ this.setAttribute("value", nextValue);
3274
3284
  this.#suppressEvents = false;
3275
3285
  this.dispatchEvent(
3276
- new CustomEvent("input", { detail: e.detail, bubbles: true }),
3286
+ new CustomEvent("input", {
3287
+ detail: nextValue,
3288
+ bubbles: true,
3289
+ composed: true,
3290
+ }),
3277
3291
  );
3278
3292
  });
3279
3293
  sc.addEventListener("change", (e) => {
3294
+ e.stopPropagation();
3280
3295
  if (this.#suppressEvents) return;
3296
+ const nextValue = this.#normalizeChildEventValue(e);
3297
+ if (nextValue === null) return;
3281
3298
  this.dispatchEvent(
3282
- new CustomEvent("change", { detail: e.detail, bubbles: true }),
3299
+ new CustomEvent("change", {
3300
+ detail: nextValue,
3301
+ bubbles: true,
3302
+ composed: true,
3303
+ }),
3283
3304
  );
3284
3305
  });
3285
3306
 
@@ -3308,18 +3329,32 @@ class FigOptions extends HTMLElement {
3308
3329
  if (currentValue) dd.setAttribute("value", currentValue);
3309
3330
 
3310
3331
  dd.addEventListener("input", (e) => {
3332
+ e.stopPropagation();
3311
3333
  if (this.#suppressEvents) return;
3334
+ const nextValue = this.#normalizeChildEventValue(e);
3335
+ if (!nextValue) return;
3312
3336
  this.#suppressEvents = true;
3313
- this.setAttribute("value", e.detail);
3337
+ this.setAttribute("value", nextValue);
3314
3338
  this.#suppressEvents = false;
3315
3339
  this.dispatchEvent(
3316
- new CustomEvent("input", { detail: e.detail, bubbles: true }),
3340
+ new CustomEvent("input", {
3341
+ detail: nextValue,
3342
+ bubbles: true,
3343
+ composed: true,
3344
+ }),
3317
3345
  );
3318
3346
  });
3319
3347
  dd.addEventListener("change", (e) => {
3348
+ e.stopPropagation();
3320
3349
  if (this.#suppressEvents) return;
3350
+ const nextValue = this.#normalizeChildEventValue(e);
3351
+ if (!nextValue) return;
3321
3352
  this.dispatchEvent(
3322
- new CustomEvent("change", { detail: e.detail, bubbles: true }),
3353
+ new CustomEvent("change", {
3354
+ detail: nextValue,
3355
+ bubbles: true,
3356
+ composed: true,
3357
+ }),
3323
3358
  );
3324
3359
  });
3325
3360
 
@@ -4175,6 +4210,7 @@ customElements.define("fig-input-text", FigInputText);
4175
4210
  * @attr {number} step - Step increment
4176
4211
  * @attr {number} transform - A multiplier for displayed number values
4177
4212
  * @attr {string} units - Unit string to append/prepend to displayed value (e.g., "%", "°", "$")
4213
+ * @attr {string} units-disallow - Comma-separated units to disallow (defaults to "px")
4178
4214
  * @attr {string} unit-position - Position of unit: "suffix" (default) or "prefix"
4179
4215
  * @attr {string} name - Form field name
4180
4216
  */
@@ -4189,10 +4225,31 @@ class FigInputNumber extends HTMLElement {
4189
4225
  #boundBlur;
4190
4226
  #boundKeyDown;
4191
4227
  #units;
4228
+ #rawUnits;
4229
+ #unitsDisallow;
4192
4230
  #unitPosition;
4193
4231
  #precision;
4194
4232
  #isInteracting = false;
4195
4233
  #stepperEl = null;
4234
+ static #DEFAULT_UNITS_DISALLOW = "px";
4235
+
4236
+ #parseUnitsDisallowList(value) {
4237
+ return (value || "")
4238
+ .split(",")
4239
+ .map((unit) => unit.trim().toLowerCase())
4240
+ .filter(Boolean);
4241
+ }
4242
+
4243
+ #resolveUnits(rawUnits) {
4244
+ const unit = (rawUnits || "").trim();
4245
+ if (!unit) return "";
4246
+ const disallowList = this.#unitsDisallow ?? [];
4247
+ return disallowList.includes(unit.toLowerCase()) ? "" : unit;
4248
+ }
4249
+
4250
+ #setUnitsFromAttributes() {
4251
+ this.#units = this.#resolveUnits(this.#rawUnits);
4252
+ }
4196
4253
 
4197
4254
  #syncSteppers(hasSteppers) {
4198
4255
  if (hasSteppers && !this.#stepperEl) {
@@ -4266,7 +4323,14 @@ class FigInputNumber extends HTMLElement {
4266
4323
  valueAttr !== null && valueAttr !== "" ? Number(valueAttr) : "";
4267
4324
  this.placeholder = this.getAttribute("placeholder") || "";
4268
4325
  this.name = this.getAttribute("name") || null;
4269
- this.#units = this.getAttribute("units") || "";
4326
+ this.#rawUnits = this.getAttribute("units") || "";
4327
+ const unitsDisallowAttr = this.getAttribute("units-disallow");
4328
+ this.#unitsDisallow = this.#parseUnitsDisallowList(
4329
+ unitsDisallowAttr === null
4330
+ ? FigInputNumber.#DEFAULT_UNITS_DISALLOW
4331
+ : unitsDisallowAttr,
4332
+ );
4333
+ this.#setUnitsFromAttributes();
4270
4334
  this.#unitPosition = this.getAttribute("unit-position") || "suffix";
4271
4335
  this.#precision = this.hasAttribute("precision")
4272
4336
  ? Number(this.getAttribute("precision"))
@@ -4587,6 +4651,7 @@ class FigInputNumber extends HTMLElement {
4587
4651
  "transform",
4588
4652
  "name",
4589
4653
  "units",
4654
+ "units-disallow",
4590
4655
  "unit-position",
4591
4656
  "steppers",
4592
4657
  "precision",
@@ -4601,7 +4666,17 @@ class FigInputNumber extends HTMLElement {
4601
4666
  newValue !== null && newValue !== "false";
4602
4667
  break;
4603
4668
  case "units":
4604
- this.#units = newValue || "";
4669
+ this.#rawUnits = newValue || "";
4670
+ this.#setUnitsFromAttributes();
4671
+ this.input.value = this.#formatWithUnit(this.value);
4672
+ break;
4673
+ case "units-disallow":
4674
+ this.#unitsDisallow = this.#parseUnitsDisallowList(
4675
+ newValue === null
4676
+ ? FigInputNumber.#DEFAULT_UNITS_DISALLOW
4677
+ : newValue,
4678
+ );
4679
+ this.#setUnitsFromAttributes();
4605
4680
  this.input.value = this.#formatWithUnit(this.value);
4606
4681
  break;
4607
4682
  case "unit-position":
@@ -11584,13 +11659,6 @@ class FigFillPicker extends HTMLElement {
11584
11659
  const showAlpha = this.getAttribute("alpha") !== "false";
11585
11660
  const experimental = this.getAttribute("experimental");
11586
11661
  const expAttr = experimental ? `experimental="${experimental}"` : "";
11587
- const savedMode = localStorage.getItem("figui-color-input-mode");
11588
- if (
11589
- savedMode &&
11590
- ["hex", "rgb", "hsl", "hsb", "lab", "lch"].includes(savedMode)
11591
- ) {
11592
- this.#colorInputMode = savedMode;
11593
- }
11594
11662
 
11595
11663
  container.innerHTML = `
11596
11664
  <fig-preview class="fig-fill-picker-color-area">
@@ -11669,7 +11737,6 @@ class FigFillPicker extends HTMLElement {
11669
11737
  const modeDropdown = container.querySelector(".fig-fill-picker-input-mode");
11670
11738
  modeDropdown.addEventListener("input", (e) => {
11671
11739
  this.#colorInputMode = e.target.value;
11672
- localStorage.setItem("figui-color-input-mode", this.#colorInputMode);
11673
11740
  this.#rebuildColorInputFields();
11674
11741
  });
11675
11742
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "4.4.4",
3
+ "version": "4.5.3",
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",
@@ -36,7 +36,7 @@
36
36
  "dev": "bun --hot server.ts",
37
37
  "build": "bun build fig.js --minify --outdir dist && npm run build:css",
38
38
  "build:css": "lightningcss --minify --nesting --bundle fig.css -o dist/fig.css && lightningcss --minify --nesting --bundle components.css -o dist/components.css && lightningcss --minify --nesting base.css -o dist/base.css",
39
- "dev:playground": "cd playground && npm run dev",
39
+ "dev:playground": "node playground/dev.mjs",
40
40
  "build:playground": "cd playground && npm run build"
41
41
  },
42
42
  "repository": {