@rogieking/figui3 2.17.3 → 2.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/components.css CHANGED
@@ -2512,6 +2512,12 @@ fig-input-fill {
2512
2512
  gap: 0;
2513
2513
  }
2514
2514
  }
2515
+
2516
+ fig-field[direction="horizontal"] &,
2517
+ fig-field[direction="row"] & {
2518
+ flex: 1;
2519
+ min-width: 0;
2520
+ }
2515
2521
  }
2516
2522
 
2517
2523
  fig-slider {
@@ -2524,6 +2530,12 @@ fig-slider {
2524
2530
  & fig-input-number {
2525
2531
  flex-basis: 5rem;
2526
2532
  }
2533
+
2534
+ fig-field[direction="horizontal"] &,
2535
+ fig-field[direction="row"] & {
2536
+ flex: 1;
2537
+ min-width: 0;
2538
+ }
2527
2539
  }
2528
2540
 
2529
2541
  fig-field,
package/fig.js CHANGED
@@ -2022,6 +2022,7 @@ customElements.define("fig-segmented-control", FigSegmentedControl);
2022
2022
  * @attr {string} color - The color for the slider track (for opacity type)
2023
2023
  */
2024
2024
  class FigSlider extends HTMLElement {
2025
+ #isInteracting = false;
2025
2026
  // Private fields declarations
2026
2027
  #typeDefaults = {
2027
2028
  range: { min: 0, max: 100, step: 1 },
@@ -2088,6 +2089,7 @@ class FigSlider extends HTMLElement {
2088
2089
  let slider = `<div class="fig-slider-input-container" role="group">
2089
2090
  <input
2090
2091
  type="range"
2092
+ ${this.text ? 'tabindex="-1"' : ""}
2091
2093
  ${this.disabled ? "disabled" : ""}
2092
2094
  min="${this.min}"
2093
2095
  max="${this.max}"
@@ -2124,6 +2126,8 @@ class FigSlider extends HTMLElement {
2124
2126
  this.input.addEventListener("input", this.#boundHandleInput);
2125
2127
  this.input.removeEventListener("change", this.#boundHandleChange);
2126
2128
  this.input.addEventListener("change", this.#boundHandleChange);
2129
+ this.input.addEventListener("pointerdown", () => { this.#isInteracting = true; });
2130
+ this.input.addEventListener("pointerup", () => { this.#isInteracting = false; });
2127
2131
 
2128
2132
  if (this.default) {
2129
2133
  this.style.setProperty(
@@ -2253,6 +2257,7 @@ class FigSlider extends HTMLElement {
2253
2257
  }
2254
2258
 
2255
2259
  #handleChange() {
2260
+ this.#isInteracting = false;
2256
2261
  this.#syncValue();
2257
2262
  this.dispatchEvent(
2258
2263
  new CustomEvent("change", { detail: this.value, bubbles: true })
@@ -2306,6 +2311,7 @@ class FigSlider extends HTMLElement {
2306
2311
  }
2307
2312
  break;
2308
2313
  case "value":
2314
+ if (this.#isInteracting) break;
2309
2315
  this.value = newValue;
2310
2316
  this.input.value = newValue;
2311
2317
  this.#syncProperties();
@@ -2365,6 +2371,7 @@ customElements.define("fig-slider", FigSlider);
2365
2371
  * @attr {number} transform - A multiplier for displayed number values
2366
2372
  */
2367
2373
  class FigInputText extends HTMLElement {
2374
+ #isInteracting = false;
2368
2375
  #boundMouseMove;
2369
2376
  #boundMouseUp;
2370
2377
  #boundMouseDown;
@@ -2507,6 +2514,7 @@ class FigInputText extends HTMLElement {
2507
2514
  #handleMouseDown(e) {
2508
2515
  if (this.type !== "number") return;
2509
2516
  if (e.altKey) {
2517
+ this.#isInteracting = true;
2510
2518
  this.input.style.cursor =
2511
2519
  this.style.cursor =
2512
2520
  document.body.style.cursor =
@@ -2519,6 +2527,7 @@ class FigInputText extends HTMLElement {
2519
2527
  }
2520
2528
  #handleMouseUp(e) {
2521
2529
  if (this.type !== "number") return;
2530
+ this.#isInteracting = false;
2522
2531
  this.input.style.cursor =
2523
2532
  this.style.cursor =
2524
2533
  document.body.style.cursor =
@@ -2594,6 +2603,7 @@ class FigInputText extends HTMLElement {
2594
2603
  }
2595
2604
  break;
2596
2605
  case "value":
2606
+ if (this.#isInteracting) break;
2597
2607
  let value = newValue;
2598
2608
  if (this.type === "number") {
2599
2609
  value = this.#sanitizeInput(value, false);
@@ -2651,6 +2661,7 @@ class FigInputNumber extends HTMLElement {
2651
2661
  #units;
2652
2662
  #unitPosition;
2653
2663
  #precision;
2664
+ #isInteracting = false;
2654
2665
 
2655
2666
  constructor() {
2656
2667
  super();
@@ -2830,6 +2841,7 @@ class FigInputNumber extends HTMLElement {
2830
2841
  }
2831
2842
 
2832
2843
  #handleFocus(e) {
2844
+ this.#isInteracting = true;
2833
2845
  setTimeout(() => {
2834
2846
  const value = e.target.value;
2835
2847
  if (value && this.#units) {
@@ -2846,6 +2858,7 @@ class FigInputNumber extends HTMLElement {
2846
2858
  }
2847
2859
 
2848
2860
  #handleBlur(e) {
2861
+ this.#isInteracting = false;
2849
2862
  let numericValue = this.#getNumericValue(e.target.value);
2850
2863
  if (numericValue !== "") {
2851
2864
  let val = Number(numericValue) / (this.transform || 1);
@@ -2939,6 +2952,7 @@ class FigInputNumber extends HTMLElement {
2939
2952
  #handleMouseDown(e) {
2940
2953
  if (this.disabled) return;
2941
2954
  if (e.altKey) {
2955
+ this.#isInteracting = true;
2942
2956
  this.input.style.cursor =
2943
2957
  this.style.cursor =
2944
2958
  document.body.style.cursor =
@@ -2951,6 +2965,7 @@ class FigInputNumber extends HTMLElement {
2951
2965
  }
2952
2966
 
2953
2967
  #handleMouseUp(e) {
2968
+ this.#isInteracting = false;
2954
2969
  this.input.style.cursor =
2955
2970
  this.style.cursor =
2956
2971
  document.body.style.cursor =
@@ -3019,6 +3034,7 @@ class FigInputNumber extends HTMLElement {
3019
3034
  this.input.value = this.#formatWithUnit(this.value);
3020
3035
  break;
3021
3036
  case "value":
3037
+ if (this.#isInteracting) break;
3022
3038
  let value =
3023
3039
  newValue !== null && newValue !== "" ? Number(newValue) : "";
3024
3040
  if (value !== "") {
@@ -4167,9 +4183,15 @@ class FigInputFill extends HTMLElement {
4167
4183
 
4168
4184
  switch (name) {
4169
4185
  case "value":
4186
+ const prevType = this.#fillType;
4170
4187
  this.#parseValue();
4171
4188
  if (this.#fillPicker) {
4172
- this.#render();
4189
+ if (this.#fillType !== prevType) {
4190
+ this.#render();
4191
+ } else {
4192
+ this.#updateFillPicker();
4193
+ this.#updateControls();
4194
+ }
4173
4195
  }
4174
4196
  break;
4175
4197
  case "disabled":
@@ -4540,18 +4562,37 @@ customElements.define("fig-toast", FigToast, { extends: "dialog" });
4540
4562
  * @attr {string} value - The current input value
4541
4563
  */
4542
4564
  class FigComboInput extends HTMLElement {
4565
+ #usesCustomDropdown = false;
4566
+ #boundHandleSelectInput = null;
4567
+
4543
4568
  constructor() {
4544
4569
  super();
4570
+ this.#boundHandleSelectInput = this.handleSelectInput.bind(this);
4545
4571
  }
4546
4572
  getOptionsFromAttribute() {
4547
4573
  return (this.getAttribute("options") || "").split(",");
4548
4574
  }
4549
4575
  connectedCallback() {
4576
+ const customDropdown =
4577
+ Array.from(this.children).find((child) => child.tagName === "FIG-DROPDOWN") ||
4578
+ null;
4579
+ this.#usesCustomDropdown = customDropdown !== null;
4580
+ if (customDropdown) {
4581
+ customDropdown.remove();
4582
+ }
4583
+
4550
4584
  this.options = this.getOptionsFromAttribute();
4551
4585
  this.placeholder = this.getAttribute("placeholder") || "";
4552
4586
  this.value = this.getAttribute("value") || "";
4553
4587
  const experimental = this.getAttribute("experimental");
4554
4588
  const expAttr = experimental ? `experimental="${experimental}"` : "";
4589
+ const dropdownHTML = this.#usesCustomDropdown
4590
+ ? ""
4591
+ : `<fig-dropdown type="dropdown" ${expAttr}>
4592
+ ${this.options
4593
+ .map((option) => `<option>${option}</option>`)
4594
+ .join("")}
4595
+ </fig-dropdown>`;
4555
4596
  this.innerHTML = `<div class="input-combo">
4556
4597
  <fig-input-text placeholder="${this.placeholder}">
4557
4598
  </fig-input-text>
@@ -4559,21 +4600,30 @@ class FigComboInput extends HTMLElement {
4559
4600
  <svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
4560
4601
  <path d='M5.87868 7.12132L8 9.24264L10.1213 7.12132' stroke='currentColor' stroke-opacity="0.9" stroke-linecap='round'/>
4561
4602
  </svg>
4562
- <fig-dropdown type="dropdown" ${expAttr}>
4563
- ${this.options
4564
- .map((option) => `<option>${option}</option>`)
4565
- .join("")}
4566
- </fig-dropdown>
4603
+ ${dropdownHTML}
4567
4604
  </fig-button>
4568
4605
  </div>`;
4569
4606
  requestAnimationFrame(() => {
4570
4607
  this.input = this.querySelector("fig-input-text");
4608
+ const button = this.querySelector("fig-button");
4609
+
4610
+ if (this.#usesCustomDropdown && customDropdown && button) {
4611
+ if (!customDropdown.hasAttribute("type")) {
4612
+ customDropdown.setAttribute("type", "dropdown");
4613
+ }
4614
+ if (experimental) {
4615
+ customDropdown.setAttribute("experimental", experimental);
4616
+ }
4617
+ button.append(customDropdown);
4618
+ }
4571
4619
  this.dropdown = this.querySelector("fig-dropdown");
4572
4620
 
4573
- this.dropdown.addEventListener(
4574
- "input",
4575
- this.handleSelectInput.bind(this)
4576
- );
4621
+ this.dropdown?.removeEventListener("input", this.#boundHandleSelectInput);
4622
+ this.dropdown?.addEventListener("input", this.#boundHandleSelectInput);
4623
+
4624
+ if (this.input) {
4625
+ this.input.setAttribute("value", this.value);
4626
+ }
4577
4627
 
4578
4628
  // Apply initial disabled state
4579
4629
  if (this.hasAttribute("disabled")) {
@@ -4581,6 +4631,9 @@ class FigComboInput extends HTMLElement {
4581
4631
  }
4582
4632
  });
4583
4633
  }
4634
+ disconnectedCallback() {
4635
+ this.dropdown?.removeEventListener("input", this.#boundHandleSelectInput);
4636
+ }
4584
4637
  handleSelectInput(e) {
4585
4638
  this.setAttribute("value", e.target.closest("fig-dropdown").value);
4586
4639
  }
@@ -4614,7 +4667,7 @@ class FigComboInput extends HTMLElement {
4614
4667
  switch (name) {
4615
4668
  case "options":
4616
4669
  this.options = newValue.split(",");
4617
- if (this.dropdown) {
4670
+ if (this.dropdown && !this.#usesCustomDropdown) {
4618
4671
  this.dropdown.innerHTML = this.options
4619
4672
  .map((option) => `<option>${option}</option>`)
4620
4673
  .join("");
@@ -4639,7 +4692,7 @@ class FigComboInput extends HTMLElement {
4639
4692
  if (this.dropdown) {
4640
4693
  if (newValue) {
4641
4694
  this.dropdown.setAttribute("experimental", newValue);
4642
- } else {
4695
+ } else if (!this.#usesCustomDropdown) {
4643
4696
  this.dropdown.removeAttribute("experimental");
4644
4697
  }
4645
4698
  }
@@ -5283,6 +5336,7 @@ class FigInputJoystick extends HTMLElement {
5283
5336
  }
5284
5337
  attributeChangedCallback(name, oldValue, newValue) {
5285
5338
  if (name === "value") {
5339
+ if (this.isDragging) return;
5286
5340
  this.value = newValue;
5287
5341
  }
5288
5342
  if (name === "precision") {
@@ -5740,6 +5794,7 @@ class FigInputAngle extends HTMLElement {
5740
5794
  attributeChangedCallback(name, oldValue, newValue) {
5741
5795
  switch (name) {
5742
5796
  case "value":
5797
+ if (this.isDragging) break;
5743
5798
  this.value = Number(newValue);
5744
5799
  break;
5745
5800
  case "precision":
package/index.html CHANGED
@@ -1267,69 +1267,62 @@
1267
1267
  </fig-field>
1268
1268
 
1269
1269
  <h3>Horizontal Fields with Different Inputs</h3>
1270
- <fig-field direction="horizontal"
1271
- style="width: 240px;">
1272
- <label>Text Input</label>
1273
- <fig-input-text placeholder="Enter text"></fig-input-text>
1274
- </fig-field>
1275
- <fig-field direction="horizontal"
1276
- style="width: 240px;">
1277
- <label>Number Input</label>
1278
- <fig-input-number value="100"
1279
- units="px"></fig-input-number>
1280
- </fig-field>
1281
- <fig-field direction="horizontal"
1282
- style="width: 240px;">
1283
- <label>Dropdown</label>
1284
- <fig-dropdown>
1285
- <option>Option One</option>
1286
- <option>Option Two</option>
1287
- <option>Option Three</option>
1288
- </fig-dropdown>
1289
- </fig-field>
1290
- <fig-field direction="horizontal"
1291
- style="width: 240px;">
1292
- <label>Slider</label>
1293
- <fig-slider value="50"
1294
- text="true"></fig-slider>
1295
- </fig-field>
1296
- <fig-field direction="horizontal"
1297
- style="width: 240px;">
1298
- <label>Color</label>
1299
- <fig-input-color value="#0D99FF"
1300
- text="true"></fig-input-color>
1301
- </fig-field>
1302
- <fig-field direction="horizontal"
1303
- style="width: 240px;">
1304
- <label>Angle</label>
1305
- <fig-input-angle value="45"
1306
- text="true"></fig-input-angle>
1307
- </fig-field>
1308
- <fig-field direction="horizontal"
1309
- style="width: 240px;">
1310
- <label>Joystick</label>
1311
- <fig-input-joystick text="true"
1312
- value="50,50"></fig-input-joystick>
1313
- </fig-field>
1314
- <fig-field direction="horizontal"
1315
- style="width: 240px;">
1316
- <label>Switch</label>
1317
- <fig-switch></fig-switch>
1318
- </fig-field>
1319
- <fig-field direction="horizontal"
1320
- style="width: 240px;">
1321
- <label>Checkbox</label>
1322
- <fig-checkbox></fig-checkbox>
1323
- </fig-field>
1324
- <fig-field direction="horizontal"
1325
- style="width: 240px;">
1326
- <label>Segmented</label>
1327
- <fig-segmented-control>
1328
- <fig-segment value="left">Left</fig-segment>
1329
- <fig-segment value="center">Center</fig-segment>
1330
- <fig-segment value="right">Right</fig-segment>
1331
- </fig-segmented-control>
1332
- </fig-field>
1270
+ <p class="description">Drag the right edge to test at different widths.</p>
1271
+ <div class="resize-test" style="width: 240px;">
1272
+ <fig-field direction="horizontal">
1273
+ <label>Text Input</label>
1274
+ <fig-input-text placeholder="Enter text" full></fig-input-text>
1275
+ </fig-field>
1276
+ <fig-field direction="horizontal">
1277
+ <label>Number Input</label>
1278
+ <fig-input-number value="100"
1279
+ units="px" full></fig-input-number>
1280
+ </fig-field>
1281
+ <fig-field direction="horizontal">
1282
+ <label>Dropdown</label>
1283
+ <fig-dropdown full>
1284
+ <option>Option One</option>
1285
+ <option>Option Two</option>
1286
+ <option>Option Three</option>
1287
+ </fig-dropdown>
1288
+ </fig-field>
1289
+ <fig-field direction="horizontal">
1290
+ <label>Slider</label>
1291
+ <fig-slider value="50"
1292
+ text="true" full></fig-slider>
1293
+ </fig-field>
1294
+ <fig-field direction="horizontal">
1295
+ <label>Color</label>
1296
+ <fig-input-color value="#0D99FF"
1297
+ text="true" full></fig-input-color>
1298
+ </fig-field>
1299
+ <fig-field direction="horizontal">
1300
+ <label>Angle</label>
1301
+ <fig-input-angle value="45"
1302
+ text="true" full></fig-input-angle>
1303
+ </fig-field>
1304
+ <fig-field direction="horizontal">
1305
+ <label>Joystick</label>
1306
+ <fig-input-joystick text="true"
1307
+ value="50,50" full></fig-input-joystick>
1308
+ </fig-field>
1309
+ <fig-field direction="horizontal">
1310
+ <label>Switch</label>
1311
+ <fig-switch></fig-switch>
1312
+ </fig-field>
1313
+ <fig-field direction="horizontal">
1314
+ <label>Checkbox</label>
1315
+ <fig-checkbox></fig-checkbox>
1316
+ </fig-field>
1317
+ <fig-field direction="horizontal">
1318
+ <label>Segmented</label>
1319
+ <fig-segmented-control full>
1320
+ <fig-segment value="left">Left</fig-segment>
1321
+ <fig-segment value="center">Center</fig-segment>
1322
+ <fig-segment value="right">Right</fig-segment>
1323
+ </fig-segmented-control>
1324
+ </fig-field>
1325
+ </div>
1333
1326
  </section>
1334
1327
  <hr>
1335
1328
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "2.17.3",
3
+ "version": "2.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",