@rogieking/figui3 2.11.1 → 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 +195 -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() {
|
|
@@ -4948,6 +5012,7 @@ class FigInputAngle extends HTMLElement {
|
|
|
4948
5012
|
if (this.angleInput) {
|
|
4949
5013
|
this.angleInput.setAttribute("value", this.angle.toFixed(this.precision));
|
|
4950
5014
|
}
|
|
5015
|
+
this.#updateRotationDisplay();
|
|
4951
5016
|
}
|
|
4952
5017
|
|
|
4953
5018
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -4995,6 +5060,14 @@ class FigInputAngle extends HTMLElement {
|
|
|
4995
5060
|
this.#syncHandlePosition();
|
|
4996
5061
|
}
|
|
4997
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;
|
|
4998
5071
|
}
|
|
4999
5072
|
}
|
|
5000
5073
|
}
|
|
@@ -5095,7 +5168,7 @@ class FigLayer extends HTMLElement {
|
|
|
5095
5168
|
new CustomEvent("openchange", {
|
|
5096
5169
|
detail: { open: value },
|
|
5097
5170
|
bubbles: true,
|
|
5098
|
-
})
|
|
5171
|
+
})
|
|
5099
5172
|
);
|
|
5100
5173
|
}
|
|
5101
5174
|
}
|
|
@@ -5117,7 +5190,7 @@ class FigLayer extends HTMLElement {
|
|
|
5117
5190
|
new CustomEvent("visibilitychange", {
|
|
5118
5191
|
detail: { visible: value },
|
|
5119
5192
|
bubbles: true,
|
|
5120
|
-
})
|
|
5193
|
+
})
|
|
5121
5194
|
);
|
|
5122
5195
|
}
|
|
5123
5196
|
}
|
|
@@ -5131,7 +5204,7 @@ class FigLayer extends HTMLElement {
|
|
|
5131
5204
|
new CustomEvent("openchange", {
|
|
5132
5205
|
detail: { open: isOpen },
|
|
5133
5206
|
bubbles: true,
|
|
5134
|
-
})
|
|
5207
|
+
})
|
|
5135
5208
|
);
|
|
5136
5209
|
}
|
|
5137
5210
|
|
|
@@ -5141,7 +5214,7 @@ class FigLayer extends HTMLElement {
|
|
|
5141
5214
|
new CustomEvent("visibilitychange", {
|
|
5142
5215
|
detail: { visible: isVisible },
|
|
5143
5216
|
bubbles: true,
|
|
5144
|
-
})
|
|
5217
|
+
})
|
|
5145
5218
|
);
|
|
5146
5219
|
}
|
|
5147
5220
|
}
|
|
@@ -5305,7 +5378,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5305
5378
|
bg = `url(${this.#image.url})`;
|
|
5306
5379
|
const sizing = this.#getBackgroundSizing(
|
|
5307
5380
|
this.#image.scaleMode,
|
|
5308
|
-
this.#image.scale
|
|
5381
|
+
this.#image.scale
|
|
5309
5382
|
);
|
|
5310
5383
|
bgSize = sizing.size;
|
|
5311
5384
|
bgPosition = sizing.position;
|
|
@@ -5318,7 +5391,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5318
5391
|
bg = `url(${this.#video.url})`;
|
|
5319
5392
|
const sizing = this.#getBackgroundSizing(
|
|
5320
5393
|
this.#video.scaleMode,
|
|
5321
|
-
this.#video.scale
|
|
5394
|
+
this.#video.scale
|
|
5322
5395
|
);
|
|
5323
5396
|
bgSize = sizing.size;
|
|
5324
5397
|
bgPosition = sizing.position;
|
|
@@ -5467,7 +5540,9 @@ class FigFillPicker extends HTMLElement {
|
|
|
5467
5540
|
? `<span class="fig-fill-picker-type-label">${
|
|
5468
5541
|
lockedMode.charAt(0).toUpperCase() + lockedMode.slice(1)
|
|
5469
5542
|
}</span>`
|
|
5470
|
-
: `<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
|
+
}">
|
|
5471
5546
|
<option value="solid">Solid</option>
|
|
5472
5547
|
<option value="gradient">Gradient</option>
|
|
5473
5548
|
<option value="image">Image</option>
|
|
@@ -5587,7 +5662,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5587
5662
|
<div class="fig-fill-picker-inputs">
|
|
5588
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>
|
|
5589
5664
|
<fig-input-color class="fig-fill-picker-color-input" text="true" picker="false" value="${this.#hsvToHex(
|
|
5590
|
-
this.#color
|
|
5665
|
+
this.#color
|
|
5591
5666
|
)}"></fig-input-color>
|
|
5592
5667
|
</div>
|
|
5593
5668
|
`;
|
|
@@ -5614,7 +5689,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5614
5689
|
// Setup opacity slider
|
|
5615
5690
|
if (showAlpha) {
|
|
5616
5691
|
this.#opacitySlider = container.querySelector(
|
|
5617
|
-
'fig-slider[type="opacity"]'
|
|
5692
|
+
'fig-slider[type="opacity"]'
|
|
5618
5693
|
);
|
|
5619
5694
|
this.#opacitySlider.addEventListener("input", (e) => {
|
|
5620
5695
|
this.#color.a = parseFloat(e.target.value) / 100;
|
|
@@ -5714,7 +5789,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5714
5789
|
this.#colorAreaHandle.style.top = `${y}px`;
|
|
5715
5790
|
this.#colorAreaHandle.style.setProperty(
|
|
5716
5791
|
"--picker-color",
|
|
5717
|
-
this.#hsvToHex({ ...this.#color, a: 1 })
|
|
5792
|
+
this.#hsvToHex({ ...this.#color, a: 1 })
|
|
5718
5793
|
);
|
|
5719
5794
|
}
|
|
5720
5795
|
|
|
@@ -5777,7 +5852,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5777
5852
|
const hex = this.#hsvToHex(this.#color);
|
|
5778
5853
|
|
|
5779
5854
|
const colorInput = this.#dialog.querySelector(
|
|
5780
|
-
".fig-fill-picker-color-input"
|
|
5855
|
+
".fig-fill-picker-color-input"
|
|
5781
5856
|
);
|
|
5782
5857
|
if (colorInput) {
|
|
5783
5858
|
colorInput.setAttribute("value", hex);
|
|
@@ -5844,7 +5919,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5844
5919
|
#setupGradientEvents(container) {
|
|
5845
5920
|
// Type dropdown
|
|
5846
5921
|
const typeDropdown = container.querySelector(
|
|
5847
|
-
".fig-fill-picker-gradient-type"
|
|
5922
|
+
".fig-fill-picker-gradient-type"
|
|
5848
5923
|
);
|
|
5849
5924
|
typeDropdown.addEventListener("change", (e) => {
|
|
5850
5925
|
this.#gradient.type = e.target.value;
|
|
@@ -5855,7 +5930,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5855
5930
|
// Angle input
|
|
5856
5931
|
// Convert from fig-input-angle coordinates (0° = right) to CSS coordinates (0° = up)
|
|
5857
5932
|
const angleInput = container.querySelector(
|
|
5858
|
-
".fig-fill-picker-gradient-angle"
|
|
5933
|
+
".fig-fill-picker-gradient-angle"
|
|
5859
5934
|
);
|
|
5860
5935
|
angleInput.addEventListener("input", (e) => {
|
|
5861
5936
|
const pickerAngle = parseFloat(e.target.value) || 0;
|
|
@@ -5914,10 +5989,10 @@ class FigFillPicker extends HTMLElement {
|
|
|
5914
5989
|
|
|
5915
5990
|
// Show/hide angle vs center inputs
|
|
5916
5991
|
const angleInput = container.querySelector(
|
|
5917
|
-
".fig-fill-picker-gradient-angle"
|
|
5992
|
+
".fig-fill-picker-gradient-angle"
|
|
5918
5993
|
);
|
|
5919
5994
|
const centerInputs = container.querySelector(
|
|
5920
|
-
".fig-fill-picker-gradient-center"
|
|
5995
|
+
".fig-fill-picker-gradient-center"
|
|
5921
5996
|
);
|
|
5922
5997
|
|
|
5923
5998
|
if (this.#gradient.type === "radial") {
|
|
@@ -5950,7 +6025,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5950
6025
|
if (!this.#dialog) return;
|
|
5951
6026
|
|
|
5952
6027
|
const list = this.#dialog.querySelector(
|
|
5953
|
-
".fig-fill-picker-gradient-stops-list"
|
|
6028
|
+
".fig-fill-picker-gradient-stops-list"
|
|
5954
6029
|
);
|
|
5955
6030
|
if (!list) return;
|
|
5956
6031
|
|
|
@@ -5970,7 +6045,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5970
6045
|
<span class="fig-mask-icon" style="--icon: var(--icon-minus)"></span>
|
|
5971
6046
|
</fig-button>
|
|
5972
6047
|
</div>
|
|
5973
|
-
|
|
6048
|
+
`
|
|
5974
6049
|
)
|
|
5975
6050
|
.join("");
|
|
5976
6051
|
|
|
@@ -6068,7 +6143,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6068
6143
|
|
|
6069
6144
|
#setupImageEvents(container) {
|
|
6070
6145
|
const scaleModeDropdown = container.querySelector(
|
|
6071
|
-
".fig-fill-picker-scale-mode"
|
|
6146
|
+
".fig-fill-picker-scale-mode"
|
|
6072
6147
|
);
|
|
6073
6148
|
const scaleInput = container.querySelector(".fig-fill-picker-scale");
|
|
6074
6149
|
const uploadBtn = container.querySelector(".fig-fill-picker-upload");
|
|
@@ -6110,7 +6185,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6110
6185
|
|
|
6111
6186
|
// Drag and drop
|
|
6112
6187
|
const previewArea = container.querySelector(
|
|
6113
|
-
".fig-fill-picker-media-preview"
|
|
6188
|
+
".fig-fill-picker-media-preview"
|
|
6114
6189
|
);
|
|
6115
6190
|
previewArea.addEventListener("dragover", (e) => {
|
|
6116
6191
|
e.preventDefault();
|
|
@@ -6216,7 +6291,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6216
6291
|
|
|
6217
6292
|
#setupVideoEvents(container) {
|
|
6218
6293
|
const scaleModeDropdown = container.querySelector(
|
|
6219
|
-
".fig-fill-picker-scale-mode"
|
|
6294
|
+
".fig-fill-picker-scale-mode"
|
|
6220
6295
|
);
|
|
6221
6296
|
const uploadBtn = container.querySelector(".fig-fill-picker-upload");
|
|
6222
6297
|
const fileInput = container.querySelector('input[type="file"]');
|
|
@@ -6235,7 +6310,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6235
6310
|
|
|
6236
6311
|
// Drag and drop
|
|
6237
6312
|
const previewArea = container.querySelector(
|
|
6238
|
-
".fig-fill-picker-media-preview"
|
|
6313
|
+
".fig-fill-picker-media-preview"
|
|
6239
6314
|
);
|
|
6240
6315
|
|
|
6241
6316
|
fileInput.addEventListener("change", (e) => {
|
|
@@ -6304,10 +6379,10 @@ class FigFillPicker extends HTMLElement {
|
|
|
6304
6379
|
const video = container.querySelector(".fig-fill-picker-webcam-video");
|
|
6305
6380
|
const status = container.querySelector(".fig-fill-picker-webcam-status");
|
|
6306
6381
|
const captureBtn = container.querySelector(
|
|
6307
|
-
".fig-fill-picker-webcam-capture"
|
|
6382
|
+
".fig-fill-picker-webcam-capture"
|
|
6308
6383
|
);
|
|
6309
6384
|
const cameraSelect = container.querySelector(
|
|
6310
|
-
".fig-fill-picker-camera-select"
|
|
6385
|
+
".fig-fill-picker-camera-select"
|
|
6311
6386
|
);
|
|
6312
6387
|
|
|
6313
6388
|
const startWebcam = async (deviceId = null) => {
|
|
@@ -6320,8 +6395,9 @@ class FigFillPicker extends HTMLElement {
|
|
|
6320
6395
|
this.#webcam.stream.getTracks().forEach((track) => track.stop());
|
|
6321
6396
|
}
|
|
6322
6397
|
|
|
6323
|
-
this.#webcam.stream =
|
|
6324
|
-
|
|
6398
|
+
this.#webcam.stream = await navigator.mediaDevices.getUserMedia(
|
|
6399
|
+
constraints
|
|
6400
|
+
);
|
|
6325
6401
|
video.srcObject = this.#webcam.stream;
|
|
6326
6402
|
video.style.display = "block";
|
|
6327
6403
|
status.style.display = "none";
|
|
@@ -6337,7 +6413,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6337
6413
|
(cam, i) =>
|
|
6338
6414
|
`<option value="${cam.deviceId}">${
|
|
6339
6415
|
cam.label || `Camera ${i + 1}`
|
|
6340
|
-
}</option
|
|
6416
|
+
}</option>`
|
|
6341
6417
|
)
|
|
6342
6418
|
.join("");
|
|
6343
6419
|
}
|
|
@@ -6629,7 +6705,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6629
6705
|
new CustomEvent("input", {
|
|
6630
6706
|
bubbles: true,
|
|
6631
6707
|
detail: this.value,
|
|
6632
|
-
})
|
|
6708
|
+
})
|
|
6633
6709
|
);
|
|
6634
6710
|
}
|
|
6635
6711
|
|
|
@@ -6638,7 +6714,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6638
6714
|
new CustomEvent("change", {
|
|
6639
6715
|
bubbles: true,
|
|
6640
6716
|
detail: this.value,
|
|
6641
|
-
})
|
|
6717
|
+
})
|
|
6642
6718
|
);
|
|
6643
6719
|
}
|
|
6644
6720
|
|
|
@@ -6710,7 +6786,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6710
6786
|
this.#opacitySlider.setAttribute("value", this.#color.a * 100);
|
|
6711
6787
|
this.#opacitySlider.setAttribute(
|
|
6712
6788
|
"color",
|
|
6713
|
-
this.#hsvToHex(this.#color)
|
|
6789
|
+
this.#hsvToHex(this.#color)
|
|
6714
6790
|
);
|
|
6715
6791
|
}
|
|
6716
6792
|
}
|
package/package.json
CHANGED