@rogieking/figui3 3.21.0 → 3.21.1

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
@@ -5389,14 +5389,15 @@ class FigInputFill extends HTMLElement {
5389
5389
  ${opacityHtml(Math.round(this.#solid.alpha * 100))}`;
5390
5390
  break;
5391
5391
 
5392
- case "gradient":
5392
+ case "gradient": {
5393
5393
  const gradientLabel =
5394
5394
  this.#gradient.type.charAt(0).toUpperCase() +
5395
5395
  this.#gradient.type.slice(1);
5396
5396
  controlsHtml = `
5397
5397
  <label class="fig-input-fill-label">${gradientLabel}</label>
5398
- ${opacityHtml(this.#gradient.stops[0]?.opacity ?? 100)}`;
5398
+ ${opacityHtml(100)}`;
5399
5399
  break;
5400
+ }
5400
5401
 
5401
5402
  case "image":
5402
5403
  controlsHtml = `
@@ -5529,10 +5530,6 @@ class FigInputFill extends HTMLElement {
5529
5530
  this.#solid.alpha = alpha;
5530
5531
  break;
5531
5532
  case "gradient":
5532
- // Apply to all stops
5533
- this.#gradient.stops.forEach((stop) => {
5534
- stop.opacity = opacity;
5535
- });
5536
5533
  break;
5537
5534
  case "image":
5538
5535
  this.#image.opacity = alpha;
@@ -5575,12 +5572,6 @@ class FigInputFill extends HTMLElement {
5575
5572
  }
5576
5573
  break;
5577
5574
  case "gradient": {
5578
- if (this.#opacityInput) {
5579
- this.#opacityInput.setAttribute(
5580
- "value",
5581
- this.#gradient.stops[0]?.opacity ?? 100,
5582
- );
5583
- }
5584
5575
  const label = this.querySelector(".fig-input-fill-label");
5585
5576
  if (label) {
5586
5577
  const newLabel =
@@ -5657,7 +5648,7 @@ class FigInputFill extends HTMLElement {
5657
5648
  </fig-input-number>
5658
5649
  </fig-tooltip>`;
5659
5650
  break;
5660
- case "gradient":
5651
+ case "gradient": {
5661
5652
  const gradientLabel =
5662
5653
  this.#gradient.type.charAt(0).toUpperCase() +
5663
5654
  this.#gradient.type.slice(1);
@@ -5669,12 +5660,13 @@ class FigInputFill extends HTMLElement {
5669
5660
  placeholder="##"
5670
5661
  min="0"
5671
5662
  max="100"
5672
- value="${this.#gradient.stops[0]?.opacity ?? 100}"
5663
+ value="100"
5673
5664
  units="%"
5674
5665
  ${disabled ? "disabled" : ""}>
5675
5666
  </fig-input-number>
5676
5667
  </fig-tooltip>`;
5677
5668
  break;
5669
+ }
5678
5670
  case "image":
5679
5671
  controlsHtml = `
5680
5672
  <label class="fig-input-fill-label">Image</label>
@@ -5768,9 +5760,6 @@ class FigInputFill extends HTMLElement {
5768
5760
  this.#solid.alpha = alpha;
5769
5761
  break;
5770
5762
  case "gradient":
5771
- this.#gradient.stops.forEach((stop) => {
5772
- stop.opacity = opacity;
5773
- });
5774
5763
  break;
5775
5764
  case "image":
5776
5765
  this.#image.opacity = alpha;
@@ -6392,17 +6381,31 @@ class FigInputGradient extends HTMLElement {
6392
6381
  const sorted = [...this.#gradient.stops].sort(
6393
6382
  (a, b) => a.position - b.position,
6394
6383
  );
6395
- const stops = sorted.map((s) => `${s.color} ${s.position}%`).join(", ");
6384
+ const stops = sorted
6385
+ .map((s) => {
6386
+ const alpha = (s.opacity ?? 100) / 100;
6387
+ if (alpha >= 1) return `${s.color} ${s.position}%`;
6388
+ const { r, g, b } = figHexToRGB(s.color);
6389
+ return `rgba(${r}, ${g}, ${b}, ${alpha}) ${s.position}%`;
6390
+ })
6391
+ .join(", ");
6396
6392
  const interp = gradientInterpolationClause(this.#gradient);
6397
6393
  return `linear-gradient(${this.#gradient.angle}deg ${interp}, ${stops})`;
6398
6394
  }
6399
6395
 
6396
+ #stopColorCSS(stop) {
6397
+ const alpha = (stop.opacity ?? 100) / 100;
6398
+ if (alpha >= 1) return stop.color;
6399
+ const { r, g, b } = figHexToRGB(stop.color);
6400
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
6401
+ }
6402
+
6400
6403
  #buildStopHandles() {
6401
6404
  const disabled = this.hasAttribute("disabled");
6402
6405
  return this.#gradient.stops
6403
6406
  .map(
6404
6407
  (stop, i) =>
6405
- `<fig-tooltip action="manual" text="${Math.round(stop.position)}%"><fig-handle drag drag-axes="x" drag-surface=".fig-input-gradient-track" type="color" color="${stop.color}" value="${stop.position}% 50%" hit-area="4" data-stop-index="${i}"${disabled ? " disabled" : ""}></fig-handle></fig-tooltip>`,
6408
+ `<fig-tooltip action="manual" text="${Math.round(stop.position)}%"><fig-handle drag drag-axes="x" drag-surface=".fig-input-gradient-track" type="color" color="${this.#stopColorCSS(stop)}" value="${stop.position}% 50%" hit-area="4" data-stop-index="${i}"${disabled ? " disabled" : ""}></fig-handle></fig-tooltip>`,
6406
6409
  )
6407
6410
  .join("");
6408
6411
  }
@@ -6643,7 +6646,7 @@ class FigInputGradient extends HTMLElement {
6643
6646
  const stop = stops[i];
6644
6647
  h.dataset.stopIndex = i;
6645
6648
  h.setAttribute("value", `${stop.position}% 50%`);
6646
- h.setAttribute("color", stop.color);
6649
+ h.setAttribute("color", this.#stopColorCSS(stop));
6647
6650
  const tip = h.closest("fig-tooltip");
6648
6651
  if (tip) tip.setAttribute("text", `${Math.round(stop.position)}%`);
6649
6652
  }
@@ -6760,6 +6763,10 @@ class FigInputGradient extends HTMLElement {
6760
6763
  const idx = parseInt(handle.dataset.stopIndex, 10);
6761
6764
  if (!isNaN(idx) && this.#gradient.stops[idx]) {
6762
6765
  this.#gradient.stops[idx].color = e.detail.color;
6766
+ if (e.detail.opacity !== undefined) {
6767
+ this.#gradient.stops[idx].opacity = e.detail.opacity;
6768
+ }
6769
+ handle.setAttribute("color", this.#stopColorCSS(this.#gradient.stops[idx]));
6763
6770
  this.#syncChit();
6764
6771
  this.#emitInput();
6765
6772
  }
@@ -6811,6 +6818,10 @@ class FigInputGradient extends HTMLElement {
6811
6818
  const idx = parseInt(handle.dataset.stopIndex, 10);
6812
6819
  if (!isNaN(idx) && this.#gradient.stops[idx]) {
6813
6820
  this.#gradient.stops[idx].color = e.detail.color;
6821
+ if (e.detail.opacity !== undefined) {
6822
+ this.#gradient.stops[idx].opacity = e.detail.opacity;
6823
+ }
6824
+ handle.setAttribute("color", this.#stopColorCSS(this.#gradient.stops[idx]));
6814
6825
  this.#syncChit();
6815
6826
  this.#emitChange();
6816
6827
  }
@@ -6852,7 +6863,8 @@ class FigInputGradient extends HTMLElement {
6852
6863
  const idx = parseInt(handle.dataset.stopIndex, 10);
6853
6864
  if (isNaN(idx) || !this.#gradient.stops[idx]) continue;
6854
6865
  const newColor = handle.getAttribute("color");
6855
- if (newColor && newColor !== this.#gradient.stops[idx].color) {
6866
+ if (!newColor || !newColor.startsWith("#")) continue;
6867
+ if (newColor !== this.#gradient.stops[idx].color) {
6856
6868
  this.#gradient.stops[idx].color = newColor;
6857
6869
  this.#syncChit();
6858
6870
  this.#emitInput();
@@ -7578,8 +7590,8 @@ class FigChit extends HTMLElement {
7578
7590
  }
7579
7591
  }
7580
7592
 
7581
- // Always update CSS variable with raw value so vars stay reactive
7582
- this.style.setProperty("--chit-background", rawBg);
7593
+ const isImage = /^(linear-gradient|radial-gradient|conic-gradient|repeating-|url)\s*\(/i.test(rawBg);
7594
+ this.style.setProperty("--chit-background", isImage ? rawBg : `linear-gradient(${rawBg}, ${rawBg})`);
7583
7595
  }
7584
7596
 
7585
7597
  #handleInput(e) {
@@ -7605,9 +7617,9 @@ class FigChit extends HTMLElement {
7605
7617
  attributeChangedCallback(name, oldValue, newValue) {
7606
7618
  if (oldValue === newValue) return;
7607
7619
  if (name === "background") {
7608
- // Skip full re-render if this was triggered by internal input
7609
7620
  if (this.#internalUpdate) {
7610
- this.style.setProperty("--chit-background", newValue);
7621
+ const isImg = /^(linear-gradient|radial-gradient|conic-gradient|repeating-|url)\s*\(/i.test(newValue);
7622
+ this.style.setProperty("--chit-background", isImg ? newValue : `linear-gradient(${newValue}, ${newValue})`);
7611
7623
  return;
7612
7624
  }
7613
7625
  this.#render();
@@ -7629,6 +7641,10 @@ class FigChit extends HTMLElement {
7629
7641
  }
7630
7642
  }
7631
7643
  customElements.define("fig-chit", FigChit);
7644
+ class FigSwatch extends FigChit{
7645
+
7646
+ }
7647
+ customElements.define("fig-swatch", FigSwatch);
7632
7648
 
7633
7649
  /* Upload */
7634
7650
  /**
@@ -10899,7 +10915,6 @@ class FigFillPicker extends HTMLElement {
10899
10915
  this.#chit.style.setProperty("--chit-bg-size", bgSize);
10900
10916
  this.#chit.style.setProperty("--chit-bg-position", bgPosition);
10901
10917
 
10902
- // For solid colors, also update the alpha
10903
10918
  if (this.#fillType === "solid") {
10904
10919
  this.#chit.setAttribute("alpha", this.#color.a);
10905
10920
  } else {
@@ -12017,10 +12032,10 @@ class FigFillPicker extends HTMLElement {
12017
12032
  stopColor.addEventListener("input", (e) => {
12018
12033
  this.#gradient.stops[index].color =
12019
12034
  e.target.hexOpaque || e.target.value;
12020
- const parsedAlpha = parseFloat(e.target.alpha);
12021
- this.#gradient.stops[index].opacity = isNaN(parsedAlpha)
12022
- ? 100
12023
- : parsedAlpha;
12035
+ const a = e.detail?.rgba?.a;
12036
+ if (a !== undefined) {
12037
+ this.#gradient.stops[index].opacity = Math.round(a * 100);
12038
+ }
12024
12039
  this.#updateGradientPreview();
12025
12040
  this.#emitInput();
12026
12041
  });
@@ -13011,8 +13026,12 @@ class FigColorTip extends HTMLElement {
13011
13026
  }
13012
13027
 
13013
13028
  const eventDetail = { color: this.value };
13014
- if (this.#alphaEnabled && detail?.opacity !== undefined) {
13015
- eventDetail.opacity = detail.opacity;
13029
+ if (this.#alphaEnabled) {
13030
+ if (detail?.opacity !== undefined) {
13031
+ eventDetail.opacity = detail.opacity;
13032
+ } else if (detail?.alpha !== undefined) {
13033
+ eventDetail.opacity = Math.round(detail.alpha * 100);
13034
+ }
13016
13035
  }
13017
13036
 
13018
13037
  this.dispatchEvent(
@@ -15005,19 +15024,25 @@ class FigHandle extends HTMLElement {
15005
15024
  this.#colorTip = null;
15006
15025
  }
15007
15026
 
15027
+ #colorWithOpacity(hex, opacity) {
15028
+ if (opacity === undefined || opacity >= 100) return hex;
15029
+ const { r, g, b } = figHexToRGB(hex);
15030
+ return `rgba(${r}, ${g}, ${b}, ${opacity / 100})`;
15031
+ }
15032
+
15008
15033
  #handleColorTipInput = (e) => {
15009
15034
  e.stopPropagation();
15010
15035
  if (e.detail?.color) {
15011
- this.setAttribute("color", e.detail.color);
15012
- this.dispatchEvent(new CustomEvent("input", { bubbles: true, detail: { color: e.detail.color } }));
15036
+ this.setAttribute("color", this.#colorWithOpacity(e.detail.color, e.detail.opacity));
15037
+ this.dispatchEvent(new CustomEvent("input", { bubbles: true, detail: { color: e.detail.color, opacity: e.detail.opacity } }));
15013
15038
  }
15014
15039
  };
15015
15040
 
15016
15041
  #handleColorTipChange = (e) => {
15017
15042
  e.stopPropagation();
15018
15043
  if (e.detail?.color) {
15019
- this.setAttribute("color", e.detail.color);
15020
- this.dispatchEvent(new CustomEvent("change", { bubbles: true, detail: { color: e.detail.color } }));
15044
+ this.setAttribute("color", this.#colorWithOpacity(e.detail.color, e.detail.opacity));
15045
+ this.dispatchEvent(new CustomEvent("change", { bubbles: true, detail: { color: e.detail.color, opacity: e.detail.opacity } }));
15021
15046
  }
15022
15047
  };
15023
15048
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "3.21.0",
3
+ "version": "3.21.1",
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",