@rogieking/figui3 3.4.3 → 3.5.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.
Files changed (3) hide show
  1. package/components.css +22 -4
  2. package/fig.js +165 -81
  3. package/package.json +1 -1
package/components.css CHANGED
@@ -1229,7 +1229,9 @@ fig-chit {
1229
1229
 
1230
1230
  /* Large gradient/image: also fill the area */
1231
1231
  &[data-type="gradient"]::after,
1232
- &[data-type="image"]::after {
1232
+ &[data-type="image"]::after,
1233
+ &[data-type="gradient"]::before,
1234
+ &[data-type="image"]::before {
1233
1235
  width: var(--size);
1234
1236
  height: var(--size);
1235
1237
  border-radius: var(--radius-medium);
@@ -1241,6 +1243,20 @@ fig-chit {
1241
1243
  opacity: 0.5;
1242
1244
  }
1243
1245
 
1246
+ &::before {
1247
+ content: "";
1248
+ width: 0.875rem;
1249
+ height: 0.875rem;
1250
+ border-radius: 0.125rem;
1251
+ grid-area: 1/1;
1252
+ place-self: center;
1253
+ }
1254
+ &[size="large"]::before {
1255
+ width: var(--size);
1256
+ height: var(--size);
1257
+ border-radius: var(--radius-medium);
1258
+ }
1259
+
1244
1260
  /* Gradient/Image types - inset thumbnail with hidden input */
1245
1261
  &[data-type="gradient"],
1246
1262
  &[data-type="image"] {
@@ -1250,6 +1266,7 @@ fig-chit {
1250
1266
  content: "";
1251
1267
  width: 0.875rem;
1252
1268
  height: 0.875rem;
1269
+
1253
1270
  background: var(--chit-background);
1254
1271
  background-size: var(--chit-bg-size);
1255
1272
  background-position: var(--chit-bg-position);
@@ -1288,9 +1305,10 @@ fig-chit {
1288
1305
  }
1289
1306
 
1290
1307
  /* Checkerboard for empty/missing images */
1291
- &[data-type="image"]:not([background])::after,
1292
- &[data-type="image"][background=""]::after,
1293
- &[data-type="image"][background="url()"]::after {
1308
+ &[data-type="image"]:not([background])::before,
1309
+ &[data-type="image"][background=""]::before,
1310
+ &[data-type="image"][background="url()"]::before,
1311
+ &[checkerboard]:not([checkerboard="false"])::before {
1294
1312
  background: var(--checkerboard);
1295
1313
  }
1296
1314
  }
package/fig.js CHANGED
@@ -9,7 +9,7 @@ function figIsWebKitOrIOSBrowser() {
9
9
  const userAgent = navigator.userAgent || "";
10
10
  const isIOSBrowser =
11
11
  /\b(iPad|iPhone|iPod)\b/.test(userAgent) ||
12
- /\bMacintosh\b/.test(userAgent) && /\bMobile\b/.test(userAgent);
12
+ (/\bMacintosh\b/.test(userAgent) && /\bMobile\b/.test(userAgent));
13
13
  const isDesktopWebKit =
14
14
  /\bAppleWebKit\b/.test(userAgent) &&
15
15
  !/\b(Chrome|Chromium|Edg|OPR|SamsungBrowser)\b/.test(userAgent);
@@ -41,9 +41,10 @@ function figSupportsCustomizedBuiltIns() {
41
41
 
42
42
  const figNeedsBuiltInPolyfill =
43
43
  figIsWebKitOrIOSBrowser() && !figSupportsCustomizedBuiltIns();
44
- const figBuiltInPolyfillReady = (figNeedsBuiltInPolyfill
45
- ? import("./polyfills/custom-elements-webkit.js")
46
- : Promise.resolve()
44
+ const figBuiltInPolyfillReady = (
45
+ figNeedsBuiltInPolyfill
46
+ ? import("./polyfills/custom-elements-webkit.js")
47
+ : Promise.resolve()
47
48
  )
48
49
  .then(() => {})
49
50
  .catch((error) => {
@@ -62,14 +63,12 @@ function figDefineCustomizedBuiltIn(name, constructor, options) {
62
63
  return;
63
64
  }
64
65
 
65
- figBuiltInPolyfillReady
66
- .then(define)
67
- .catch((error) => {
68
- console.error(
69
- `[figui3] Failed to load customized built-in polyfill for "${name}".`,
70
- error,
71
- );
72
- });
66
+ figBuiltInPolyfillReady.then(define).catch((error) => {
67
+ console.error(
68
+ `[figui3] Failed to load customized built-in polyfill for "${name}".`,
69
+ error,
70
+ );
71
+ });
73
72
  }
74
73
 
75
74
  function figUniqueId() {
@@ -1208,18 +1207,25 @@ class FigPopup extends HTMLDialogElement {
1208
1207
  }
1209
1208
 
1210
1209
  ensureInitialized() {
1211
- if (typeof this._anchorObserver === "undefined") this._anchorObserver = null;
1212
- if (typeof this._contentObserver === "undefined") this._contentObserver = null;
1213
- if (typeof this._mutationObserver === "undefined") this._mutationObserver = null;
1214
- if (typeof this._anchorTrackRAF === "undefined") this._anchorTrackRAF = null;
1215
- if (typeof this._lastAnchorRect === "undefined") this._lastAnchorRect = null;
1210
+ if (typeof this._anchorObserver === "undefined")
1211
+ this._anchorObserver = null;
1212
+ if (typeof this._contentObserver === "undefined")
1213
+ this._contentObserver = null;
1214
+ if (typeof this._mutationObserver === "undefined")
1215
+ this._mutationObserver = null;
1216
+ if (typeof this._anchorTrackRAF === "undefined")
1217
+ this._anchorTrackRAF = null;
1218
+ if (typeof this._lastAnchorRect === "undefined")
1219
+ this._lastAnchorRect = null;
1216
1220
  if (typeof this._isPopupActive === "undefined") this._isPopupActive = false;
1217
1221
  if (typeof this._rafId === "undefined") this._rafId = null;
1218
1222
  if (typeof this._anchorRef === "undefined") this._anchorRef = null;
1219
1223
  if (typeof this._isDragging === "undefined") this._isDragging = false;
1220
1224
  if (typeof this._dragPending === "undefined") this._dragPending = false;
1221
- if (typeof this._dragStartPos === "undefined") this._dragStartPos = { x: 0, y: 0 };
1222
- if (typeof this._dragOffset === "undefined") this._dragOffset = { x: 0, y: 0 };
1225
+ if (typeof this._dragStartPos === "undefined")
1226
+ this._dragStartPos = { x: 0, y: 0 };
1227
+ if (typeof this._dragOffset === "undefined")
1228
+ this._dragOffset = { x: 0, y: 0 };
1223
1229
  if (typeof this._dragThreshold !== "number") this._dragThreshold = 3;
1224
1230
  if (typeof this._wasDragged === "undefined") this._wasDragged = false;
1225
1231
 
@@ -1228,7 +1234,11 @@ class FigPopup extends HTMLDialogElement {
1228
1234
  }
1229
1235
  if (typeof this._boundScroll !== "function") {
1230
1236
  this._boundScroll = (e) => {
1231
- if (this.open && !this.contains(e.target) && this.shouldAutoReposition()) {
1237
+ if (
1238
+ this.open &&
1239
+ !this.contains(e.target) &&
1240
+ this.shouldAutoReposition()
1241
+ ) {
1232
1242
  this.queueReposition();
1233
1243
  }
1234
1244
  };
@@ -1516,7 +1526,10 @@ class FigPopup extends HTMLDialogElement {
1516
1526
  const anchor = this.resolveAnchor();
1517
1527
  const nextRect = this.readRectSnapshot(anchor);
1518
1528
  const canAutoReposition = this.shouldAutoReposition();
1519
- if (canAutoReposition && this.hasRectChanged(this._lastAnchorRect, nextRect)) {
1529
+ if (
1530
+ canAutoReposition &&
1531
+ this.hasRectChanged(this._lastAnchorRect, nextRect)
1532
+ ) {
1520
1533
  this._lastAnchorRect = nextRect;
1521
1534
  this.queueReposition();
1522
1535
  } else if (!canAutoReposition) {
@@ -1989,7 +2002,9 @@ class FigPopup extends HTMLDialogElement {
1989
2002
  const anchorCenterY = anchorRect.top + anchorRect.height / 2;
1990
2003
  const measuredRect = this.getBoundingClientRect();
1991
2004
  const rect =
1992
- measuredRect.width > 0 && measuredRect.height > 0 ? measuredRect : popupRect;
2005
+ measuredRect.width > 0 && measuredRect.height > 0
2006
+ ? measuredRect
2007
+ : popupRect;
1993
2008
  // Always use the rendered popup rect so beak alignment matches real final placement.
1994
2009
  const resolvedLeft = rect.left;
1995
2010
  const resolvedTop = rect.top;
@@ -2082,14 +2097,7 @@ class FigPopup extends HTMLDialogElement {
2082
2097
  let bestScore = Number.POSITIVE_INFINITY;
2083
2098
 
2084
2099
  for (const { v, h, s } of candidates) {
2085
- const coords = this.computeCoords(
2086
- anchorRect,
2087
- popupRect,
2088
- v,
2089
- h,
2090
- offset,
2091
- s,
2092
- );
2100
+ const coords = this.computeCoords(anchorRect, popupRect, v, h, offset, s);
2093
2101
  const placementSide = this.getPlacementSide(v, h, s);
2094
2102
 
2095
2103
  if (s) {
@@ -3102,11 +3110,7 @@ class FigSlider extends HTMLElement {
3102
3110
  break;
3103
3111
  case "default":
3104
3112
  this.default =
3105
- newValue !== null
3106
- ? newValue
3107
- : this.type === "delta"
3108
- ? 0
3109
- : this.min;
3113
+ newValue !== null ? newValue : this.type === "delta" ? 0 : this.min;
3110
3114
  this.#syncProperties();
3111
3115
  break;
3112
3116
  case "min":
@@ -3172,7 +3176,8 @@ class FigInputText extends HTMLElement {
3172
3176
  this.placeholder = this.getAttribute("placeholder") || "";
3173
3177
  this.name = this.getAttribute("name") || null;
3174
3178
  this.readonly =
3175
- this.hasAttribute("readonly") && this.getAttribute("readonly") !== "false";
3179
+ this.hasAttribute("readonly") &&
3180
+ this.getAttribute("readonly") !== "false";
3176
3181
 
3177
3182
  if (this.type === "number") {
3178
3183
  if (this.getAttribute("step")) {
@@ -5684,8 +5689,22 @@ class FigChit extends HTMLElement {
5684
5689
  }
5685
5690
  }
5686
5691
 
5692
+ #resolveBackground(bg) {
5693
+ if (!bg || !bg.includes("var(")) return bg;
5694
+ const prev = this.style.background;
5695
+ this.style.background = bg;
5696
+ const cs = getComputedStyle(this);
5697
+ const bgImage = cs.backgroundImage;
5698
+ const bgColor = cs.backgroundColor;
5699
+ this.style.background = prev;
5700
+ if (bgImage && bgImage !== "none") return bgImage;
5701
+ return bgColor || bg;
5702
+ }
5703
+
5687
5704
  #render() {
5688
- const bg = this.getAttribute("background") || "#D9D9D9";
5705
+ const rawBg = this.getAttribute("background") || "#D9D9D9";
5706
+ const isVar = rawBg.includes("var(");
5707
+ const bg = isVar ? this.#resolveBackground(rawBg) : rawBg;
5689
5708
  const newType = this.#detectType(bg);
5690
5709
 
5691
5710
  // Only rebuild DOM if type changes
@@ -5702,21 +5721,22 @@ class FigChit extends HTMLElement {
5702
5721
  const hex = this.#toHex(bg);
5703
5722
  this.innerHTML = `<input type="color" value="${hex}" />`;
5704
5723
  this.input = this.querySelector("input");
5705
- this.input.addEventListener("input", this.#boundHandleInput);
5724
+ if (!isVar) {
5725
+ this.input.addEventListener("input", this.#boundHandleInput);
5726
+ }
5706
5727
  } else {
5707
5728
  this.innerHTML = "";
5708
5729
  this.input = null;
5709
5730
  }
5710
5731
  } else if (this.#type === "color" && this.input) {
5711
- // Just update input value without rebuilding DOM
5712
5732
  const hex = this.#toHex(bg);
5713
5733
  if (this.input.value !== hex) {
5714
5734
  this.input.value = hex;
5715
5735
  }
5716
5736
  }
5717
5737
 
5718
- // Always update CSS variable
5719
- this.style.setProperty("--chit-background", bg);
5738
+ // Always update CSS variable with raw value so vars stay reactive
5739
+ this.style.setProperty("--chit-background", rawBg);
5720
5740
  }
5721
5741
 
5722
5742
  #handleInput(e) {
@@ -5783,9 +5803,9 @@ class FigImage extends HTMLElement {
5783
5803
  super();
5784
5804
  }
5785
5805
  #getInnerHTML() {
5786
- return `<fig-chit size="large" background="${
5787
- this.src ? `url(${this.src})` : "url()"
5788
- }" disabled></fig-chit><div>${
5806
+ const cb = this.hasAttribute("checkerboard") && this.getAttribute("checkerboard") !== "false";
5807
+ const bg = this.src ? `url(${this.src})` : (cb ? "url()" : "var(--figma-color-bg-secondary)");
5808
+ return `<fig-chit size="large" data-type="image" background="${bg}" disabled${cb ? ' checkerboard' : ''}></fig-chit><div>${
5789
5809
  this.upload
5790
5810
  ? `<fig-button variant="overlay" type="upload">
5791
5811
  ${this.label}
@@ -5946,7 +5966,7 @@ class FigImage extends HTMLElement {
5946
5966
  this.setAttribute("src", this.blob);
5947
5967
  }
5948
5968
  static get observedAttributes() {
5949
- return ["src", "upload", "download", "aspect-ratio", "fit"];
5969
+ return ["src", "upload", "download", "aspect-ratio", "fit", "checkerboard"];
5950
5970
  }
5951
5971
  get src() {
5952
5972
  return this.#src;
@@ -5960,10 +5980,12 @@ class FigImage extends HTMLElement {
5960
5980
  if (name === "src") {
5961
5981
  this.#src = newValue;
5962
5982
  if (this.chit) {
5963
- this.chit.setAttribute(
5964
- "background",
5965
- this.#src ? `url(${this.#src})` : "",
5966
- );
5983
+ const hasCb = this.hasAttribute("checkerboard") && this.getAttribute("checkerboard") !== "false";
5984
+ if (this.#src) {
5985
+ this.chit.setAttribute("background", `url(${this.#src})`);
5986
+ } else {
5987
+ this.chit.setAttribute("background", hasCb ? "url()" : "var(--figma-color-bg-secondary)");
5988
+ }
5967
5989
  }
5968
5990
  if (this.#src) {
5969
5991
  this.#loadImage(this.#src);
@@ -5996,6 +6018,15 @@ class FigImage extends HTMLElement {
5996
6018
  this.style.removeProperty("--fit");
5997
6019
  }
5998
6020
  }
6021
+ if (name === "checkerboard") {
6022
+ if (this.chit) {
6023
+ if (newValue !== null && newValue !== "false") {
6024
+ this.chit.setAttribute("checkerboard", "");
6025
+ } else {
6026
+ this.chit.removeAttribute("checkerboard");
6027
+ }
6028
+ }
6029
+ }
5999
6030
  }
6000
6031
  }
6001
6032
  customElements.define("fig-image", FigImage);
@@ -6714,7 +6745,9 @@ class FigEasingCurve extends HTMLElement {
6714
6745
  this.#startBezierDrag(e, 2),
6715
6746
  );
6716
6747
 
6717
- const bezierSurface = this.querySelector(".fig-easing-curve-svg-container");
6748
+ const bezierSurface = this.querySelector(
6749
+ ".fig-easing-curve-svg-container",
6750
+ );
6718
6751
  if (bezierSurface) {
6719
6752
  bezierSurface.addEventListener("pointerdown", (e) => {
6720
6753
  // Handles keep their own direct drag behavior.
@@ -6732,7 +6765,9 @@ class FigEasingCurve extends HTMLElement {
6732
6765
  this.#startSpringDrag(e, "duration");
6733
6766
  });
6734
6767
 
6735
- const springSurface = this.querySelector(".fig-easing-curve-svg-container");
6768
+ const springSurface = this.querySelector(
6769
+ ".fig-easing-curve-svg-container",
6770
+ );
6736
6771
  if (springSurface) {
6737
6772
  springSurface.addEventListener("pointerdown", (e) => {
6738
6773
  // Bounce handle keeps its own drag mode/cursor.
@@ -6902,14 +6937,27 @@ class Fig3DRotate extends HTMLElement {
6902
6937
  #fieldInputs = {};
6903
6938
 
6904
6939
  static get observedAttributes() {
6905
- return ["value", "precision", "aspect-ratio", "fields", "perspective", "perspective-origin", "transform-origin", "selected", "drag"];
6940
+ return [
6941
+ "value",
6942
+ "precision",
6943
+ "aspect-ratio",
6944
+ "fields",
6945
+ "perspective",
6946
+ "perspective-origin",
6947
+ "transform-origin",
6948
+ "selected",
6949
+ "drag",
6950
+ ];
6906
6951
  }
6907
6952
 
6908
6953
  connectedCallback() {
6909
6954
  this.#precision = parseInt(this.getAttribute("precision") || "1");
6910
6955
  this.#syncAspectRatioVar(this.getAttribute("aspect-ratio"));
6911
6956
  this.#syncPerspectiveVar(this.getAttribute("perspective"));
6912
- this.#syncCSSVar("--perspective-origin", this.getAttribute("perspective-origin"));
6957
+ this.#syncCSSVar(
6958
+ "--perspective-origin",
6959
+ this.getAttribute("perspective-origin"),
6960
+ );
6913
6961
  this.#syncTransformOrigin(this.getAttribute("transform-origin"));
6914
6962
  this.#parseFields(this.getAttribute("fields"));
6915
6963
  const val = this.getAttribute("value");
@@ -6958,7 +7006,10 @@ class Fig3DRotate extends HTMLElement {
6958
7006
  }
6959
7007
  const parts = value.trim().split(/\s+/);
6960
7008
  if (parts.length === 2) {
6961
- this.style.setProperty("--transform-origin", `${parts[0]} ${parts[1]} -50cqi`);
7009
+ this.style.setProperty(
7010
+ "--transform-origin",
7011
+ `${parts[0]} ${parts[1]} -50cqi`,
7012
+ );
6962
7013
  } else {
6963
7014
  this.style.setProperty("--transform-origin", value.trim());
6964
7015
  }
@@ -6974,7 +7025,10 @@ class Fig3DRotate extends HTMLElement {
6974
7025
  const faces = this.#cube.querySelectorAll(".fig-3d-rotate-face");
6975
7026
  const name = value ? value.trim().toLowerCase() : "";
6976
7027
  for (const face of faces) {
6977
- face.classList.toggle("selected", name !== "" && face.classList.contains(name));
7028
+ face.classList.toggle(
7029
+ "selected",
7030
+ name !== "" && face.classList.contains(name),
7031
+ );
6978
7032
  }
6979
7033
  }
6980
7034
 
@@ -7062,7 +7116,11 @@ class Fig3DRotate extends HTMLElement {
7062
7116
 
7063
7117
  #render() {
7064
7118
  const axisLabels = { rotateX: "X", rotateY: "Y", rotateZ: "Z" };
7065
- const axisValues = { rotateX: this.#rx, rotateY: this.#ry, rotateZ: this.#rz };
7119
+ const axisValues = {
7120
+ rotateX: this.#rx,
7121
+ rotateY: this.#ry,
7122
+ rotateZ: this.#rz,
7123
+ };
7066
7124
  const fieldsHTML = this.#fields
7067
7125
  .map(
7068
7126
  (axis) =>
@@ -7115,17 +7173,21 @@ class Fig3DRotate extends HTMLElement {
7115
7173
  }
7116
7174
 
7117
7175
  #syncFieldInputs() {
7118
- const axisValues = { rotateX: this.#rx, rotateY: this.#ry, rotateZ: this.#rz };
7176
+ const axisValues = {
7177
+ rotateX: this.#rx,
7178
+ rotateY: this.#ry,
7179
+ rotateZ: this.#rz,
7180
+ };
7119
7181
  for (const axis of this.#fields) {
7120
7182
  const input = this.#fieldInputs[axis];
7121
- if (input) input.setAttribute("value", axisValues[axis].toFixed(this.#precision));
7183
+ if (input)
7184
+ input.setAttribute("value", axisValues[axis].toFixed(this.#precision));
7122
7185
  }
7123
7186
  }
7124
7187
 
7125
7188
  #updateCube() {
7126
7189
  if (!this.#cube) return;
7127
- this.#cube.style.transform =
7128
- `rotateX(${this.#rx}deg) rotateY(${this.#ry}deg) rotateZ(${this.#rz}deg)`;
7190
+ this.#cube.style.transform = `rotateX(${this.#rx}deg) rotateY(${this.#ry}deg) rotateZ(${this.#rz}deg)`;
7129
7191
  }
7130
7192
 
7131
7193
  #emit(type) {
@@ -7339,11 +7401,7 @@ class FigOriginGrid extends HTMLElement {
7339
7401
  }
7340
7402
 
7341
7403
  #parseValue(value) {
7342
- const parts = value
7343
- .trim()
7344
- .replace(/,/g, " ")
7345
- .split(/\s+/)
7346
- .filter(Boolean);
7404
+ const parts = value.trim().replace(/,/g, " ").split(/\s+/).filter(Boolean);
7347
7405
  if (parts.length < 1) return;
7348
7406
 
7349
7407
  if (parts.length === 1) {
@@ -7439,7 +7497,8 @@ class FigOriginGrid extends HTMLElement {
7439
7497
  #syncHandlePosition() {
7440
7498
  if (!this.#handle) return;
7441
7499
  // Constrain draggable visual bounds to the 3x3 dot centers.
7442
- const toVisual = (value) => 16.6667 + (this.#clampPercentage(value) / 100) * 66.6667;
7500
+ const toVisual = (value) =>
7501
+ 16.6667 + (this.#clampPercentage(value) / 100) * 66.6667;
7443
7502
  this.#handle.style.left = `${toVisual(this.#x)}%`;
7444
7503
  this.#handle.style.top = `${toVisual(this.#y)}%`;
7445
7504
  }
@@ -7553,10 +7612,18 @@ class FigOriginGrid extends HTMLElement {
7553
7612
  }
7554
7613
 
7555
7614
  #detachHandleDragListeners() {
7556
- if (!this.#grid || !this.#boundHandlePointerMove || !this.#boundHandlePointerEnd) return;
7615
+ if (
7616
+ !this.#grid ||
7617
+ !this.#boundHandlePointerMove ||
7618
+ !this.#boundHandlePointerEnd
7619
+ )
7620
+ return;
7557
7621
  this.#grid.removeEventListener("pointermove", this.#boundHandlePointerMove);
7558
7622
  this.#grid.removeEventListener("pointerup", this.#boundHandlePointerEnd);
7559
- this.#grid.removeEventListener("pointercancel", this.#boundHandlePointerEnd);
7623
+ this.#grid.removeEventListener(
7624
+ "pointercancel",
7625
+ this.#boundHandlePointerEnd,
7626
+ );
7560
7627
  this.#grid.removeEventListener(
7561
7628
  "lostpointercapture",
7562
7629
  this.#boundHandlePointerEnd,
@@ -7577,7 +7644,8 @@ class FigOriginGrid extends HTMLElement {
7577
7644
  this.#grid.setPointerCapture(e.pointerId);
7578
7645
 
7579
7646
  this.#boundHandlePointerMove = (moveEvent) => {
7580
- if (!this.#isDragging || moveEvent.pointerId !== this.#activePointerId) return;
7647
+ if (!this.#isDragging || moveEvent.pointerId !== this.#activePointerId)
7648
+ return;
7581
7649
  const dx = moveEvent.clientX - startClientX;
7582
7650
  const dy = moveEvent.clientY - startClientY;
7583
7651
  const distance = Math.hypot(dx, dy);
@@ -7595,7 +7663,8 @@ class FigOriginGrid extends HTMLElement {
7595
7663
  };
7596
7664
 
7597
7665
  this.#boundHandlePointerEnd = (endEvent) => {
7598
- if (!this.#isDragging || endEvent.pointerId !== this.#activePointerId) return;
7666
+ if (!this.#isDragging || endEvent.pointerId !== this.#activePointerId)
7667
+ return;
7599
7668
  this.#isDragging = false;
7600
7669
  this.#activePointerId = null;
7601
7670
  this.#grid.classList.remove("is-dragging");
@@ -7612,7 +7681,10 @@ class FigOriginGrid extends HTMLElement {
7612
7681
  this.#grid.addEventListener("pointermove", this.#boundHandlePointerMove);
7613
7682
  this.#grid.addEventListener("pointerup", this.#boundHandlePointerEnd);
7614
7683
  this.#grid.addEventListener("pointercancel", this.#boundHandlePointerEnd);
7615
- this.#grid.addEventListener("lostpointercapture", this.#boundHandlePointerEnd);
7684
+ this.#grid.addEventListener(
7685
+ "lostpointercapture",
7686
+ this.#boundHandlePointerEnd,
7687
+ );
7616
7688
  }
7617
7689
 
7618
7690
  #setupEvents() {
@@ -8064,7 +8136,8 @@ class FigInputJoystick extends HTMLElement {
8064
8136
  const isPercent = token.includes("%");
8065
8137
  const numeric = Number.parseFloat(token.replace(/%/g, "").trim());
8066
8138
  if (!Number.isFinite(numeric)) return 0.5;
8067
- const decimal = isPercent || Math.abs(numeric) > 1 ? numeric / 100 : numeric;
8139
+ const decimal =
8140
+ isPercent || Math.abs(numeric) > 1 ? numeric / 100 : numeric;
8068
8141
  return Math.max(0, Math.min(1, decimal));
8069
8142
  };
8070
8143
  const x = parseAxis(parts[0]);
@@ -10480,7 +10553,9 @@ class FigChooser extends HTMLElement {
10480
10553
  }
10481
10554
 
10482
10555
  get #overflowMode() {
10483
- return this.getAttribute("overflow") === "scrollbar" ? "scrollbar" : "buttons";
10556
+ return this.getAttribute("overflow") === "scrollbar"
10557
+ ? "scrollbar"
10558
+ : "buttons";
10484
10559
  }
10485
10560
 
10486
10561
  get #dragEnabled() {
@@ -10730,12 +10805,14 @@ class FigChooser extends HTMLElement {
10730
10805
 
10731
10806
  if (isHorizontal) {
10732
10807
  const atStart = this.scrollLeft <= threshold;
10733
- const atEnd = this.scrollLeft + this.clientWidth >= this.scrollWidth - threshold;
10808
+ const atEnd =
10809
+ this.scrollLeft + this.clientWidth >= this.scrollWidth - threshold;
10734
10810
  this.classList.toggle("overflow-start", !atStart);
10735
10811
  this.classList.toggle("overflow-end", !atEnd);
10736
10812
  } else {
10737
10813
  const atStart = this.scrollTop <= threshold;
10738
- const atEnd = this.scrollTop + this.clientHeight >= this.scrollHeight - threshold;
10814
+ const atEnd =
10815
+ this.scrollTop + this.clientHeight >= this.scrollHeight - threshold;
10739
10816
  this.classList.toggle("overflow-start", !atStart);
10740
10817
  this.classList.toggle("overflow-end", !atEnd);
10741
10818
  }
@@ -10800,7 +10877,9 @@ class FigChooser extends HTMLElement {
10800
10877
  this.style.cursor = "";
10801
10878
  this.style.userSelect = "";
10802
10879
  if (e.pointerId !== undefined) {
10803
- try { this.releasePointerCapture(e.pointerId); } catch {}
10880
+ try {
10881
+ this.releasePointerCapture(e.pointerId);
10882
+ } catch {}
10804
10883
  }
10805
10884
  if (wasDrag) {
10806
10885
  e.preventDefault();
@@ -10853,7 +10932,11 @@ class FigChooser extends HTMLElement {
10853
10932
  this.removeEventListener("pointerdown", this.#dragState.onPointerDown);
10854
10933
  window.removeEventListener("pointermove", this.#dragState.onPointerMove);
10855
10934
  window.removeEventListener("pointerup", this.#dragState.onPointerUp);
10856
- this.removeEventListener("pointerup", this.#dragState.onPointerUpCapture, true);
10935
+ this.removeEventListener(
10936
+ "pointerup",
10937
+ this.#dragState.onPointerUpCapture,
10938
+ true,
10939
+ );
10857
10940
  this.removeEventListener("click", this.#dragState.onClick, true);
10858
10941
  this.style.cursor = "";
10859
10942
  this.style.userSelect = "";
@@ -10904,8 +10987,7 @@ class FigChooser extends HTMLElement {
10904
10987
  }
10905
10988
 
10906
10989
  #scrollByPage(direction) {
10907
- const isHorizontal =
10908
- this.getAttribute("layout") === "horizontal";
10990
+ const isHorizontal = this.getAttribute("layout") === "horizontal";
10909
10991
  const pageSize = isHorizontal ? this.clientWidth : this.clientHeight;
10910
10992
  const scrollAmount = pageSize * 0.8 * direction;
10911
10993
 
@@ -10925,12 +11007,14 @@ class FigChooser extends HTMLElement {
10925
11007
  const options = { behavior: "smooth" };
10926
11008
 
10927
11009
  if (overflowY) {
10928
- const target = el.offsetTop - this.clientHeight / 2 + el.offsetHeight / 2;
11010
+ const target =
11011
+ el.offsetTop - this.clientHeight / 2 + el.offsetHeight / 2;
10929
11012
  options.top = target;
10930
11013
  }
10931
11014
 
10932
11015
  if (overflowX) {
10933
- const target = el.offsetLeft - this.clientWidth / 2 + el.offsetWidth / 2;
11016
+ const target =
11017
+ el.offsetLeft - this.clientWidth / 2 + el.offsetWidth / 2;
10934
11018
  options.left = target;
10935
11019
  }
10936
11020
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "3.4.3",
3
+ "version": "3.5.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",