@rogieking/figui3 2.21.0 → 2.22.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/fig.js +82 -63
- package/index.html +11 -0
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -1177,8 +1177,6 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1177
1177
|
this.#setupDragListeners();
|
|
1178
1178
|
} else {
|
|
1179
1179
|
this.#removeDragListeners();
|
|
1180
|
-
const header = this.querySelector("fig-header, header");
|
|
1181
|
-
if (header) header.style.cursor = "";
|
|
1182
1180
|
}
|
|
1183
1181
|
return;
|
|
1184
1182
|
}
|
|
@@ -1298,19 +1296,32 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1298
1296
|
const anchor = this.#resolveAnchor();
|
|
1299
1297
|
if (anchor && anchor.contains(target)) return;
|
|
1300
1298
|
|
|
1299
|
+
if (this.#isInsideDescendantPopup(target)) return;
|
|
1300
|
+
|
|
1301
1301
|
this.open = false;
|
|
1302
1302
|
}
|
|
1303
1303
|
|
|
1304
|
+
#isInsideDescendantPopup(target) {
|
|
1305
|
+
const targetDialog = target.closest?.('dialog[is="fig-popup"]');
|
|
1306
|
+
if (!targetDialog || targetDialog === this) return false;
|
|
1307
|
+
|
|
1308
|
+
let current = targetDialog;
|
|
1309
|
+
const visited = new Set();
|
|
1310
|
+
while (current && !visited.has(current)) {
|
|
1311
|
+
visited.add(current);
|
|
1312
|
+
const popupAnchor = current.anchor;
|
|
1313
|
+
if (!(popupAnchor instanceof Element)) break;
|
|
1314
|
+
if (this.contains(popupAnchor)) return true;
|
|
1315
|
+
current = popupAnchor.closest?.('dialog[is="fig-popup"]');
|
|
1316
|
+
}
|
|
1317
|
+
return false;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1304
1320
|
// ---- Drag support ----
|
|
1305
1321
|
|
|
1306
1322
|
#setupDragListeners() {
|
|
1307
1323
|
if (this.drag) {
|
|
1308
1324
|
this.addEventListener("pointerdown", this.#boundPointerDown);
|
|
1309
|
-
const handleSelector = this.getAttribute("handle");
|
|
1310
|
-
const handleEl = handleSelector
|
|
1311
|
-
? this.querySelector(handleSelector)
|
|
1312
|
-
: this.querySelector("fig-header, header");
|
|
1313
|
-
if (handleEl) handleEl.style.cursor = "grab";
|
|
1314
1325
|
}
|
|
1315
1326
|
}
|
|
1316
1327
|
|
|
@@ -1527,21 +1538,49 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1527
1538
|
};
|
|
1528
1539
|
}
|
|
1529
1540
|
|
|
1530
|
-
#
|
|
1531
|
-
const
|
|
1532
|
-
top: ["top", "bottom", "center"],
|
|
1533
|
-
center: ["center", "top", "bottom"],
|
|
1534
|
-
bottom: ["bottom", "top", "center"],
|
|
1535
|
-
};
|
|
1536
|
-
const horizontalMap = {
|
|
1537
|
-
left: ["left", "right", "center"],
|
|
1538
|
-
center: ["center", "left", "right"],
|
|
1539
|
-
right: ["right", "left", "center"],
|
|
1540
|
-
};
|
|
1541
|
+
#getPlacementCandidates(vertical, horizontal, shorthand) {
|
|
1542
|
+
const opp = { top: "bottom", bottom: "top", left: "right", right: "left", center: "center" };
|
|
1541
1543
|
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1544
|
+
if (shorthand) {
|
|
1545
|
+
const perp = (shorthand === "left" || shorthand === "right")
|
|
1546
|
+
? ["top", "bottom"]
|
|
1547
|
+
: ["left", "right"];
|
|
1548
|
+
return [
|
|
1549
|
+
{ v: vertical, h: horizontal, s: shorthand },
|
|
1550
|
+
{ v: vertical, h: horizontal, s: opp[shorthand] },
|
|
1551
|
+
{ v: vertical, h: horizontal, s: perp[0] },
|
|
1552
|
+
{ v: vertical, h: horizontal, s: perp[1] },
|
|
1553
|
+
];
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
if (vertical === "center") {
|
|
1557
|
+
return [
|
|
1558
|
+
{ v: "center", h: horizontal, s: null },
|
|
1559
|
+
{ v: "center", h: opp[horizontal], s: null },
|
|
1560
|
+
{ v: "top", h: horizontal, s: null },
|
|
1561
|
+
{ v: "bottom", h: horizontal, s: null },
|
|
1562
|
+
{ v: "top", h: opp[horizontal], s: null },
|
|
1563
|
+
{ v: "bottom", h: opp[horizontal], s: null },
|
|
1564
|
+
];
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
if (horizontal === "center") {
|
|
1568
|
+
return [
|
|
1569
|
+
{ v: vertical, h: "center", s: null },
|
|
1570
|
+
{ v: opp[vertical], h: "center", s: null },
|
|
1571
|
+
{ v: vertical, h: "left", s: null },
|
|
1572
|
+
{ v: vertical, h: "right", s: null },
|
|
1573
|
+
{ v: opp[vertical], h: "left", s: null },
|
|
1574
|
+
{ v: opp[vertical], h: "right", s: null },
|
|
1575
|
+
];
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
return [
|
|
1579
|
+
{ v: vertical, h: horizontal, s: null },
|
|
1580
|
+
{ v: opp[vertical], h: horizontal, s: null },
|
|
1581
|
+
{ v: vertical, h: opp[horizontal], s: null },
|
|
1582
|
+
{ v: opp[vertical], h: opp[horizontal], s: null },
|
|
1583
|
+
];
|
|
1545
1584
|
}
|
|
1546
1585
|
|
|
1547
1586
|
#computeCoords(anchorRect, popupRect, vertical, horizontal, offset, shorthand) {
|
|
@@ -1695,8 +1734,6 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1695
1734
|
const popupRect = this.getBoundingClientRect();
|
|
1696
1735
|
const offset = this.#parseOffset();
|
|
1697
1736
|
const { vertical, horizontal, shorthand } = this.#parsePosition();
|
|
1698
|
-
const verticalOrder = this.#getOrder(vertical, "vertical");
|
|
1699
|
-
const horizontalOrder = this.#getOrder(horizontal, "horizontal");
|
|
1700
1737
|
const anchor = this.#resolveAnchor();
|
|
1701
1738
|
|
|
1702
1739
|
if (!anchor) {
|
|
@@ -1712,52 +1749,32 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1712
1749
|
}
|
|
1713
1750
|
|
|
1714
1751
|
const anchorRect = anchor.getBoundingClientRect();
|
|
1752
|
+
const candidates = this.#getPlacementCandidates(vertical, horizontal, shorthand);
|
|
1715
1753
|
let best = null;
|
|
1716
1754
|
let bestSide = "top";
|
|
1717
1755
|
let bestScore = Number.POSITIVE_INFINITY;
|
|
1718
1756
|
|
|
1719
|
-
for (const v of
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
this.#updatePopoverBeak(
|
|
1734
|
-
anchorRect,
|
|
1735
|
-
popupRect,
|
|
1736
|
-
coords.left,
|
|
1737
|
-
coords.top,
|
|
1738
|
-
placementSide
|
|
1739
|
-
);
|
|
1740
|
-
return;
|
|
1741
|
-
}
|
|
1742
|
-
const score = this.#overflowScore(coords, popupRect);
|
|
1743
|
-
if (score < bestScore) {
|
|
1744
|
-
bestScore = score;
|
|
1745
|
-
best = coords;
|
|
1746
|
-
bestSide = placementSide;
|
|
1747
|
-
}
|
|
1757
|
+
for (const { v, h, s } of candidates) {
|
|
1758
|
+
const coords = this.#computeCoords(anchorRect, popupRect, v, h, offset, s);
|
|
1759
|
+
const placementSide = this.#getPlacementSide(v, h, s);
|
|
1760
|
+
if (this.#fits(coords, popupRect)) {
|
|
1761
|
+
this.style.left = `${coords.left}px`;
|
|
1762
|
+
this.style.top = `${coords.top}px`;
|
|
1763
|
+
this.#updatePopoverBeak(anchorRect, popupRect, coords.left, coords.top, placementSide);
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
const score = this.#overflowScore(coords, popupRect);
|
|
1767
|
+
if (score < bestScore) {
|
|
1768
|
+
bestScore = score;
|
|
1769
|
+
best = coords;
|
|
1770
|
+
bestSide = placementSide;
|
|
1748
1771
|
}
|
|
1749
1772
|
}
|
|
1750
1773
|
|
|
1751
1774
|
const clamped = this.#clamp(best || { left: 0, top: 0 }, popupRect);
|
|
1752
1775
|
this.style.left = `${clamped.left}px`;
|
|
1753
1776
|
this.style.top = `${clamped.top}px`;
|
|
1754
|
-
this.#updatePopoverBeak(
|
|
1755
|
-
anchorRect,
|
|
1756
|
-
popupRect,
|
|
1757
|
-
clamped.left,
|
|
1758
|
-
clamped.top,
|
|
1759
|
-
bestSide
|
|
1760
|
-
);
|
|
1777
|
+
this.#updatePopoverBeak(anchorRect, popupRect, clamped.left, clamped.top, bestSide);
|
|
1761
1778
|
}
|
|
1762
1779
|
|
|
1763
1780
|
#queueReposition() {
|
|
@@ -3352,6 +3369,8 @@ class FigInputColor extends HTMLElement {
|
|
|
3352
3369
|
const showAlpha = this.getAttribute("alpha") === "true";
|
|
3353
3370
|
const experimental = this.getAttribute("experimental");
|
|
3354
3371
|
const expAttr = experimental ? `experimental="${experimental}"` : "";
|
|
3372
|
+
const dialogPos = this.getAttribute("dialog-position") || "left";
|
|
3373
|
+
const dialogPosAttr = `dialog-position="${dialogPos}"`;
|
|
3355
3374
|
|
|
3356
3375
|
let html = ``;
|
|
3357
3376
|
if (this.getAttribute("text")) {
|
|
@@ -3376,7 +3395,7 @@ class FigInputColor extends HTMLElement {
|
|
|
3376
3395
|
let swatchElement = "";
|
|
3377
3396
|
if (!hidePicker) {
|
|
3378
3397
|
swatchElement = useFigmaPicker
|
|
3379
|
-
? `<fig-fill-picker mode="solid"
|
|
3398
|
+
? `<fig-fill-picker mode="solid" ${dialogPosAttr} ${expAttr} ${
|
|
3380
3399
|
showAlpha ? "" : 'alpha="false"'
|
|
3381
3400
|
} value='{"type":"solid","color":"${this.hexOpaque}","opacity":${
|
|
3382
3401
|
this.alpha
|
|
@@ -3394,7 +3413,7 @@ class FigInputColor extends HTMLElement {
|
|
|
3394
3413
|
html = ``;
|
|
3395
3414
|
} else {
|
|
3396
3415
|
html = useFigmaPicker
|
|
3397
|
-
? `<fig-fill-picker mode="solid"
|
|
3416
|
+
? `<fig-fill-picker mode="solid" ${dialogPosAttr} ${expAttr} ${
|
|
3398
3417
|
showAlpha ? "" : 'alpha="false"'
|
|
3399
3418
|
} value='{"type":"solid","color":"${this.hexOpaque}","opacity":${
|
|
3400
3419
|
this.alpha
|
|
@@ -3586,7 +3605,7 @@ class FigInputColor extends HTMLElement {
|
|
|
3586
3605
|
}
|
|
3587
3606
|
|
|
3588
3607
|
static get observedAttributes() {
|
|
3589
|
-
return ["value", "style", "mode", "picker", "experimental"];
|
|
3608
|
+
return ["value", "style", "mode", "picker", "experimental", "dialog-position"];
|
|
3590
3609
|
}
|
|
3591
3610
|
|
|
3592
3611
|
get mode() {
|
|
@@ -6957,7 +6976,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
6957
6976
|
<fig-input-number class="fig-fill-picker-stop-position" min="0" max="100" value="${
|
|
6958
6977
|
stop.position
|
|
6959
6978
|
}" units="%"></fig-input-number>
|
|
6960
|
-
<fig-input-color class="fig-fill-picker-stop-color" text="true" alpha="true" picker="figma" value="${
|
|
6979
|
+
<fig-input-color class="fig-fill-picker-stop-color" text="true" alpha="true" picker="figma" dialog-position="right" value="${
|
|
6961
6980
|
stop.color
|
|
6962
6981
|
}"></fig-input-color>
|
|
6963
6982
|
<fig-button icon variant="ghost" class="fig-fill-picker-stop-remove" ${
|
package/index.html
CHANGED
|
@@ -1806,6 +1806,13 @@
|
|
|
1806
1806
|
alpha="true"
|
|
1807
1807
|
picker="figma"></fig-input-color>
|
|
1808
1808
|
|
|
1809
|
+
<h4>Figma Picker (Experimental Modern)</h4>
|
|
1810
|
+
<fig-input-color value="#E84393"
|
|
1811
|
+
text="true"
|
|
1812
|
+
alpha="true"
|
|
1813
|
+
picker="figma"
|
|
1814
|
+
experimental="modern"></fig-input-color>
|
|
1815
|
+
|
|
1809
1816
|
<h4>No Picker (text input only)</h4>
|
|
1810
1817
|
<fig-input-color value="#9747FF"
|
|
1811
1818
|
text="true"
|
|
@@ -1995,6 +2002,10 @@
|
|
|
1995
2002
|
<h3>Webcam Fill</h3>
|
|
1996
2003
|
<fig-input-fill value='{"type":"webcam","webcam":{"opacity":1}}'></fig-input-fill>
|
|
1997
2004
|
|
|
2005
|
+
<h3>Experimental Modern</h3>
|
|
2006
|
+
<fig-input-fill experimental="modern"
|
|
2007
|
+
value='{"type":"solid","color":"#E84393","alpha":1}'></fig-input-fill>
|
|
2008
|
+
|
|
1998
2009
|
<h3>Disabled</h3>
|
|
1999
2010
|
<fig-input-fill disabled
|
|
2000
2011
|
value='{"type":"solid","color":"#AA96DA","alpha":1}'></fig-input-fill>
|
package/package.json
CHANGED