@rogieking/figui3 2.33.3 → 2.34.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 +45 -3
  2. package/fig.js +56 -13
  3. package/package.json +1 -1
package/components.css CHANGED
@@ -1439,10 +1439,18 @@ fig-3d-rotate {
1439
1439
  gap: var(--spacer-2);
1440
1440
  width: 100%;
1441
1441
  --aspect-ratio: 1 / 1;
1442
+ --perspective: 20rem;
1442
1443
  --gradient-start-color: light-dark(
1443
1444
  rgba(0, 0, 0, 0.05),
1444
1445
  rgba(255, 255, 255, 0.05)
1445
1446
  );
1447
+ --border-width: 1px;
1448
+ --border-start-color: light-dark(
1449
+ rgba(0, 0, 0, 0.15),
1450
+ rgba(255, 255, 255, 0.15)
1451
+ );
1452
+ --border-end-color: transparent;
1453
+ --border-end-color: transparent;
1446
1454
  --gradient-end-color: transparent;
1447
1455
  --figma-3d-rotate-handle-size: 6px;
1448
1456
  --front-face-bg: light-dark(var(--figma-color-bg), #555);
@@ -1484,7 +1492,8 @@ fig-3d-rotate {
1484
1492
  aspect-ratio: 1 / 1;
1485
1493
  max-height: max(3.5rem, 50%);
1486
1494
  max-width: max(3.5rem, 50%);
1487
- perspective: 20rem;
1495
+ perspective: var(--perspective, 20rem);
1496
+ container-type: inline-size;
1488
1497
  }
1489
1498
 
1490
1499
  .fig-3d-rotate-cube {
@@ -1493,6 +1502,7 @@ fig-3d-rotate {
1493
1502
  position: relative;
1494
1503
  aspect-ratio: 1 / 1;
1495
1504
  transform-style: preserve-3d;
1505
+ transform-origin: 50% 50% -50cqi;
1496
1506
  }
1497
1507
 
1498
1508
  .fig-3d-rotate-face {
@@ -1531,8 +1541,8 @@ fig-3d-rotate {
1531
1541
  rotateY(-0.25turn);
1532
1542
  background: linear-gradient(
1533
1543
  to bottom,
1534
- var(--gradient-start-color),
1535
- var(--gradient-start-color)
1544
+ var(--border-start-color),
1545
+ var(--border-end-color)
1536
1546
  );
1537
1547
  border-radius: var(--radius-medium);
1538
1548
  }
@@ -1544,6 +1554,14 @@ fig-3d-rotate {
1544
1554
  var(--gradient-start-color),
1545
1555
  var(--gradient-end-color)
1546
1556
  );
1557
+ border-width: var(--border-width) 0;
1558
+ border-style: solid;
1559
+ border-image: linear-gradient(
1560
+ to right,
1561
+ var(--border-start-color),
1562
+ var(--border-end-color)
1563
+ )
1564
+ 1;
1547
1565
  }
1548
1566
  &.left {
1549
1567
  transform-origin: 100% 50%;
@@ -1553,6 +1571,14 @@ fig-3d-rotate {
1553
1571
  var(--gradient-start-color),
1554
1572
  var(--gradient-end-color)
1555
1573
  );
1574
+ border-width: var(--border-width) 0;
1575
+ border-style: solid;
1576
+ border-image: linear-gradient(
1577
+ to left,
1578
+ var(--border-start-color),
1579
+ var(--border-end-color)
1580
+ )
1581
+ 1;
1556
1582
  }
1557
1583
  &.top {
1558
1584
  translate: 0 -100%;
@@ -1563,6 +1589,14 @@ fig-3d-rotate {
1563
1589
  var(--gradient-start-color),
1564
1590
  var(--gradient-end-color)
1565
1591
  );
1592
+ border-width: 0 var(--border-width);
1593
+ border-style: solid;
1594
+ border-image: linear-gradient(
1595
+ to top,
1596
+ var(--border-start-color),
1597
+ var(--border-end-color)
1598
+ )
1599
+ 1;
1566
1600
  }
1567
1601
  &.bottom {
1568
1602
  top: 100%;
@@ -1574,6 +1608,14 @@ fig-3d-rotate {
1574
1608
  var(--gradient-start-color),
1575
1609
  var(--gradient-end-color)
1576
1610
  );
1611
+ border-width: 0 var(--border-width);
1612
+ border-style: solid;
1613
+ border-image: linear-gradient(
1614
+ to bottom,
1615
+ var(--border-start-color),
1616
+ var(--border-end-color)
1617
+ )
1618
+ 1;
1577
1619
  }
1578
1620
  }
1579
1621
  }
package/fig.js CHANGED
@@ -2726,6 +2726,7 @@ class FigInputText extends HTMLElement {
2726
2726
  #isInteracting = false;
2727
2727
  #boundMouseMove;
2728
2728
  #boundMouseUp;
2729
+ #boundWindowBlur;
2729
2730
  #boundMouseDown;
2730
2731
  #boundInputChange;
2731
2732
 
@@ -2734,6 +2735,7 @@ class FigInputText extends HTMLElement {
2734
2735
  // Pre-bind the event handlers once
2735
2736
  this.#boundMouseMove = this.#handleMouseMove.bind(this);
2736
2737
  this.#boundMouseUp = this.#handleMouseUp.bind(this);
2738
+ this.#boundWindowBlur = this.#handleMouseUp.bind(this);
2737
2739
  this.#boundMouseDown = this.#handleMouseDown.bind(this);
2738
2740
  this.#boundInputChange = (e) => {
2739
2741
  e.stopPropagation();
@@ -2831,6 +2833,7 @@ class FigInputText extends HTMLElement {
2831
2833
  this.removeEventListener("pointerdown", this.#boundMouseDown);
2832
2834
  window.removeEventListener("pointermove", this.#boundMouseMove);
2833
2835
  window.removeEventListener("pointerup", this.#boundMouseUp);
2836
+ window.removeEventListener("blur", this.#boundWindowBlur);
2834
2837
  }
2835
2838
 
2836
2839
  focus() {
@@ -2862,6 +2865,10 @@ class FigInputText extends HTMLElement {
2862
2865
  }
2863
2866
  #handleMouseMove(e) {
2864
2867
  if (this.type !== "number") return;
2868
+ if (e.buttons === 0) {
2869
+ this.#handleMouseUp();
2870
+ return;
2871
+ }
2865
2872
  let step = (this.step || 1) * e.movementX;
2866
2873
  let value = Number(this.input.value);
2867
2874
  value = value / (this.transform || 1) + step;
@@ -2885,6 +2892,7 @@ class FigInputText extends HTMLElement {
2885
2892
  this.style.userSelect = "none";
2886
2893
  window.addEventListener("pointermove", this.#boundMouseMove);
2887
2894
  window.addEventListener("pointerup", this.#boundMouseUp);
2895
+ window.addEventListener("blur", this.#boundWindowBlur);
2888
2896
  }
2889
2897
  }
2890
2898
  #handleMouseUp(e) {
@@ -2897,6 +2905,7 @@ class FigInputText extends HTMLElement {
2897
2905
  this.style.userSelect = "all";
2898
2906
  window.removeEventListener("pointermove", this.#boundMouseMove);
2899
2907
  window.removeEventListener("pointerup", this.#boundMouseUp);
2908
+ window.removeEventListener("blur", this.#boundWindowBlur);
2900
2909
  }
2901
2910
  #sanitizeInput(value, transform = true) {
2902
2911
  let sanitized = value;
@@ -3018,6 +3027,7 @@ customElements.define("fig-input-text", FigInputText);
3018
3027
  class FigInputNumber extends HTMLElement {
3019
3028
  #boundMouseMove;
3020
3029
  #boundMouseUp;
3030
+ #boundWindowBlur;
3021
3031
  #boundMouseDown;
3022
3032
  #boundInputChange;
3023
3033
  #boundInput;
@@ -3049,6 +3059,7 @@ class FigInputNumber extends HTMLElement {
3049
3059
  // Pre-bind the event handlers once
3050
3060
  this.#boundMouseMove = this.#handleMouseMove.bind(this);
3051
3061
  this.#boundMouseUp = this.#handleMouseUp.bind(this);
3062
+ this.#boundWindowBlur = this.#handleMouseUp.bind(this);
3052
3063
  this.#boundMouseDown = this.#handleMouseDown.bind(this);
3053
3064
  this.#boundInputChange = (e) => {
3054
3065
  e.stopPropagation();
@@ -3170,6 +3181,7 @@ class FigInputNumber extends HTMLElement {
3170
3181
  this.removeEventListener("pointerdown", this.#boundMouseDown);
3171
3182
  window.removeEventListener("pointermove", this.#boundMouseMove);
3172
3183
  window.removeEventListener("pointerup", this.#boundMouseUp);
3184
+ window.removeEventListener("blur", this.#boundWindowBlur);
3173
3185
  }
3174
3186
 
3175
3187
  focus() {
@@ -3322,6 +3334,10 @@ class FigInputNumber extends HTMLElement {
3322
3334
 
3323
3335
  #handleMouseMove(e) {
3324
3336
  if (this.disabled) return;
3337
+ if (e.buttons === 0) {
3338
+ this.#handleMouseUp();
3339
+ return;
3340
+ }
3325
3341
  let step = (this.step || 1) * e.movementX;
3326
3342
  let numericValue = this.#getNumericValue(this.input.value);
3327
3343
  let value = Number(numericValue) / (this.transform || 1) + step;
@@ -3343,6 +3359,7 @@ class FigInputNumber extends HTMLElement {
3343
3359
  this.style.userSelect = "none";
3344
3360
  window.addEventListener("pointermove", this.#boundMouseMove);
3345
3361
  window.addEventListener("pointerup", this.#boundMouseUp);
3362
+ window.addEventListener("blur", this.#boundWindowBlur);
3346
3363
  }
3347
3364
  }
3348
3365
 
@@ -3355,6 +3372,7 @@ class FigInputNumber extends HTMLElement {
3355
3372
  this.style.userSelect = "all";
3356
3373
  window.removeEventListener("pointermove", this.#boundMouseMove);
3357
3374
  window.removeEventListener("pointerup", this.#boundMouseUp);
3375
+ window.removeEventListener("blur", this.#boundWindowBlur);
3358
3376
  }
3359
3377
 
3360
3378
  #sanitizeInput(value, transform = true) {
@@ -6444,12 +6462,13 @@ class Fig3DRotate extends HTMLElement {
6444
6462
  #fieldInputs = {};
6445
6463
 
6446
6464
  static get observedAttributes() {
6447
- return ["value", "precision", "aspect-ratio", "fields"];
6465
+ return ["value", "precision", "aspect-ratio", "fields", "perspective"];
6448
6466
  }
6449
6467
 
6450
6468
  connectedCallback() {
6451
6469
  this.#precision = parseInt(this.getAttribute("precision") || "1");
6452
6470
  this.#syncAspectRatioVar(this.getAttribute("aspect-ratio"));
6471
+ this.#syncPerspectiveVar(this.getAttribute("perspective"));
6453
6472
  this.#parseFields(this.getAttribute("fields"));
6454
6473
  const val = this.getAttribute("value");
6455
6474
  if (val) this.#parseValue(val);
@@ -6472,6 +6491,14 @@ class Fig3DRotate extends HTMLElement {
6472
6491
  }
6473
6492
  }
6474
6493
 
6494
+ #syncPerspectiveVar(value) {
6495
+ if (value && value.trim()) {
6496
+ this.style.setProperty("--perspective", value.trim());
6497
+ } else {
6498
+ this.style.removeProperty("--perspective");
6499
+ }
6500
+ }
6501
+
6475
6502
  #parseFields(str) {
6476
6503
  if (!str || !str.trim()) {
6477
6504
  this.#fields = [];
@@ -6489,6 +6516,10 @@ class Fig3DRotate extends HTMLElement {
6489
6516
  this.#syncAspectRatioVar(newValue);
6490
6517
  return;
6491
6518
  }
6519
+ if (name === "perspective") {
6520
+ this.#syncPerspectiveVar(newValue);
6521
+ return;
6522
+ }
6492
6523
  if (name === "fields") {
6493
6524
  this.#parseFields(newValue);
6494
6525
  if (this.#cube) this.#render();
@@ -6651,10 +6682,12 @@ class Fig3DRotate extends HTMLElement {
6651
6682
  this.#rx = this.#snapToIncrement(startRx - dy * 0.5);
6652
6683
  this.#updateCube();
6653
6684
  this.#syncFieldInputs();
6685
+ this.setAttribute("value", this.value);
6654
6686
  this.#emit("input");
6655
6687
  };
6656
6688
 
6657
6689
  const onUp = () => {
6690
+ this.setAttribute("value", this.value);
6658
6691
  this.#isDragging = false;
6659
6692
  this.#container.classList.remove("dragging");
6660
6693
  document.removeEventListener("pointermove", onMove);
@@ -8240,6 +8273,12 @@ class FigFillPicker extends HTMLElement {
8240
8273
  #setupColorAreaEvents() {
8241
8274
  if (!this.#colorArea || !this.#colorAreaHandle) return;
8242
8275
 
8276
+ const endColorDrag = () => {
8277
+ if (!this.#isDraggingColor) return;
8278
+ this.#isDraggingColor = false;
8279
+ this.#emitChange();
8280
+ };
8281
+
8243
8282
  const updateFromEvent = (e) => {
8244
8283
  const rect = this.#colorArea.getBoundingClientRect();
8245
8284
  const x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
@@ -8261,15 +8300,17 @@ class FigFillPicker extends HTMLElement {
8261
8300
  });
8262
8301
 
8263
8302
  this.#colorArea.addEventListener("pointermove", (e) => {
8264
- if (this.#isDraggingColor) {
8265
- updateFromEvent(e);
8303
+ if (!this.#isDraggingColor) return;
8304
+ if (e.buttons === 0) {
8305
+ endColorDrag();
8306
+ return;
8266
8307
  }
8308
+ updateFromEvent(e);
8267
8309
  });
8268
8310
 
8269
- this.#colorArea.addEventListener("pointerup", () => {
8270
- this.#isDraggingColor = false;
8271
- this.#emitChange();
8272
- });
8311
+ this.#colorArea.addEventListener("pointerup", endColorDrag);
8312
+ this.#colorArea.addEventListener("pointercancel", endColorDrag);
8313
+ this.#colorArea.addEventListener("lostpointercapture", endColorDrag);
8273
8314
 
8274
8315
  // Handle drag (for when handle is at corners)
8275
8316
  this.#colorAreaHandle.addEventListener("pointerdown", (e) => {
@@ -8279,15 +8320,17 @@ class FigFillPicker extends HTMLElement {
8279
8320
  });
8280
8321
 
8281
8322
  this.#colorAreaHandle.addEventListener("pointermove", (e) => {
8282
- if (this.#isDraggingColor) {
8283
- updateFromEvent(e);
8323
+ if (!this.#isDraggingColor) return;
8324
+ if (e.buttons === 0) {
8325
+ endColorDrag();
8326
+ return;
8284
8327
  }
8328
+ updateFromEvent(e);
8285
8329
  });
8286
8330
 
8287
- this.#colorAreaHandle.addEventListener("pointerup", () => {
8288
- this.#isDraggingColor = false;
8289
- this.#emitChange();
8290
- });
8331
+ this.#colorAreaHandle.addEventListener("pointerup", endColorDrag);
8332
+ this.#colorAreaHandle.addEventListener("pointercancel", endColorDrag);
8333
+ this.#colorAreaHandle.addEventListener("lostpointercapture", endColorDrag);
8291
8334
  }
8292
8335
 
8293
8336
  #updateColorInputs() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "2.33.3",
3
+ "version": "2.34.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",