@rogieking/figui3 2.11.0 → 2.12.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 +9 -9
- package/fig.js +198 -119
- package/package.json +1 -1
package/components.css
CHANGED
|
@@ -308,20 +308,20 @@
|
|
|
308
308
|
0px 10px 24px rgba(0, 0, 0, 0.18), 0px 2px 5px rgba(0, 0, 0, 0.15);
|
|
309
309
|
--figma-elevation-100: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.3),
|
|
310
310
|
0px 1px 3px 0px rgba(0, 0, 0, 0.15);
|
|
311
|
-
--figma-elevation-200:
|
|
312
|
-
|
|
311
|
+
--figma-elevation-200: 0 0 0.5px 0 rgba(0, 0, 0, 0.18),
|
|
312
|
+
0 3px 8px 0 rgba(0, 0, 0, 0.1), 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
|
313
313
|
--figma-elevation-400-menu-panel: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.12),
|
|
314
314
|
0px 10px 16px 0px rgba(0, 0, 0, 0.12), 0px 2px 5px 0px rgba(0, 0, 0, 0.15);
|
|
315
315
|
--figma-elevation-500-modal-window: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.08),
|
|
316
316
|
0px 10px 24px 0px rgba(0, 0, 0, 0.18), 0px 2px 5px 0px rgba(0, 0, 0, 0.15);
|
|
317
|
-
--handle-shadow: 0px 0 0 0.5px rgba(0, 0, 0, 0.1), var(--figma-elevation-
|
|
317
|
+
--handle-shadow: 0px 0 0 0.5px rgba(0, 0, 0, 0.1), var(--figma-elevation-100);
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
/* Dark theme overrides for non-color values (shadows, elevations) */
|
|
321
321
|
/* These cannot use light-dark() as they are complex values */
|
|
322
322
|
@media (prefers-color-scheme: dark) {
|
|
323
323
|
:root {
|
|
324
|
-
--handle-shadow: 0px 0 0 0.75px
|
|
324
|
+
--handle-shadow: 0px 0 0 0.75px rgba(0, 0, 0, 0.1),
|
|
325
325
|
0px 0px 0.5px 0px rgba(255, 255, 255, 0.1);
|
|
326
326
|
--figma-elevation-100: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.5),
|
|
327
327
|
0px 0.75px 0px 0px rgba(255, 255, 255, 0.1) inset,
|
|
@@ -343,7 +343,7 @@
|
|
|
343
343
|
|
|
344
344
|
/* Class-based dark theme override (for manual theme switching) */
|
|
345
345
|
:root.figma-dark {
|
|
346
|
-
--handle-shadow: 0px 0 0 0.75px
|
|
346
|
+
--handle-shadow: 0px 0 0 0.75px rgba(0, 0, 0, 0.1),
|
|
347
347
|
0px 0px 0.5px 0px rgba(255, 255, 255, 0.1);
|
|
348
348
|
--figma-elevation-100: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.5),
|
|
349
349
|
0px 0.75px 0px 0px rgba(255, 255, 255, 0.1) inset,
|
|
@@ -1575,7 +1575,7 @@ fig-slider {
|
|
|
1575
1575
|
--slider-tick-size: calc(var(--slider-height) / 4);
|
|
1576
1576
|
--slider-handle-shadow: inset 0 0 0 calc(4px + 0.5rem * var(--unchanged))
|
|
1577
1577
|
var(--handle-color),
|
|
1578
|
-
0px 0 0 0.5px rgba(0, 0, 0, 0.1), var(--figma-elevation-
|
|
1578
|
+
0px 0 0 0.5px rgba(0, 0, 0, 0.1), var(--figma-elevation-100);
|
|
1579
1579
|
--slider-handle-shadow-focus: inset 0 0 0 4px var(--handle-color),
|
|
1580
1580
|
inset 0 0 0 5px rgba(0, 0, 0, 0.1), var(--handle-shadow),
|
|
1581
1581
|
0 0 0 1px var(--figma-color-border-selected);
|
|
@@ -1862,7 +1862,7 @@ fig-slider {
|
|
|
1862
1862
|
--slider-handle-shadow: inset 0 0 0 calc(6px + 0.5rem * var(--unchanged))
|
|
1863
1863
|
var(--handle-color),
|
|
1864
1864
|
0 0 0 0.75px rgba(0, 0, 0, 0.075), inset 0 0 0 5px rgba(0, 0, 0, 0.1),
|
|
1865
|
-
var(--figma-elevation-
|
|
1865
|
+
var(--figma-elevation-100);
|
|
1866
1866
|
|
|
1867
1867
|
.fig-slider-input-container {
|
|
1868
1868
|
height: var(--slider-height);
|
|
@@ -1891,7 +1891,7 @@ fig-slider {
|
|
|
1891
1891
|
--slider-handle-shadow: inset 0 0 0 calc(6px + 0.5rem * var(--unchanged))
|
|
1892
1892
|
var(--handle-color),
|
|
1893
1893
|
0 0 0 0.75px rgba(0, 0, 0, 0.075), inset 0 0 0 5px rgba(0, 0, 0, 0.1),
|
|
1894
|
-
var(--figma-elevation-
|
|
1894
|
+
var(--figma-elevation-100);
|
|
1895
1895
|
|
|
1896
1896
|
background-color: var(--figma-color-bg-secondary);
|
|
1897
1897
|
border-radius: var(--radius-medium);
|
|
@@ -2643,7 +2643,7 @@ fig-input-angle {
|
|
|
2643
2643
|
grid-area: 1/1;
|
|
2644
2644
|
width: calc(0.5rem + 2px);
|
|
2645
2645
|
height: calc(0.5rem + 2px);
|
|
2646
|
-
|
|
2646
|
+
&::before {
|
|
2647
2647
|
content: "";
|
|
2648
2648
|
display: block;
|
|
2649
2649
|
width: 0.5rem;
|
package/fig.js
CHANGED
|
@@ -235,7 +235,7 @@ class FigDropdown extends HTMLElement {
|
|
|
235
235
|
detail: selectedValue,
|
|
236
236
|
bubbles: true,
|
|
237
237
|
composed: true,
|
|
238
|
-
})
|
|
238
|
+
})
|
|
239
239
|
);
|
|
240
240
|
}
|
|
241
241
|
|
|
@@ -252,7 +252,7 @@ class FigDropdown extends HTMLElement {
|
|
|
252
252
|
detail: selectedValue,
|
|
253
253
|
bubbles: true,
|
|
254
254
|
composed: true,
|
|
255
|
-
})
|
|
255
|
+
})
|
|
256
256
|
);
|
|
257
257
|
}
|
|
258
258
|
|
|
@@ -318,10 +318,11 @@ customElements.define("fig-dropdown", FigDropdown);
|
|
|
318
318
|
*/
|
|
319
319
|
class FigTooltip extends HTMLElement {
|
|
320
320
|
#boundHideOnChromeOpen;
|
|
321
|
-
#boundHideOnDragStart;
|
|
322
321
|
#boundHidePopupOutsideClick;
|
|
323
322
|
#touchTimeout;
|
|
324
323
|
#isTouching = false;
|
|
324
|
+
#observer = null;
|
|
325
|
+
#repositionRAF = null;
|
|
325
326
|
constructor() {
|
|
326
327
|
super();
|
|
327
328
|
this.action = this.getAttribute("action") || "hover";
|
|
@@ -330,7 +331,6 @@ class FigTooltip extends HTMLElement {
|
|
|
330
331
|
|
|
331
332
|
// Bind methods that will be used as event listeners
|
|
332
333
|
this.#boundHideOnChromeOpen = this.#hideOnChromeOpen.bind(this);
|
|
333
|
-
this.#boundHideOnDragStart = this.hidePopup.bind(this);
|
|
334
334
|
this.#boundHidePopupOutsideClick = this.hidePopupOutsideClick.bind(this);
|
|
335
335
|
}
|
|
336
336
|
connectedCallback() {
|
|
@@ -344,16 +344,16 @@ class FigTooltip extends HTMLElement {
|
|
|
344
344
|
document.removeEventListener(
|
|
345
345
|
"mousedown",
|
|
346
346
|
this.#boundHideOnChromeOpen,
|
|
347
|
-
true
|
|
347
|
+
true
|
|
348
348
|
);
|
|
349
|
-
//
|
|
350
|
-
this
|
|
349
|
+
// Disconnect mutation observer
|
|
350
|
+
this.#stopObserving();
|
|
351
351
|
|
|
352
352
|
// Remove click outside listener for click action
|
|
353
353
|
if (this.action === "click") {
|
|
354
354
|
document.body.removeEventListener(
|
|
355
355
|
"click",
|
|
356
|
-
this.#boundHidePopupOutsideClick
|
|
356
|
+
this.#boundHidePopupOutsideClick
|
|
357
357
|
);
|
|
358
358
|
}
|
|
359
359
|
|
|
@@ -411,6 +411,7 @@ class FigTooltip extends HTMLElement {
|
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
destroy() {
|
|
414
|
+
this.#stopObserving();
|
|
414
415
|
if (this.popup) {
|
|
415
416
|
this.popup.remove();
|
|
416
417
|
}
|
|
@@ -418,7 +419,7 @@ class FigTooltip extends HTMLElement {
|
|
|
418
419
|
if (this.action === "click") {
|
|
419
420
|
document.body.removeEventListener(
|
|
420
421
|
"click",
|
|
421
|
-
this.#boundHidePopupOutsideClick
|
|
422
|
+
this.#boundHidePopupOutsideClick
|
|
422
423
|
);
|
|
423
424
|
}
|
|
424
425
|
}
|
|
@@ -436,12 +437,9 @@ class FigTooltip extends HTMLElement {
|
|
|
436
437
|
this.addEventListener("pointerenter", this.showDelayedPopup.bind(this));
|
|
437
438
|
this.addEventListener(
|
|
438
439
|
"pointerleave",
|
|
439
|
-
this.#handlePointerLeave.bind(this)
|
|
440
|
+
this.#handlePointerLeave.bind(this)
|
|
440
441
|
);
|
|
441
442
|
}
|
|
442
|
-
// Add mousedown listener instead of dragstart
|
|
443
|
-
this.addEventListener("mousedown", this.#boundHideOnDragStart);
|
|
444
|
-
|
|
445
443
|
// Touch support for mobile hover simulation
|
|
446
444
|
this.addEventListener("touchstart", this.#handleTouchStart.bind(this), {
|
|
447
445
|
passive: true,
|
|
@@ -490,6 +488,20 @@ class FigTooltip extends HTMLElement {
|
|
|
490
488
|
}
|
|
491
489
|
|
|
492
490
|
showPopup() {
|
|
491
|
+
this.#repositionPopup();
|
|
492
|
+
this.popup.style.opacity = "1";
|
|
493
|
+
this.popup.style.visibility = "visible";
|
|
494
|
+
this.popup.style.display = "block";
|
|
495
|
+
this.popup.style.pointerEvents = "all";
|
|
496
|
+
this.popup.style.zIndex = figGetHighestZIndex() + 1;
|
|
497
|
+
|
|
498
|
+
this.isOpen = true;
|
|
499
|
+
this.#startObserving();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
#repositionPopup() {
|
|
503
|
+
if (!this.popup || !this.firstElementChild) return;
|
|
504
|
+
|
|
493
505
|
const rect = this.firstElementChild.getBoundingClientRect();
|
|
494
506
|
const popupRect = this.popup.getBoundingClientRect();
|
|
495
507
|
const offset = this.getOffset();
|
|
@@ -520,18 +532,12 @@ class FigTooltip extends HTMLElement {
|
|
|
520
532
|
|
|
521
533
|
this.popup.style.top = `${top}px`;
|
|
522
534
|
this.popup.style.left = `${left}px`;
|
|
523
|
-
this.popup.style.opacity = "1";
|
|
524
|
-
this.popup.style.visibility = "visible";
|
|
525
|
-
this.popup.style.display = "block";
|
|
526
|
-
this.popup.style.pointerEvents = "all";
|
|
527
|
-
this.popup.style.zIndex = figGetHighestZIndex() + 1;
|
|
528
|
-
|
|
529
|
-
this.isOpen = true;
|
|
530
535
|
}
|
|
531
536
|
|
|
532
537
|
hidePopup() {
|
|
533
538
|
clearTimeout(this.timeout);
|
|
534
539
|
clearTimeout(this.#touchTimeout);
|
|
540
|
+
this.#stopObserving();
|
|
535
541
|
if (this.popup) {
|
|
536
542
|
this.popup.style.opacity = "0";
|
|
537
543
|
this.popup.style.display = "block";
|
|
@@ -542,6 +548,35 @@ class FigTooltip extends HTMLElement {
|
|
|
542
548
|
this.isOpen = false;
|
|
543
549
|
}
|
|
544
550
|
|
|
551
|
+
#startObserving() {
|
|
552
|
+
this.#stopObserving();
|
|
553
|
+
const target = this.firstElementChild;
|
|
554
|
+
if (!target) return;
|
|
555
|
+
|
|
556
|
+
this.#observer = new MutationObserver(() => {
|
|
557
|
+
if (this.#repositionRAF) cancelAnimationFrame(this.#repositionRAF);
|
|
558
|
+
this.#repositionRAF = requestAnimationFrame(() => {
|
|
559
|
+
this.#repositionPopup();
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
this.#observer.observe(target, {
|
|
564
|
+
attributes: true,
|
|
565
|
+
attributeFilter: ["style", "class", "transform"],
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
#stopObserving() {
|
|
570
|
+
if (this.#repositionRAF) {
|
|
571
|
+
cancelAnimationFrame(this.#repositionRAF);
|
|
572
|
+
this.#repositionRAF = null;
|
|
573
|
+
}
|
|
574
|
+
if (this.#observer) {
|
|
575
|
+
this.#observer.disconnect();
|
|
576
|
+
this.#observer = null;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
545
580
|
hidePopupOutsideClick(event) {
|
|
546
581
|
if (this.isOpen && !this.popup.contains(event.target)) {
|
|
547
582
|
this.hidePopup();
|
|
@@ -1278,7 +1313,7 @@ class FigSegmentedControl extends HTMLElement {
|
|
|
1278
1313
|
requestAnimationFrame(() => {
|
|
1279
1314
|
const segments = this.querySelectorAll("fig-segment");
|
|
1280
1315
|
const hasSelected = Array.from(segments).some((s) =>
|
|
1281
|
-
s.hasAttribute("selected")
|
|
1316
|
+
s.hasAttribute("selected")
|
|
1282
1317
|
);
|
|
1283
1318
|
if (!hasSelected && segments.length > 0) {
|
|
1284
1319
|
this.selectedSegment = segments[0];
|
|
@@ -1435,7 +1470,7 @@ class FigSlider extends HTMLElement {
|
|
|
1435
1470
|
if (this.default) {
|
|
1436
1471
|
this.style.setProperty(
|
|
1437
1472
|
"--default",
|
|
1438
|
-
this.#calculateNormal(this.default)
|
|
1473
|
+
this.#calculateNormal(this.default)
|
|
1439
1474
|
);
|
|
1440
1475
|
}
|
|
1441
1476
|
|
|
@@ -1445,7 +1480,7 @@ class FigSlider extends HTMLElement {
|
|
|
1445
1480
|
this.inputContainer.append(this.datalist);
|
|
1446
1481
|
this.datalist.setAttribute(
|
|
1447
1482
|
"id",
|
|
1448
|
-
this.datalist.getAttribute("id") || figUniqueId()
|
|
1483
|
+
this.datalist.getAttribute("id") || figUniqueId()
|
|
1449
1484
|
);
|
|
1450
1485
|
this.input.setAttribute("list", this.datalist.getAttribute("id"));
|
|
1451
1486
|
} else if (this.type === "stepper") {
|
|
@@ -1470,7 +1505,7 @@ class FigSlider extends HTMLElement {
|
|
|
1470
1505
|
}
|
|
1471
1506
|
if (this.datalist) {
|
|
1472
1507
|
let defaultOption = this.datalist.querySelector(
|
|
1473
|
-
`option[value='${this.default}']
|
|
1508
|
+
`option[value='${this.default}']`
|
|
1474
1509
|
);
|
|
1475
1510
|
if (defaultOption) {
|
|
1476
1511
|
defaultOption.setAttribute("default", "true");
|
|
@@ -1479,19 +1514,19 @@ class FigSlider extends HTMLElement {
|
|
|
1479
1514
|
if (this.figInputNumber) {
|
|
1480
1515
|
this.figInputNumber.removeEventListener(
|
|
1481
1516
|
"input",
|
|
1482
|
-
this.#boundHandleTextInput
|
|
1517
|
+
this.#boundHandleTextInput
|
|
1483
1518
|
);
|
|
1484
1519
|
this.figInputNumber.addEventListener(
|
|
1485
1520
|
"input",
|
|
1486
|
-
this.#boundHandleTextInput
|
|
1521
|
+
this.#boundHandleTextInput
|
|
1487
1522
|
);
|
|
1488
1523
|
this.figInputNumber.removeEventListener(
|
|
1489
1524
|
"change",
|
|
1490
|
-
this.#boundHandleTextChange
|
|
1525
|
+
this.#boundHandleTextChange
|
|
1491
1526
|
);
|
|
1492
1527
|
this.figInputNumber.addEventListener(
|
|
1493
1528
|
"change",
|
|
1494
|
-
this.#boundHandleTextChange
|
|
1529
|
+
this.#boundHandleTextChange
|
|
1495
1530
|
);
|
|
1496
1531
|
}
|
|
1497
1532
|
|
|
@@ -1511,11 +1546,11 @@ class FigSlider extends HTMLElement {
|
|
|
1511
1546
|
if (this.figInputNumber) {
|
|
1512
1547
|
this.figInputNumber.removeEventListener(
|
|
1513
1548
|
"input",
|
|
1514
|
-
this.#boundHandleTextInput
|
|
1549
|
+
this.#boundHandleTextInput
|
|
1515
1550
|
);
|
|
1516
1551
|
this.figInputNumber.removeEventListener(
|
|
1517
1552
|
"change",
|
|
1518
|
-
this.#boundHandleTextChange
|
|
1553
|
+
this.#boundHandleTextChange
|
|
1519
1554
|
);
|
|
1520
1555
|
}
|
|
1521
1556
|
}
|
|
@@ -1525,7 +1560,7 @@ class FigSlider extends HTMLElement {
|
|
|
1525
1560
|
this.value = this.input.value = this.figInputNumber.value;
|
|
1526
1561
|
this.#syncProperties();
|
|
1527
1562
|
this.dispatchEvent(
|
|
1528
|
-
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
1563
|
+
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
1529
1564
|
);
|
|
1530
1565
|
}
|
|
1531
1566
|
}
|
|
@@ -1555,14 +1590,14 @@ class FigSlider extends HTMLElement {
|
|
|
1555
1590
|
#handleInput() {
|
|
1556
1591
|
this.#syncValue();
|
|
1557
1592
|
this.dispatchEvent(
|
|
1558
|
-
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
1593
|
+
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
1559
1594
|
);
|
|
1560
1595
|
}
|
|
1561
1596
|
|
|
1562
1597
|
#handleChange() {
|
|
1563
1598
|
this.#syncValue();
|
|
1564
1599
|
this.dispatchEvent(
|
|
1565
|
-
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
1600
|
+
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
1566
1601
|
);
|
|
1567
1602
|
}
|
|
1568
1603
|
|
|
@@ -1571,7 +1606,7 @@ class FigSlider extends HTMLElement {
|
|
|
1571
1606
|
this.value = this.input.value = this.figInputNumber.value;
|
|
1572
1607
|
this.#syncProperties();
|
|
1573
1608
|
this.dispatchEvent(
|
|
1574
|
-
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
1609
|
+
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
1575
1610
|
);
|
|
1576
1611
|
}
|
|
1577
1612
|
}
|
|
@@ -1778,10 +1813,10 @@ class FigInputText extends HTMLElement {
|
|
|
1778
1813
|
this.value = value;
|
|
1779
1814
|
this.input.value = valueTransformed;
|
|
1780
1815
|
this.dispatchEvent(
|
|
1781
|
-
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
1816
|
+
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
1782
1817
|
);
|
|
1783
1818
|
this.dispatchEvent(
|
|
1784
|
-
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
1819
|
+
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
1785
1820
|
);
|
|
1786
1821
|
}
|
|
1787
1822
|
#handleMouseMove(e) {
|
|
@@ -1831,13 +1866,13 @@ class FigInputText extends HTMLElement {
|
|
|
1831
1866
|
if (typeof this.min === "number") {
|
|
1832
1867
|
sanitized = Math.max(
|
|
1833
1868
|
transform ? this.#transformNumber(this.min) : this.min,
|
|
1834
|
-
sanitized
|
|
1869
|
+
sanitized
|
|
1835
1870
|
);
|
|
1836
1871
|
}
|
|
1837
1872
|
if (typeof this.max === "number") {
|
|
1838
1873
|
sanitized = Math.min(
|
|
1839
1874
|
transform ? this.#transformNumber(this.max) : this.max,
|
|
1840
|
-
sanitized
|
|
1875
|
+
sanitized
|
|
1841
1876
|
);
|
|
1842
1877
|
}
|
|
1843
1878
|
|
|
@@ -2149,7 +2184,7 @@ class FigInputNumber extends HTMLElement {
|
|
|
2149
2184
|
e.target.value = "";
|
|
2150
2185
|
}
|
|
2151
2186
|
this.dispatchEvent(
|
|
2152
|
-
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
2187
|
+
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
2153
2188
|
);
|
|
2154
2189
|
}
|
|
2155
2190
|
|
|
@@ -2175,10 +2210,10 @@ class FigInputNumber extends HTMLElement {
|
|
|
2175
2210
|
this.input.value = this.#formatWithUnit(this.value);
|
|
2176
2211
|
|
|
2177
2212
|
this.dispatchEvent(
|
|
2178
|
-
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
2213
|
+
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
2179
2214
|
);
|
|
2180
2215
|
this.dispatchEvent(
|
|
2181
|
-
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
2216
|
+
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
2182
2217
|
);
|
|
2183
2218
|
}
|
|
2184
2219
|
|
|
@@ -2190,7 +2225,7 @@ class FigInputNumber extends HTMLElement {
|
|
|
2190
2225
|
this.value = "";
|
|
2191
2226
|
}
|
|
2192
2227
|
this.dispatchEvent(
|
|
2193
|
-
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
2228
|
+
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
2194
2229
|
);
|
|
2195
2230
|
}
|
|
2196
2231
|
|
|
@@ -2207,10 +2242,10 @@ class FigInputNumber extends HTMLElement {
|
|
|
2207
2242
|
e.target.value = "";
|
|
2208
2243
|
}
|
|
2209
2244
|
this.dispatchEvent(
|
|
2210
|
-
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
2245
|
+
new CustomEvent("input", { detail: this.value, bubbles: true })
|
|
2211
2246
|
);
|
|
2212
2247
|
this.dispatchEvent(
|
|
2213
|
-
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
2248
|
+
new CustomEvent("change", { detail: this.value, bubbles: true })
|
|
2214
2249
|
);
|
|
2215
2250
|
}
|
|
2216
2251
|
|
|
@@ -2397,7 +2432,7 @@ class FigField extends HTMLElement {
|
|
|
2397
2432
|
requestAnimationFrame(() => {
|
|
2398
2433
|
this.label = this.querySelector(":scope>label");
|
|
2399
2434
|
this.input = Array.from(this.childNodes).find((node) =>
|
|
2400
|
-
node.nodeName.toLowerCase().startsWith("fig-")
|
|
2435
|
+
node.nodeName.toLowerCase().startsWith("fig-")
|
|
2401
2436
|
);
|
|
2402
2437
|
if (this.input && this.label) {
|
|
2403
2438
|
this.label.addEventListener("click", this.focus.bind(this));
|
|
@@ -2518,11 +2553,11 @@ class FigInputColor extends HTMLElement {
|
|
|
2518
2553
|
}
|
|
2519
2554
|
this.#fillPicker.addEventListener(
|
|
2520
2555
|
"input",
|
|
2521
|
-
this.#handleFillPickerInput.bind(this)
|
|
2556
|
+
this.#handleFillPickerInput.bind(this)
|
|
2522
2557
|
);
|
|
2523
2558
|
this.#fillPicker.addEventListener(
|
|
2524
2559
|
"change",
|
|
2525
|
-
this.#handleChange.bind(this)
|
|
2560
|
+
this.#handleChange.bind(this)
|
|
2526
2561
|
);
|
|
2527
2562
|
}
|
|
2528
2563
|
|
|
@@ -2535,22 +2570,22 @@ class FigInputColor extends HTMLElement {
|
|
|
2535
2570
|
}
|
|
2536
2571
|
this.#textInput.addEventListener(
|
|
2537
2572
|
"input",
|
|
2538
|
-
this.#handleTextInput.bind(this)
|
|
2573
|
+
this.#handleTextInput.bind(this)
|
|
2539
2574
|
);
|
|
2540
2575
|
this.#textInput.addEventListener(
|
|
2541
2576
|
"change",
|
|
2542
|
-
this.#handleChange.bind(this)
|
|
2577
|
+
this.#handleChange.bind(this)
|
|
2543
2578
|
);
|
|
2544
2579
|
}
|
|
2545
2580
|
|
|
2546
2581
|
if (this.#alphaInput) {
|
|
2547
2582
|
this.#alphaInput.addEventListener(
|
|
2548
2583
|
"input",
|
|
2549
|
-
this.#handleAlphaInput.bind(this)
|
|
2584
|
+
this.#handleAlphaInput.bind(this)
|
|
2550
2585
|
);
|
|
2551
2586
|
this.#alphaInput.addEventListener(
|
|
2552
2587
|
"change",
|
|
2553
|
-
this.#handleChange.bind(this)
|
|
2588
|
+
this.#handleChange.bind(this)
|
|
2554
2589
|
);
|
|
2555
2590
|
}
|
|
2556
2591
|
});
|
|
@@ -2563,7 +2598,7 @@ class FigInputColor extends HTMLElement {
|
|
|
2563
2598
|
g: isNaN(this.rgba.g) ? 0 : this.rgba.g,
|
|
2564
2599
|
b: isNaN(this.rgba.b) ? 0 : this.rgba.b,
|
|
2565
2600
|
},
|
|
2566
|
-
this.rgba.a
|
|
2601
|
+
this.rgba.a
|
|
2567
2602
|
);
|
|
2568
2603
|
this.hexWithAlpha = this.value.toUpperCase();
|
|
2569
2604
|
this.hexOpaque = this.hexWithAlpha.slice(0, 7);
|
|
@@ -2606,7 +2641,7 @@ class FigInputColor extends HTMLElement {
|
|
|
2606
2641
|
type: "solid",
|
|
2607
2642
|
color: this.hexOpaque,
|
|
2608
2643
|
opacity: this.alpha,
|
|
2609
|
-
})
|
|
2644
|
+
})
|
|
2610
2645
|
);
|
|
2611
2646
|
}
|
|
2612
2647
|
this.#emitInputEvent();
|
|
@@ -2629,7 +2664,7 @@ class FigInputColor extends HTMLElement {
|
|
|
2629
2664
|
// Display without # prefix
|
|
2630
2665
|
this.#textInput.setAttribute(
|
|
2631
2666
|
"value",
|
|
2632
|
-
this.hexOpaque.slice(1).toUpperCase()
|
|
2667
|
+
this.hexOpaque.slice(1).toUpperCase()
|
|
2633
2668
|
);
|
|
2634
2669
|
}
|
|
2635
2670
|
this.#emitInputEvent();
|
|
@@ -2651,7 +2686,7 @@ class FigInputColor extends HTMLElement {
|
|
|
2651
2686
|
if (this.#textInput) {
|
|
2652
2687
|
this.#textInput.setAttribute(
|
|
2653
2688
|
"value",
|
|
2654
|
-
this.hexOpaque.slice(1).toUpperCase()
|
|
2689
|
+
this.hexOpaque.slice(1).toUpperCase()
|
|
2655
2690
|
);
|
|
2656
2691
|
}
|
|
2657
2692
|
if (this.#alphaInput && detail.alpha !== undefined) {
|
|
@@ -2709,7 +2744,7 @@ class FigInputColor extends HTMLElement {
|
|
|
2709
2744
|
type: "solid",
|
|
2710
2745
|
color: this.hexOpaque,
|
|
2711
2746
|
opacity: this.alpha,
|
|
2712
|
-
})
|
|
2747
|
+
})
|
|
2713
2748
|
);
|
|
2714
2749
|
}
|
|
2715
2750
|
if (this.#alphaInput) {
|
|
@@ -2776,7 +2811,7 @@ class FigInputColor extends HTMLElement {
|
|
|
2776
2811
|
// Handle rgba colors
|
|
2777
2812
|
else if (color.startsWith("rgba") || color.startsWith("rgb")) {
|
|
2778
2813
|
let matches = color.match(
|
|
2779
|
-
/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)
|
|
2814
|
+
/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)/
|
|
2780
2815
|
);
|
|
2781
2816
|
if (matches) {
|
|
2782
2817
|
r = parseInt(matches[1]);
|
|
@@ -2788,7 +2823,7 @@ class FigInputColor extends HTMLElement {
|
|
|
2788
2823
|
// Handle hsla colors
|
|
2789
2824
|
else if (color.startsWith("hsla") || color.startsWith("hsl")) {
|
|
2790
2825
|
let matches = color.match(
|
|
2791
|
-
/hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*(\d+(?:\.\d+)?))?\)
|
|
2826
|
+
/hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*(\d+(?:\.\d+)?))?\)/
|
|
2792
2827
|
);
|
|
2793
2828
|
if (matches) {
|
|
2794
2829
|
let h = parseInt(matches[1]) / 360;
|
|
@@ -3015,7 +3050,9 @@ class FigInputFill extends HTMLElement {
|
|
|
3015
3050
|
|
|
3016
3051
|
this.innerHTML = `
|
|
3017
3052
|
<div class="input-combo">
|
|
3018
|
-
<fig-fill-picker value='${fillPickerValue}' ${
|
|
3053
|
+
<fig-fill-picker value='${fillPickerValue}' ${
|
|
3054
|
+
disabled ? "disabled" : ""
|
|
3055
|
+
}></fig-fill-picker>
|
|
3019
3056
|
${controlsHtml}
|
|
3020
3057
|
</div>`;
|
|
3021
3058
|
|
|
@@ -3144,13 +3181,13 @@ class FigInputFill extends HTMLElement {
|
|
|
3144
3181
|
if (this.#hexInput) {
|
|
3145
3182
|
this.#hexInput.setAttribute(
|
|
3146
3183
|
"value",
|
|
3147
|
-
this.#solid.color.slice(1).toUpperCase()
|
|
3184
|
+
this.#solid.color.slice(1).toUpperCase()
|
|
3148
3185
|
);
|
|
3149
3186
|
}
|
|
3150
3187
|
if (this.#opacityInput) {
|
|
3151
3188
|
this.#opacityInput.setAttribute(
|
|
3152
3189
|
"value",
|
|
3153
|
-
Math.round(this.#solid.alpha * 100)
|
|
3190
|
+
Math.round(this.#solid.alpha * 100)
|
|
3154
3191
|
);
|
|
3155
3192
|
}
|
|
3156
3193
|
break;
|
|
@@ -3158,7 +3195,7 @@ class FigInputFill extends HTMLElement {
|
|
|
3158
3195
|
if (this.#opacityInput) {
|
|
3159
3196
|
this.#opacityInput.setAttribute(
|
|
3160
3197
|
"value",
|
|
3161
|
-
this.#gradient.stops[0]?.opacity || 100
|
|
3198
|
+
this.#gradient.stops[0]?.opacity || 100
|
|
3162
3199
|
);
|
|
3163
3200
|
}
|
|
3164
3201
|
break;
|
|
@@ -3166,7 +3203,7 @@ class FigInputFill extends HTMLElement {
|
|
|
3166
3203
|
if (this.#opacityInput) {
|
|
3167
3204
|
this.#opacityInput.setAttribute(
|
|
3168
3205
|
"value",
|
|
3169
|
-
Math.round((this.#image.opacity ?? 1) * 100)
|
|
3206
|
+
Math.round((this.#image.opacity ?? 1) * 100)
|
|
3170
3207
|
);
|
|
3171
3208
|
}
|
|
3172
3209
|
break;
|
|
@@ -3174,7 +3211,7 @@ class FigInputFill extends HTMLElement {
|
|
|
3174
3211
|
if (this.#opacityInput) {
|
|
3175
3212
|
this.#opacityInput.setAttribute(
|
|
3176
3213
|
"value",
|
|
3177
|
-
Math.round((this.#video.opacity ?? 1) * 100)
|
|
3214
|
+
Math.round((this.#video.opacity ?? 1) * 100)
|
|
3178
3215
|
);
|
|
3179
3216
|
}
|
|
3180
3217
|
break;
|
|
@@ -3182,7 +3219,7 @@ class FigInputFill extends HTMLElement {
|
|
|
3182
3219
|
if (this.#opacityInput) {
|
|
3183
3220
|
this.#opacityInput.setAttribute(
|
|
3184
3221
|
"value",
|
|
3185
|
-
Math.round((this.#webcam.opacity ?? 1) * 100)
|
|
3222
|
+
Math.round((this.#webcam.opacity ?? 1) * 100)
|
|
3186
3223
|
);
|
|
3187
3224
|
}
|
|
3188
3225
|
break;
|
|
@@ -3386,7 +3423,7 @@ class FigInputFill extends HTMLElement {
|
|
|
3386
3423
|
new CustomEvent("input", {
|
|
3387
3424
|
bubbles: true,
|
|
3388
3425
|
detail: this.value,
|
|
3389
|
-
})
|
|
3426
|
+
})
|
|
3390
3427
|
);
|
|
3391
3428
|
}
|
|
3392
3429
|
|
|
@@ -3395,7 +3432,7 @@ class FigInputFill extends HTMLElement {
|
|
|
3395
3432
|
new CustomEvent("change", {
|
|
3396
3433
|
bubbles: true,
|
|
3397
3434
|
detail: this.value,
|
|
3398
|
-
})
|
|
3435
|
+
})
|
|
3399
3436
|
);
|
|
3400
3437
|
}
|
|
3401
3438
|
|
|
@@ -3602,14 +3639,14 @@ class FigCheckbox extends HTMLElement {
|
|
|
3602
3639
|
bubbles: true,
|
|
3603
3640
|
composed: true,
|
|
3604
3641
|
detail: { checked: this.input.checked, value: this.input.value },
|
|
3605
|
-
})
|
|
3642
|
+
})
|
|
3606
3643
|
);
|
|
3607
3644
|
this.dispatchEvent(
|
|
3608
3645
|
new CustomEvent("change", {
|
|
3609
3646
|
bubbles: true,
|
|
3610
3647
|
composed: true,
|
|
3611
3648
|
detail: { checked: this.input.checked, value: this.input.value },
|
|
3612
|
-
})
|
|
3649
|
+
})
|
|
3613
3650
|
);
|
|
3614
3651
|
}
|
|
3615
3652
|
}
|
|
@@ -3822,7 +3859,7 @@ class FigComboInput extends HTMLElement {
|
|
|
3822
3859
|
|
|
3823
3860
|
this.dropdown.addEventListener(
|
|
3824
3861
|
"input",
|
|
3825
|
-
this.handleSelectInput.bind(this)
|
|
3862
|
+
this.handleSelectInput.bind(this)
|
|
3826
3863
|
);
|
|
3827
3864
|
|
|
3828
3865
|
// Apply initial disabled state
|
|
@@ -4076,7 +4113,7 @@ class FigImage extends HTMLElement {
|
|
|
4076
4113
|
disconnectedCallback() {
|
|
4077
4114
|
this.fileInput.removeEventListener(
|
|
4078
4115
|
"change",
|
|
4079
|
-
this.#handleFileInput.bind(this)
|
|
4116
|
+
this.#handleFileInput.bind(this)
|
|
4080
4117
|
);
|
|
4081
4118
|
}
|
|
4082
4119
|
|
|
@@ -4088,22 +4125,22 @@ class FigImage extends HTMLElement {
|
|
|
4088
4125
|
this.fileInput = this.uploadButton?.querySelector("input");
|
|
4089
4126
|
this.fileInput.removeEventListener(
|
|
4090
4127
|
"change",
|
|
4091
|
-
this.#handleFileInput.bind(this)
|
|
4128
|
+
this.#handleFileInput.bind(this)
|
|
4092
4129
|
);
|
|
4093
4130
|
this.fileInput.addEventListener(
|
|
4094
4131
|
"change",
|
|
4095
|
-
this.#handleFileInput.bind(this)
|
|
4132
|
+
this.#handleFileInput.bind(this)
|
|
4096
4133
|
);
|
|
4097
4134
|
}
|
|
4098
4135
|
if (this.download) {
|
|
4099
4136
|
this.downloadButton = this.querySelector("fig-button[type='download']");
|
|
4100
4137
|
this.downloadButton.removeEventListener(
|
|
4101
4138
|
"click",
|
|
4102
|
-
this.#handleDownload.bind(this)
|
|
4139
|
+
this.#handleDownload.bind(this)
|
|
4103
4140
|
);
|
|
4104
4141
|
this.downloadButton.addEventListener(
|
|
4105
4142
|
"click",
|
|
4106
|
-
this.#handleDownload.bind(this)
|
|
4143
|
+
this.#handleDownload.bind(this)
|
|
4107
4144
|
);
|
|
4108
4145
|
}
|
|
4109
4146
|
});
|
|
@@ -4124,7 +4161,7 @@ class FigImage extends HTMLElement {
|
|
|
4124
4161
|
this.aspectRatio = this.image.width / this.image.height;
|
|
4125
4162
|
this.style.setProperty(
|
|
4126
4163
|
"--aspect-ratio",
|
|
4127
|
-
`${this.image.width}/${this.image.height}
|
|
4164
|
+
`${this.image.width}/${this.image.height}`
|
|
4128
4165
|
);
|
|
4129
4166
|
this.dispatchEvent(
|
|
4130
4167
|
new CustomEvent("loaded", {
|
|
@@ -4134,7 +4171,7 @@ class FigImage extends HTMLElement {
|
|
|
4134
4171
|
blob: this.blob,
|
|
4135
4172
|
base64: this.base64,
|
|
4136
4173
|
},
|
|
4137
|
-
})
|
|
4174
|
+
})
|
|
4138
4175
|
);
|
|
4139
4176
|
resolve();
|
|
4140
4177
|
|
|
@@ -4185,14 +4222,14 @@ class FigImage extends HTMLElement {
|
|
|
4185
4222
|
blob: this.blob,
|
|
4186
4223
|
base64: this.base64,
|
|
4187
4224
|
},
|
|
4188
|
-
})
|
|
4225
|
+
})
|
|
4189
4226
|
);
|
|
4190
4227
|
//emit for change too
|
|
4191
4228
|
this.dispatchEvent(
|
|
4192
4229
|
new CustomEvent("change", {
|
|
4193
4230
|
bubbles: true,
|
|
4194
4231
|
cancelable: true,
|
|
4195
|
-
})
|
|
4232
|
+
})
|
|
4196
4233
|
);
|
|
4197
4234
|
this.setAttribute("src", this.blob);
|
|
4198
4235
|
}
|
|
@@ -4213,7 +4250,7 @@ class FigImage extends HTMLElement {
|
|
|
4213
4250
|
if (this.chit) {
|
|
4214
4251
|
this.chit.setAttribute(
|
|
4215
4252
|
"background",
|
|
4216
|
-
this.#src ? `url(${this.#src})` : ""
|
|
4253
|
+
this.#src ? `url(${this.#src})` : ""
|
|
4217
4254
|
);
|
|
4218
4255
|
}
|
|
4219
4256
|
if (this.#src) {
|
|
@@ -4326,7 +4363,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
4326
4363
|
this.plane.addEventListener("mousedown", this.#handleMouseDown.bind(this));
|
|
4327
4364
|
this.plane.addEventListener(
|
|
4328
4365
|
"touchstart",
|
|
4329
|
-
this.#handleTouchStart.bind(this)
|
|
4366
|
+
this.#handleTouchStart.bind(this)
|
|
4330
4367
|
);
|
|
4331
4368
|
window.addEventListener("keydown", this.#handleKeyDown.bind(this));
|
|
4332
4369
|
window.addEventListener("keyup", this.#handleKeyUp.bind(this));
|
|
@@ -4386,7 +4423,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
4386
4423
|
let x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
4387
4424
|
let screenY = Math.max(
|
|
4388
4425
|
0,
|
|
4389
|
-
Math.min(1, (e.clientY - rect.top) / rect.height)
|
|
4426
|
+
Math.min(1, (e.clientY - rect.top) / rect.height)
|
|
4390
4427
|
);
|
|
4391
4428
|
|
|
4392
4429
|
// Convert screen Y to internal Y (flip for math coordinates)
|
|
@@ -4414,7 +4451,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
4414
4451
|
new CustomEvent("input", {
|
|
4415
4452
|
bubbles: true,
|
|
4416
4453
|
cancelable: true,
|
|
4417
|
-
})
|
|
4454
|
+
})
|
|
4418
4455
|
);
|
|
4419
4456
|
}
|
|
4420
4457
|
|
|
@@ -4423,7 +4460,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
4423
4460
|
new CustomEvent("change", {
|
|
4424
4461
|
bubbles: true,
|
|
4425
4462
|
cancelable: true,
|
|
4426
|
-
})
|
|
4463
|
+
})
|
|
4427
4464
|
);
|
|
4428
4465
|
}
|
|
4429
4466
|
|
|
@@ -4552,6 +4589,7 @@ customElements.define("fig-input-joystick", FigInputJoystick);
|
|
|
4552
4589
|
* @attr {boolean} text - Whether to display a text input for the angle value.
|
|
4553
4590
|
* @attr {number} adjacent - The adjacent value of the angle.
|
|
4554
4591
|
* @attr {number} opposite - The opposite value of the angle.
|
|
4592
|
+
* @attr {boolean} show-rotations - Whether to display a rotation count (×N) when rotations > 1. Defaults to false.
|
|
4555
4593
|
*/
|
|
4556
4594
|
class FigInputAngle extends HTMLElement {
|
|
4557
4595
|
// Private fields
|
|
@@ -4574,6 +4612,8 @@ class FigInputAngle extends HTMLElement {
|
|
|
4574
4612
|
this.units = "°";
|
|
4575
4613
|
this.min = null;
|
|
4576
4614
|
this.max = null;
|
|
4615
|
+
this.showRotations = false;
|
|
4616
|
+
this.rotationSpan = null;
|
|
4577
4617
|
|
|
4578
4618
|
this.#boundHandleRawChange = this.#handleRawChange.bind(this);
|
|
4579
4619
|
}
|
|
@@ -4594,6 +4634,8 @@ class FigInputAngle extends HTMLElement {
|
|
|
4594
4634
|
this.max = this.hasAttribute("max")
|
|
4595
4635
|
? Number(this.getAttribute("max"))
|
|
4596
4636
|
: null;
|
|
4637
|
+
this.showRotations =
|
|
4638
|
+
this.getAttribute("show-rotations") === "true";
|
|
4597
4639
|
|
|
4598
4640
|
this.#render();
|
|
4599
4641
|
this.#setupListeners();
|
|
@@ -4602,7 +4644,7 @@ class FigInputAngle extends HTMLElement {
|
|
|
4602
4644
|
if (this.text && this.angleInput) {
|
|
4603
4645
|
this.angleInput.setAttribute(
|
|
4604
4646
|
"value",
|
|
4605
|
-
this.angle.toFixed(this.precision)
|
|
4647
|
+
this.angle.toFixed(this.precision)
|
|
4606
4648
|
);
|
|
4607
4649
|
}
|
|
4608
4650
|
});
|
|
@@ -4633,12 +4675,30 @@ class FigInputAngle extends HTMLElement {
|
|
|
4633
4675
|
${minAttr}
|
|
4634
4676
|
${maxAttr}
|
|
4635
4677
|
units="${this.units}">
|
|
4678
|
+
${this.showRotations ? `<span slot="append" class="fig-input-angle-rotations"></span>` : ""}
|
|
4636
4679
|
</fig-input-number>`
|
|
4637
4680
|
: ""
|
|
4638
4681
|
}
|
|
4639
4682
|
`;
|
|
4640
4683
|
}
|
|
4641
4684
|
|
|
4685
|
+
#getRotationCount() {
|
|
4686
|
+
const degrees = Math.abs(this.#toDegrees(this.angle));
|
|
4687
|
+
return Math.floor(degrees / 360);
|
|
4688
|
+
}
|
|
4689
|
+
|
|
4690
|
+
#updateRotationDisplay() {
|
|
4691
|
+
if (!this.rotationSpan) return;
|
|
4692
|
+
const rotations = this.#getRotationCount();
|
|
4693
|
+
if (rotations > 1) {
|
|
4694
|
+
this.rotationSpan.textContent = `\u00d7${rotations}`;
|
|
4695
|
+
this.rotationSpan.style.display = "";
|
|
4696
|
+
} else {
|
|
4697
|
+
this.rotationSpan.textContent = "";
|
|
4698
|
+
this.rotationSpan.style.display = "none";
|
|
4699
|
+
}
|
|
4700
|
+
}
|
|
4701
|
+
|
|
4642
4702
|
#getStepForUnit() {
|
|
4643
4703
|
switch (this.units) {
|
|
4644
4704
|
case "rad":
|
|
@@ -4704,17 +4764,19 @@ class FigInputAngle extends HTMLElement {
|
|
|
4704
4764
|
this.handle = this.querySelector(".fig-input-angle-handle");
|
|
4705
4765
|
this.plane = this.querySelector(".fig-input-angle-plane");
|
|
4706
4766
|
this.angleInput = this.querySelector("fig-input-number[name='angle']");
|
|
4767
|
+
this.rotationSpan = this.querySelector(".fig-input-angle-rotations");
|
|
4768
|
+
this.#updateRotationDisplay();
|
|
4707
4769
|
this.plane.addEventListener("mousedown", this.#handleMouseDown.bind(this));
|
|
4708
4770
|
this.plane.addEventListener(
|
|
4709
4771
|
"touchstart",
|
|
4710
|
-
this.#handleTouchStart.bind(this)
|
|
4772
|
+
this.#handleTouchStart.bind(this)
|
|
4711
4773
|
);
|
|
4712
4774
|
window.addEventListener("keydown", this.#handleKeyDown.bind(this));
|
|
4713
4775
|
window.addEventListener("keyup", this.#handleKeyUp.bind(this));
|
|
4714
4776
|
if (this.text && this.angleInput) {
|
|
4715
4777
|
this.angleInput.addEventListener(
|
|
4716
4778
|
"input",
|
|
4717
|
-
this.#handleAngleInput.bind(this)
|
|
4779
|
+
this.#handleAngleInput.bind(this)
|
|
4718
4780
|
);
|
|
4719
4781
|
}
|
|
4720
4782
|
// Capture-phase listener for unit suffix parsing
|
|
@@ -4753,6 +4815,7 @@ class FigInputAngle extends HTMLElement {
|
|
|
4753
4815
|
this.angle = Number(e.target.value);
|
|
4754
4816
|
this.#calculateAdjacentAndOpposite();
|
|
4755
4817
|
this.#syncHandlePosition();
|
|
4818
|
+
this.#updateRotationDisplay();
|
|
4756
4819
|
this.#emitInputEvent();
|
|
4757
4820
|
this.#emitChangeEvent();
|
|
4758
4821
|
}
|
|
@@ -4819,6 +4882,7 @@ class FigInputAngle extends HTMLElement {
|
|
|
4819
4882
|
if (this.text && this.angleInput) {
|
|
4820
4883
|
this.angleInput.setAttribute("value", this.angle.toFixed(this.precision));
|
|
4821
4884
|
}
|
|
4885
|
+
this.#updateRotationDisplay();
|
|
4822
4886
|
|
|
4823
4887
|
this.#emitInputEvent();
|
|
4824
4888
|
}
|
|
@@ -4830,7 +4894,7 @@ class FigInputAngle extends HTMLElement {
|
|
|
4830
4894
|
new CustomEvent("input", {
|
|
4831
4895
|
bubbles: true,
|
|
4832
4896
|
cancelable: true,
|
|
4833
|
-
})
|
|
4897
|
+
})
|
|
4834
4898
|
);
|
|
4835
4899
|
}
|
|
4836
4900
|
|
|
@@ -4839,7 +4903,7 @@ class FigInputAngle extends HTMLElement {
|
|
|
4839
4903
|
new CustomEvent("change", {
|
|
4840
4904
|
bubbles: true,
|
|
4841
4905
|
cancelable: true,
|
|
4842
|
-
})
|
|
4906
|
+
})
|
|
4843
4907
|
);
|
|
4844
4908
|
}
|
|
4845
4909
|
|
|
@@ -4922,7 +4986,7 @@ class FigInputAngle extends HTMLElement {
|
|
|
4922
4986
|
// --- Attributes ---
|
|
4923
4987
|
|
|
4924
4988
|
static get observedAttributes() {
|
|
4925
|
-
return ["value", "precision", "text", "min", "max", "units"];
|
|
4989
|
+
return ["value", "precision", "text", "min", "max", "units", "show-rotations"];
|
|
4926
4990
|
}
|
|
4927
4991
|
|
|
4928
4992
|
get value() {
|
|
@@ -4945,6 +5009,10 @@ class FigInputAngle extends HTMLElement {
|
|
|
4945
5009
|
this.angle = value;
|
|
4946
5010
|
this.#calculateAdjacentAndOpposite();
|
|
4947
5011
|
this.#syncHandlePosition();
|
|
5012
|
+
if (this.angleInput) {
|
|
5013
|
+
this.angleInput.setAttribute("value", this.angle.toFixed(this.precision));
|
|
5014
|
+
}
|
|
5015
|
+
this.#updateRotationDisplay();
|
|
4948
5016
|
}
|
|
4949
5017
|
|
|
4950
5018
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -4992,6 +5060,14 @@ class FigInputAngle extends HTMLElement {
|
|
|
4992
5060
|
this.#syncHandlePosition();
|
|
4993
5061
|
}
|
|
4994
5062
|
break;
|
|
5063
|
+
case "show-rotations":
|
|
5064
|
+
this.showRotations = newValue === "true";
|
|
5065
|
+
if (this.plane) {
|
|
5066
|
+
this.#render();
|
|
5067
|
+
this.#setupListeners();
|
|
5068
|
+
this.#syncHandlePosition();
|
|
5069
|
+
}
|
|
5070
|
+
break;
|
|
4995
5071
|
}
|
|
4996
5072
|
}
|
|
4997
5073
|
}
|
|
@@ -5092,7 +5168,7 @@ class FigLayer extends HTMLElement {
|
|
|
5092
5168
|
new CustomEvent("openchange", {
|
|
5093
5169
|
detail: { open: value },
|
|
5094
5170
|
bubbles: true,
|
|
5095
|
-
})
|
|
5171
|
+
})
|
|
5096
5172
|
);
|
|
5097
5173
|
}
|
|
5098
5174
|
}
|
|
@@ -5114,7 +5190,7 @@ class FigLayer extends HTMLElement {
|
|
|
5114
5190
|
new CustomEvent("visibilitychange", {
|
|
5115
5191
|
detail: { visible: value },
|
|
5116
5192
|
bubbles: true,
|
|
5117
|
-
})
|
|
5193
|
+
})
|
|
5118
5194
|
);
|
|
5119
5195
|
}
|
|
5120
5196
|
}
|
|
@@ -5128,7 +5204,7 @@ class FigLayer extends HTMLElement {
|
|
|
5128
5204
|
new CustomEvent("openchange", {
|
|
5129
5205
|
detail: { open: isOpen },
|
|
5130
5206
|
bubbles: true,
|
|
5131
|
-
})
|
|
5207
|
+
})
|
|
5132
5208
|
);
|
|
5133
5209
|
}
|
|
5134
5210
|
|
|
@@ -5138,7 +5214,7 @@ class FigLayer extends HTMLElement {
|
|
|
5138
5214
|
new CustomEvent("visibilitychange", {
|
|
5139
5215
|
detail: { visible: isVisible },
|
|
5140
5216
|
bubbles: true,
|
|
5141
|
-
})
|
|
5217
|
+
})
|
|
5142
5218
|
);
|
|
5143
5219
|
}
|
|
5144
5220
|
}
|
|
@@ -5302,7 +5378,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5302
5378
|
bg = `url(${this.#image.url})`;
|
|
5303
5379
|
const sizing = this.#getBackgroundSizing(
|
|
5304
5380
|
this.#image.scaleMode,
|
|
5305
|
-
this.#image.scale
|
|
5381
|
+
this.#image.scale
|
|
5306
5382
|
);
|
|
5307
5383
|
bgSize = sizing.size;
|
|
5308
5384
|
bgPosition = sizing.position;
|
|
@@ -5315,7 +5391,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5315
5391
|
bg = `url(${this.#video.url})`;
|
|
5316
5392
|
const sizing = this.#getBackgroundSizing(
|
|
5317
5393
|
this.#video.scaleMode,
|
|
5318
|
-
this.#video.scale
|
|
5394
|
+
this.#video.scale
|
|
5319
5395
|
);
|
|
5320
5396
|
bgSize = sizing.size;
|
|
5321
5397
|
bgPosition = sizing.position;
|
|
@@ -5464,7 +5540,9 @@ class FigFillPicker extends HTMLElement {
|
|
|
5464
5540
|
? `<span class="fig-fill-picker-type-label">${
|
|
5465
5541
|
lockedMode.charAt(0).toUpperCase() + lockedMode.slice(1)
|
|
5466
5542
|
}</span>`
|
|
5467
|
-
: `<fig-dropdown class="fig-fill-picker-type" variant="neue" value="${
|
|
5543
|
+
: `<fig-dropdown class="fig-fill-picker-type" variant="neue" value="${
|
|
5544
|
+
this.#fillType
|
|
5545
|
+
}">
|
|
5468
5546
|
<option value="solid">Solid</option>
|
|
5469
5547
|
<option value="gradient">Gradient</option>
|
|
5470
5548
|
<option value="image">Image</option>
|
|
@@ -5584,7 +5662,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5584
5662
|
<div class="fig-fill-picker-inputs">
|
|
5585
5663
|
<fig-button icon variant="ghost" class="fig-fill-picker-eyedropper" title="Pick color from screen"><span class="fig-mask-icon" style="--icon: var(--icon-eyedropper)"></span></fig-button>
|
|
5586
5664
|
<fig-input-color class="fig-fill-picker-color-input" text="true" picker="false" value="${this.#hsvToHex(
|
|
5587
|
-
this.#color
|
|
5665
|
+
this.#color
|
|
5588
5666
|
)}"></fig-input-color>
|
|
5589
5667
|
</div>
|
|
5590
5668
|
`;
|
|
@@ -5611,7 +5689,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5611
5689
|
// Setup opacity slider
|
|
5612
5690
|
if (showAlpha) {
|
|
5613
5691
|
this.#opacitySlider = container.querySelector(
|
|
5614
|
-
'fig-slider[type="opacity"]'
|
|
5692
|
+
'fig-slider[type="opacity"]'
|
|
5615
5693
|
);
|
|
5616
5694
|
this.#opacitySlider.addEventListener("input", (e) => {
|
|
5617
5695
|
this.#color.a = parseFloat(e.target.value) / 100;
|
|
@@ -5711,7 +5789,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5711
5789
|
this.#colorAreaHandle.style.top = `${y}px`;
|
|
5712
5790
|
this.#colorAreaHandle.style.setProperty(
|
|
5713
5791
|
"--picker-color",
|
|
5714
|
-
this.#hsvToHex({ ...this.#color, a: 1 })
|
|
5792
|
+
this.#hsvToHex({ ...this.#color, a: 1 })
|
|
5715
5793
|
);
|
|
5716
5794
|
}
|
|
5717
5795
|
|
|
@@ -5774,7 +5852,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5774
5852
|
const hex = this.#hsvToHex(this.#color);
|
|
5775
5853
|
|
|
5776
5854
|
const colorInput = this.#dialog.querySelector(
|
|
5777
|
-
".fig-fill-picker-color-input"
|
|
5855
|
+
".fig-fill-picker-color-input"
|
|
5778
5856
|
);
|
|
5779
5857
|
if (colorInput) {
|
|
5780
5858
|
colorInput.setAttribute("value", hex);
|
|
@@ -5841,7 +5919,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5841
5919
|
#setupGradientEvents(container) {
|
|
5842
5920
|
// Type dropdown
|
|
5843
5921
|
const typeDropdown = container.querySelector(
|
|
5844
|
-
".fig-fill-picker-gradient-type"
|
|
5922
|
+
".fig-fill-picker-gradient-type"
|
|
5845
5923
|
);
|
|
5846
5924
|
typeDropdown.addEventListener("change", (e) => {
|
|
5847
5925
|
this.#gradient.type = e.target.value;
|
|
@@ -5852,7 +5930,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5852
5930
|
// Angle input
|
|
5853
5931
|
// Convert from fig-input-angle coordinates (0° = right) to CSS coordinates (0° = up)
|
|
5854
5932
|
const angleInput = container.querySelector(
|
|
5855
|
-
".fig-fill-picker-gradient-angle"
|
|
5933
|
+
".fig-fill-picker-gradient-angle"
|
|
5856
5934
|
);
|
|
5857
5935
|
angleInput.addEventListener("input", (e) => {
|
|
5858
5936
|
const pickerAngle = parseFloat(e.target.value) || 0;
|
|
@@ -5911,10 +5989,10 @@ class FigFillPicker extends HTMLElement {
|
|
|
5911
5989
|
|
|
5912
5990
|
// Show/hide angle vs center inputs
|
|
5913
5991
|
const angleInput = container.querySelector(
|
|
5914
|
-
".fig-fill-picker-gradient-angle"
|
|
5992
|
+
".fig-fill-picker-gradient-angle"
|
|
5915
5993
|
);
|
|
5916
5994
|
const centerInputs = container.querySelector(
|
|
5917
|
-
".fig-fill-picker-gradient-center"
|
|
5995
|
+
".fig-fill-picker-gradient-center"
|
|
5918
5996
|
);
|
|
5919
5997
|
|
|
5920
5998
|
if (this.#gradient.type === "radial") {
|
|
@@ -5947,7 +6025,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5947
6025
|
if (!this.#dialog) return;
|
|
5948
6026
|
|
|
5949
6027
|
const list = this.#dialog.querySelector(
|
|
5950
|
-
".fig-fill-picker-gradient-stops-list"
|
|
6028
|
+
".fig-fill-picker-gradient-stops-list"
|
|
5951
6029
|
);
|
|
5952
6030
|
if (!list) return;
|
|
5953
6031
|
|
|
@@ -5967,7 +6045,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5967
6045
|
<span class="fig-mask-icon" style="--icon: var(--icon-minus)"></span>
|
|
5968
6046
|
</fig-button>
|
|
5969
6047
|
</div>
|
|
5970
|
-
|
|
6048
|
+
`
|
|
5971
6049
|
)
|
|
5972
6050
|
.join("");
|
|
5973
6051
|
|
|
@@ -6065,7 +6143,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6065
6143
|
|
|
6066
6144
|
#setupImageEvents(container) {
|
|
6067
6145
|
const scaleModeDropdown = container.querySelector(
|
|
6068
|
-
".fig-fill-picker-scale-mode"
|
|
6146
|
+
".fig-fill-picker-scale-mode"
|
|
6069
6147
|
);
|
|
6070
6148
|
const scaleInput = container.querySelector(".fig-fill-picker-scale");
|
|
6071
6149
|
const uploadBtn = container.querySelector(".fig-fill-picker-upload");
|
|
@@ -6107,7 +6185,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6107
6185
|
|
|
6108
6186
|
// Drag and drop
|
|
6109
6187
|
const previewArea = container.querySelector(
|
|
6110
|
-
".fig-fill-picker-media-preview"
|
|
6188
|
+
".fig-fill-picker-media-preview"
|
|
6111
6189
|
);
|
|
6112
6190
|
previewArea.addEventListener("dragover", (e) => {
|
|
6113
6191
|
e.preventDefault();
|
|
@@ -6213,7 +6291,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6213
6291
|
|
|
6214
6292
|
#setupVideoEvents(container) {
|
|
6215
6293
|
const scaleModeDropdown = container.querySelector(
|
|
6216
|
-
".fig-fill-picker-scale-mode"
|
|
6294
|
+
".fig-fill-picker-scale-mode"
|
|
6217
6295
|
);
|
|
6218
6296
|
const uploadBtn = container.querySelector(".fig-fill-picker-upload");
|
|
6219
6297
|
const fileInput = container.querySelector('input[type="file"]');
|
|
@@ -6232,7 +6310,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6232
6310
|
|
|
6233
6311
|
// Drag and drop
|
|
6234
6312
|
const previewArea = container.querySelector(
|
|
6235
|
-
".fig-fill-picker-media-preview"
|
|
6313
|
+
".fig-fill-picker-media-preview"
|
|
6236
6314
|
);
|
|
6237
6315
|
|
|
6238
6316
|
fileInput.addEventListener("change", (e) => {
|
|
@@ -6301,10 +6379,10 @@ class FigFillPicker extends HTMLElement {
|
|
|
6301
6379
|
const video = container.querySelector(".fig-fill-picker-webcam-video");
|
|
6302
6380
|
const status = container.querySelector(".fig-fill-picker-webcam-status");
|
|
6303
6381
|
const captureBtn = container.querySelector(
|
|
6304
|
-
".fig-fill-picker-webcam-capture"
|
|
6382
|
+
".fig-fill-picker-webcam-capture"
|
|
6305
6383
|
);
|
|
6306
6384
|
const cameraSelect = container.querySelector(
|
|
6307
|
-
".fig-fill-picker-camera-select"
|
|
6385
|
+
".fig-fill-picker-camera-select"
|
|
6308
6386
|
);
|
|
6309
6387
|
|
|
6310
6388
|
const startWebcam = async (deviceId = null) => {
|
|
@@ -6317,8 +6395,9 @@ class FigFillPicker extends HTMLElement {
|
|
|
6317
6395
|
this.#webcam.stream.getTracks().forEach((track) => track.stop());
|
|
6318
6396
|
}
|
|
6319
6397
|
|
|
6320
|
-
this.#webcam.stream =
|
|
6321
|
-
|
|
6398
|
+
this.#webcam.stream = await navigator.mediaDevices.getUserMedia(
|
|
6399
|
+
constraints
|
|
6400
|
+
);
|
|
6322
6401
|
video.srcObject = this.#webcam.stream;
|
|
6323
6402
|
video.style.display = "block";
|
|
6324
6403
|
status.style.display = "none";
|
|
@@ -6334,7 +6413,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6334
6413
|
(cam, i) =>
|
|
6335
6414
|
`<option value="${cam.deviceId}">${
|
|
6336
6415
|
cam.label || `Camera ${i + 1}`
|
|
6337
|
-
}</option
|
|
6416
|
+
}</option>`
|
|
6338
6417
|
)
|
|
6339
6418
|
.join("");
|
|
6340
6419
|
}
|
|
@@ -6626,7 +6705,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6626
6705
|
new CustomEvent("input", {
|
|
6627
6706
|
bubbles: true,
|
|
6628
6707
|
detail: this.value,
|
|
6629
|
-
})
|
|
6708
|
+
})
|
|
6630
6709
|
);
|
|
6631
6710
|
}
|
|
6632
6711
|
|
|
@@ -6635,7 +6714,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6635
6714
|
new CustomEvent("change", {
|
|
6636
6715
|
bubbles: true,
|
|
6637
6716
|
detail: this.value,
|
|
6638
|
-
})
|
|
6717
|
+
})
|
|
6639
6718
|
);
|
|
6640
6719
|
}
|
|
6641
6720
|
|
|
@@ -6707,7 +6786,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6707
6786
|
this.#opacitySlider.setAttribute("value", this.#color.a * 100);
|
|
6708
6787
|
this.#opacitySlider.setAttribute(
|
|
6709
6788
|
"color",
|
|
6710
|
-
this.#hsvToHex(this.#color)
|
|
6789
|
+
this.#hsvToHex(this.#color)
|
|
6711
6790
|
);
|
|
6712
6791
|
}
|
|
6713
6792
|
}
|
package/package.json
CHANGED