@rogieking/figui3 2.22.3 → 2.24.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 +3 -3
- package/fig.js +46 -48
- package/index.html +22 -1
- package/package.json +1 -1
- package/dist/fig.js +0 -74
package/components.css
CHANGED
|
@@ -466,7 +466,6 @@ input[type="text"][list] {
|
|
|
466
466
|
}
|
|
467
467
|
}
|
|
468
468
|
|
|
469
|
-
max-inline-size: var(--max-width);
|
|
470
469
|
padding-block: 0;
|
|
471
470
|
will-change: scale;
|
|
472
471
|
|
|
@@ -599,8 +598,9 @@ fig-dropdown,
|
|
|
599
598
|
display: none !important;
|
|
600
599
|
}
|
|
601
600
|
> select {
|
|
602
|
-
display:
|
|
603
|
-
|
|
601
|
+
display: flex;
|
|
602
|
+
align-items: center;
|
|
603
|
+
flex: 1;
|
|
604
604
|
}
|
|
605
605
|
|
|
606
606
|
/* Chevron icon using mask-image for light-dark support */
|
package/fig.js
CHANGED
|
@@ -1055,7 +1055,6 @@ customElements.define("fig-dialog", FigDialog, { extends: "dialog" });
|
|
|
1055
1055
|
* @attr {boolean|string} open - Open when present and not "false".
|
|
1056
1056
|
*/
|
|
1057
1057
|
class FigPopup extends HTMLDialogElement {
|
|
1058
|
-
#viewportPadding = 8;
|
|
1059
1058
|
#anchorObserver = null;
|
|
1060
1059
|
#contentObserver = null;
|
|
1061
1060
|
#mutationObserver = null;
|
|
@@ -1078,7 +1077,9 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1078
1077
|
constructor() {
|
|
1079
1078
|
super();
|
|
1080
1079
|
this.#boundReposition = this.#queueReposition.bind(this);
|
|
1081
|
-
this.#boundScroll = () => {
|
|
1080
|
+
this.#boundScroll = (e) => {
|
|
1081
|
+
if (this.open && !this.contains(e.target)) this.#positionPopup();
|
|
1082
|
+
};
|
|
1082
1083
|
this.#boundOutsidePointerDown = this.#handleOutsidePointerDown.bind(this);
|
|
1083
1084
|
this.#boundPointerDown = this.#handlePointerDown.bind(this);
|
|
1084
1085
|
this.#boundPointerMove = this.#handlePointerMove.bind(this);
|
|
@@ -1086,7 +1087,7 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1086
1087
|
}
|
|
1087
1088
|
|
|
1088
1089
|
static get observedAttributes() {
|
|
1089
|
-
return ["open", "anchor", "position", "offset", "variant", "theme", "drag", "handle", "autoresize"];
|
|
1090
|
+
return ["open", "anchor", "position", "offset", "variant", "theme", "drag", "handle", "autoresize", "viewport-margin"];
|
|
1090
1091
|
}
|
|
1091
1092
|
|
|
1092
1093
|
get open() {
|
|
@@ -1544,6 +1545,17 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1544
1545
|
};
|
|
1545
1546
|
}
|
|
1546
1547
|
|
|
1548
|
+
#parseViewportMargins() {
|
|
1549
|
+
const raw = (this.getAttribute("viewport-margin") || "8").trim();
|
|
1550
|
+
const tokens = raw.split(/\s+/).map(Number).filter(n => !Number.isNaN(n));
|
|
1551
|
+
const d = 8;
|
|
1552
|
+
if (tokens.length === 0) return { top: d, right: d, bottom: d, left: d };
|
|
1553
|
+
if (tokens.length === 1) return { top: tokens[0], right: tokens[0], bottom: tokens[0], left: tokens[0] };
|
|
1554
|
+
if (tokens.length === 2) return { top: tokens[0], right: tokens[1], bottom: tokens[0], left: tokens[1] };
|
|
1555
|
+
if (tokens.length === 3) return { top: tokens[0], right: tokens[1], bottom: tokens[2], left: tokens[1] };
|
|
1556
|
+
return { top: tokens[0], right: tokens[1], bottom: tokens[2], left: tokens[3] };
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1547
1559
|
#getPlacementCandidates(vertical, horizontal, shorthand) {
|
|
1548
1560
|
const opp = { top: "bottom", bottom: "top", left: "right", right: "left", center: "center" };
|
|
1549
1561
|
|
|
@@ -1688,31 +1700,29 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1688
1700
|
this.style.setProperty("--beak-offset", `${beakOffset}px`);
|
|
1689
1701
|
}
|
|
1690
1702
|
|
|
1691
|
-
#overflowScore(coords, popupRect) {
|
|
1703
|
+
#overflowScore(coords, popupRect, m) {
|
|
1692
1704
|
const vw = window.innerWidth;
|
|
1693
1705
|
const vh = window.innerHeight;
|
|
1694
1706
|
const right = coords.left + popupRect.width;
|
|
1695
1707
|
const bottom = coords.top + popupRect.height;
|
|
1696
|
-
const pad = this.#viewportPadding;
|
|
1697
1708
|
|
|
1698
|
-
const overflowLeft = Math.max(0,
|
|
1699
|
-
const overflowTop = Math.max(0,
|
|
1700
|
-
const overflowRight = Math.max(0, right - (vw -
|
|
1701
|
-
const overflowBottom = Math.max(0, bottom - (vh -
|
|
1709
|
+
const overflowLeft = Math.max(0, m.left - coords.left);
|
|
1710
|
+
const overflowTop = Math.max(0, m.top - coords.top);
|
|
1711
|
+
const overflowRight = Math.max(0, right - (vw - m.right));
|
|
1712
|
+
const overflowBottom = Math.max(0, bottom - (vh - m.bottom));
|
|
1702
1713
|
|
|
1703
1714
|
return overflowLeft + overflowTop + overflowRight + overflowBottom;
|
|
1704
1715
|
}
|
|
1705
1716
|
|
|
1706
|
-
#fits(coords, popupRect) {
|
|
1707
|
-
return this.#overflowScore(coords, popupRect) === 0;
|
|
1717
|
+
#fits(coords, popupRect, m) {
|
|
1718
|
+
return this.#overflowScore(coords, popupRect, m) === 0;
|
|
1708
1719
|
}
|
|
1709
1720
|
|
|
1710
|
-
#clamp(coords, popupRect) {
|
|
1711
|
-
const
|
|
1712
|
-
const
|
|
1713
|
-
const
|
|
1714
|
-
const
|
|
1715
|
-
const maxTop = Math.max(pad, window.innerHeight - popupRect.height - pad);
|
|
1721
|
+
#clamp(coords, popupRect, m) {
|
|
1722
|
+
const minLeft = m.left;
|
|
1723
|
+
const minTop = m.top;
|
|
1724
|
+
const maxLeft = Math.max(m.left, window.innerWidth - popupRect.width - m.right);
|
|
1725
|
+
const maxTop = Math.max(m.top, window.innerHeight - popupRect.height - m.bottom);
|
|
1716
1726
|
|
|
1717
1727
|
return {
|
|
1718
1728
|
left: Math.min(maxLeft, Math.max(minLeft, coords.left)),
|
|
@@ -1727,14 +1737,15 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1727
1737
|
const offset = this.#parseOffset();
|
|
1728
1738
|
const { vertical, horizontal, shorthand } = this.#parsePosition();
|
|
1729
1739
|
const anchor = this.#resolveAnchor();
|
|
1740
|
+
const m = this.#parseViewportMargins();
|
|
1730
1741
|
|
|
1731
1742
|
if (!anchor) {
|
|
1732
1743
|
this.#updatePopoverBeak(null, popupRect, 0, 0, "top");
|
|
1733
1744
|
const centered = {
|
|
1734
|
-
left: (window.innerWidth - popupRect.width) / 2,
|
|
1735
|
-
top: (window.innerHeight - popupRect.height) / 2,
|
|
1745
|
+
left: (m.left + (window.innerWidth - m.right - m.left - popupRect.width) / 2),
|
|
1746
|
+
top: (m.top + (window.innerHeight - m.bottom - m.top - popupRect.height) / 2),
|
|
1736
1747
|
};
|
|
1737
|
-
const clamped = this.#clamp(centered, popupRect);
|
|
1748
|
+
const clamped = this.#clamp(centered, popupRect, m);
|
|
1738
1749
|
this.style.left = `${clamped.left}px`;
|
|
1739
1750
|
this.style.top = `${clamped.top}px`;
|
|
1740
1751
|
return;
|
|
@@ -1751,31 +1762,30 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1751
1762
|
const placementSide = this.#getPlacementSide(v, h, s);
|
|
1752
1763
|
|
|
1753
1764
|
if (s) {
|
|
1754
|
-
|
|
1755
|
-
const clamped = this.#clamp(coords, popupRect);
|
|
1765
|
+
const clamped = this.#clamp(coords, popupRect, m);
|
|
1756
1766
|
const primaryFits = (s === "left" || s === "right")
|
|
1757
|
-
? (coords.left >=
|
|
1758
|
-
: (coords.top >=
|
|
1767
|
+
? (coords.left >= m.left && coords.left + popupRect.width <= window.innerWidth - m.right)
|
|
1768
|
+
: (coords.top >= m.top && coords.top + popupRect.height <= window.innerHeight - m.bottom);
|
|
1759
1769
|
if (primaryFits) {
|
|
1760
1770
|
this.style.left = `${clamped.left}px`;
|
|
1761
1771
|
this.style.top = `${clamped.top}px`;
|
|
1762
1772
|
this.#updatePopoverBeak(anchorRect, popupRect, clamped.left, clamped.top, placementSide);
|
|
1763
1773
|
return;
|
|
1764
1774
|
}
|
|
1765
|
-
const score = this.#overflowScore(coords, popupRect);
|
|
1775
|
+
const score = this.#overflowScore(coords, popupRect, m);
|
|
1766
1776
|
if (score < bestScore) {
|
|
1767
1777
|
bestScore = score;
|
|
1768
1778
|
best = clamped;
|
|
1769
1779
|
bestSide = placementSide;
|
|
1770
1780
|
}
|
|
1771
1781
|
} else {
|
|
1772
|
-
if (this.#fits(coords, popupRect)) {
|
|
1782
|
+
if (this.#fits(coords, popupRect, m)) {
|
|
1773
1783
|
this.style.left = `${coords.left}px`;
|
|
1774
1784
|
this.style.top = `${coords.top}px`;
|
|
1775
1785
|
this.#updatePopoverBeak(anchorRect, popupRect, coords.left, coords.top, placementSide);
|
|
1776
1786
|
return;
|
|
1777
1787
|
}
|
|
1778
|
-
const score = this.#overflowScore(coords, popupRect);
|
|
1788
|
+
const score = this.#overflowScore(coords, popupRect, m);
|
|
1779
1789
|
if (score < bestScore) {
|
|
1780
1790
|
bestScore = score;
|
|
1781
1791
|
best = coords;
|
|
@@ -1784,7 +1794,7 @@ class FigPopup extends HTMLDialogElement {
|
|
|
1784
1794
|
}
|
|
1785
1795
|
}
|
|
1786
1796
|
|
|
1787
|
-
const clamped = this.#clamp(best || { left: 0, top: 0 }, popupRect);
|
|
1797
|
+
const clamped = this.#clamp(best || { left: 0, top: 0 }, popupRect, m);
|
|
1788
1798
|
this.style.left = `${clamped.left}px`;
|
|
1789
1799
|
this.style.top = `${clamped.top}px`;
|
|
1790
1800
|
this.#updatePopoverBeak(anchorRect, popupRect, clamped.left, clamped.top, bestSide);
|
|
@@ -5066,6 +5076,8 @@ customElements.define("fig-chit", FigChit);
|
|
|
5066
5076
|
*/
|
|
5067
5077
|
class FigImage extends HTMLElement {
|
|
5068
5078
|
#src = null;
|
|
5079
|
+
#boundHandleFileInput = this.#handleFileInput.bind(this);
|
|
5080
|
+
#boundHandleDownload = this.#handleDownload.bind(this);
|
|
5069
5081
|
constructor() {
|
|
5070
5082
|
super();
|
|
5071
5083
|
}
|
|
@@ -5098,10 +5110,8 @@ class FigImage extends HTMLElement {
|
|
|
5098
5110
|
this.#updateRefs();
|
|
5099
5111
|
}
|
|
5100
5112
|
disconnectedCallback() {
|
|
5101
|
-
this.fileInput
|
|
5102
|
-
|
|
5103
|
-
this.#handleFileInput.bind(this)
|
|
5104
|
-
);
|
|
5113
|
+
this.fileInput?.removeEventListener("change", this.#boundHandleFileInput);
|
|
5114
|
+
this.downloadButton?.removeEventListener("click", this.#boundHandleDownload);
|
|
5105
5115
|
}
|
|
5106
5116
|
|
|
5107
5117
|
#updateRefs() {
|
|
@@ -5110,25 +5120,13 @@ class FigImage extends HTMLElement {
|
|
|
5110
5120
|
if (this.upload) {
|
|
5111
5121
|
this.uploadButton = this.querySelector("fig-button[type='upload']");
|
|
5112
5122
|
this.fileInput = this.uploadButton?.querySelector("input");
|
|
5113
|
-
this.fileInput
|
|
5114
|
-
|
|
5115
|
-
this.#handleFileInput.bind(this)
|
|
5116
|
-
);
|
|
5117
|
-
this.fileInput.addEventListener(
|
|
5118
|
-
"change",
|
|
5119
|
-
this.#handleFileInput.bind(this)
|
|
5120
|
-
);
|
|
5123
|
+
this.fileInput?.removeEventListener("change", this.#boundHandleFileInput);
|
|
5124
|
+
this.fileInput?.addEventListener("change", this.#boundHandleFileInput);
|
|
5121
5125
|
}
|
|
5122
5126
|
if (this.download) {
|
|
5123
5127
|
this.downloadButton = this.querySelector("fig-button[type='download']");
|
|
5124
|
-
this.downloadButton
|
|
5125
|
-
|
|
5126
|
-
this.#handleDownload.bind(this)
|
|
5127
|
-
);
|
|
5128
|
-
this.downloadButton.addEventListener(
|
|
5129
|
-
"click",
|
|
5130
|
-
this.#handleDownload.bind(this)
|
|
5131
|
-
);
|
|
5128
|
+
this.downloadButton?.removeEventListener("click", this.#boundHandleDownload);
|
|
5129
|
+
this.downloadButton?.addEventListener("click", this.#boundHandleDownload);
|
|
5132
5130
|
}
|
|
5133
5131
|
});
|
|
5134
5132
|
}
|
package/index.html
CHANGED
|
@@ -1577,7 +1577,8 @@
|
|
|
1577
1577
|
</fig-field>
|
|
1578
1578
|
<fig-field direction="horizontal">
|
|
1579
1579
|
<label>Dropdown</label>
|
|
1580
|
-
<fig-dropdown full
|
|
1580
|
+
<fig-dropdown full
|
|
1581
|
+
experimental="modern">
|
|
1581
1582
|
<option>Option One</option>
|
|
1582
1583
|
<option>Option Two</option>
|
|
1583
1584
|
<option>Option Three</option>
|
|
@@ -3272,6 +3273,26 @@
|
|
|
3272
3273
|
...
|
|
3273
3274
|
</dialog></code></pre>
|
|
3274
3275
|
|
|
3276
|
+
<h3>Viewport Margin</h3>
|
|
3277
|
+
<p class="description">Use <code>viewport-margin</code> to define safe areas the popup should avoid (e.g. a bottom toolbar). Uses CSS margin shorthand: <code>top right bottom left</code>.</p>
|
|
3278
|
+
<fig-button id="popup-open-viewport-margin"
|
|
3279
|
+
onclick="document.getElementById('popup-viewport-margin').open = true">Open (64px bottom margin)</fig-button>
|
|
3280
|
+
<dialog id="popup-viewport-margin"
|
|
3281
|
+
is="fig-popup"
|
|
3282
|
+
anchor="#popup-open-viewport-margin"
|
|
3283
|
+
position="bottom center"
|
|
3284
|
+
offset="8"
|
|
3285
|
+
viewport-margin="8 8 64 8">
|
|
3286
|
+
<vstack style="min-width: 14rem;">
|
|
3287
|
+
<strong style="padding: 0 var(--spacer-1);">Viewport Margin</strong>
|
|
3288
|
+
<p style="padding: 0 var(--spacer-1); margin: 0; font-size: var(--font-size-small); color: var(--figma-color-text-secondary);">This popup won't overlap the bottom 64px of the viewport.</p>
|
|
3289
|
+
<fig-input-text placeholder="Try scrolling down"></fig-input-text>
|
|
3290
|
+
</vstack>
|
|
3291
|
+
</dialog>
|
|
3292
|
+
<pre><code><dialog is="fig-popup" viewport-margin="8 8 64 8" position="bottom center" ...>
|
|
3293
|
+
...
|
|
3294
|
+
</dialog></code></pre>
|
|
3295
|
+
|
|
3275
3296
|
</section>
|
|
3276
3297
|
<hr>
|
|
3277
3298
|
|
package/package.json
CHANGED
package/dist/fig.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
function U(){return Date.now().toString(36)+Math.random().toString(36).substring(2)}if(window.customElements&&!window.customElements.get("fig-button")){class j extends HTMLElement{type;#j;constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){this.type=this.getAttribute("type")||"button",this.shadowRoot.innerHTML=`
|
|
2
|
-
<style>
|
|
3
|
-
button, button:hover, button:active {
|
|
4
|
-
padding: 0 var(--spacer-2);
|
|
5
|
-
appearance: none;
|
|
6
|
-
display: flex;
|
|
7
|
-
border: 0;
|
|
8
|
-
flex: 1;
|
|
9
|
-
text-align: center;
|
|
10
|
-
align-items: stretch;
|
|
11
|
-
justify-content: center;
|
|
12
|
-
font: inherit;
|
|
13
|
-
color: inherit;
|
|
14
|
-
outline: 0;
|
|
15
|
-
place-items: center;
|
|
16
|
-
background: transparent;
|
|
17
|
-
margin: calc(var(--spacer-2)*-1);
|
|
18
|
-
height: var(--spacer-4);
|
|
19
|
-
}
|
|
20
|
-
</style>
|
|
21
|
-
<button type="${this.type}">
|
|
22
|
-
<slot></slot>
|
|
23
|
-
</button>
|
|
24
|
-
`,this.#j=this.hasAttribute("selected")&&this.getAttribute("selected")!=="false",requestAnimationFrame(()=>{this.button=this.shadowRoot.querySelector("button"),this.button.addEventListener("click",this.#J.bind(this))})}get type(){return this.type}set type(K){this.setAttribute("type",K)}get selected(){return this.#j}set selected(K){this.setAttribute("selected",K)}#J(){if(this.type==="toggle")this.toggleAttribute("selected",!this.hasAttribute("selected"));if(this.type==="submit")this.closest("form").dispatchEvent(new Event("submit"))}static get observedAttributes(){return["disabled","selected"]}attributeChangedCallback(K,J,Q){if(this.button)switch(this.button[K]=Q,K){case"disabled":this.disabled=this.button.disabled=Q==="true"||Q===void 0&&Q!==null;break;case"type":this.type=Q,this.button.type=this.type,this.button.setAttribute("type",this.type);break;case"selected":this.#j=Q==="true";break}}}window.customElements.define("fig-button",j)}if(window.customElements&&!window.customElements.get("fig-dropdown")){class j extends HTMLElement{constructor(){super();this.select=document.createElement("select"),this.optionsSlot=document.createElement("slot"),this.attachShadow({mode:"open"})}#j(){this.select.addEventListener("input",this.#J.bind(this)),this.select.addEventListener("change",this.#K.bind(this))}connectedCallback(){this.type=this.getAttribute("type")||"select",this.appendChild(this.select),this.shadowRoot.appendChild(this.optionsSlot),this.optionsSlot.addEventListener("slotchange",this.slotChange.bind(this)),this.#j()}slotChange(){while(this.select.firstChild)this.select.firstChild.remove();if(this.type==="dropdown"){const K=document.createElement("option");K.setAttribute("hidden","true"),K.setAttribute("selected","true"),this.select.appendChild(K)}if(this.optionsSlot.assignedNodes().forEach((K)=>{if(K.nodeName==="OPTION"||K.nodeName==="OPTGROUP")this.select.appendChild(K.cloneNode(!0))}),this.#Q(this.value),this.type==="dropdown")this.select.selectedIndex=-1}#J(K){this.value=K.target.value,this.setAttribute("value",this.value)}#K(){if(this.type==="dropdown")this.select.selectedIndex=-1}focus(){this.select.focus()}blur(){this.select.blur()}get value(){return this.select?.value}set value(K){this.setAttribute("value",K)}static get observedAttributes(){return["value","type"]}#Q(K){if(this.select)this.select.querySelectorAll("option").forEach((J,Q)=>{if(J.value===this.getAttribute("value"))this.select.selectedIndex=Q})}attributeChangedCallback(K,J,Q){if(K==="value")this.#Q(Q);if(K==="type")this.type=Q}}customElements.define("fig-dropdown",j)}class P extends HTMLElement{constructor(){super();this.action=this.getAttribute("action")||"hover",this.delay=parseInt(this.getAttribute("delay"))||500,this.isOpen=!1}connectedCallback(){this.setup(),this.setupEventListeners()}disconnectedCallback(){this.destroy()}setup(){this.style.display="contents"}render(){this.destroy(),this.popup=document.createElement("span"),this.popup.setAttribute("class","fig-tooltip"),this.popup.style.position="fixed",this.popup.style.visibility="hidden",this.popup.style.display="inline-flex",this.popup.style.pointerEvents="none",this.popup.innerText=this.getAttribute("text"),document.body.append(this.popup)}destroy(){if(this.popup)this.popup.remove();document.body.addEventListener("click",this.hidePopupOutsideClick)}setupEventListeners(){if(this.action==="hover")this.addEventListener("pointerenter",this.showDelayedPopup.bind(this)),this.addEventListener("pointerleave",this.hidePopup.bind(this));else if(this.action==="click")this.addEventListener("click",this.showDelayedPopup.bind(this)),document.body.addEventListener("click",this.hidePopupOutsideClick.bind(this))}getOffset(){const j={left:8,top:4,right:8,bottom:4},K=this.getAttribute("offset");if(!K)return j;const[J,Q,X,W]=K.split(",").map(Number);return{left:isNaN(J)?j.left:J,top:isNaN(Q)?j.top:Q,right:isNaN(X)?j.right:X,bottom:isNaN(W)?j.bottom:W}}showDelayedPopup(){this.render(),clearTimeout(this.timeout),this.timeout=setTimeout(this.showPopup.bind(this),this.delay)}showPopup(){const j=this.firstElementChild.getBoundingClientRect(),K=this.popup.getBoundingClientRect(),J=this.getOffset();let Q=j.top-K.height-J.top,X=j.left+(j.width-K.width)/2;if(this.popup.setAttribute("position","top"),Q<0)this.popup.setAttribute("position","bottom"),Q=j.bottom+J.bottom;if(X<J.left)X=J.left;else if(X+K.width>window.innerWidth-J.right)X=window.innerWidth-K.width-J.right;this.popup.style.top=`${Q}px`,this.popup.style.left=`${X}px`,this.popup.style.opacity="1",this.popup.style.visibility="visible",this.popup.style.display="block",this.popup.style.pointerEvents="all",this.popup.style.zIndex=parseInt(new Date().getTime()/1000),this.isOpen=!0}hidePopup(){clearTimeout(this.timeout),this.popup.style.opacity="0",this.popup.style.display="block",this.popup.style.pointerEvents="none",this.destroy(),this.isOpen=!1}hidePopupOutsideClick(j){if(this.isOpen&&!this.popup.contains(j.target))this.hidePopup()}}customElements.define("fig-tooltip",P);class y extends P{static observedAttributes=["action","size"];constructor(){super();this.action=this.getAttribute("action")||"click",this.delay=parseInt(this.getAttribute("delay"))||0}render(){this.popup=this.popup||this.querySelector("[popover]"),this.popup.setAttribute("class","fig-popover"),this.popup.style.position="fixed",this.popup.style.display="block",this.popup.style.pointerEvents="none",document.body.append(this.popup)}destroy(){}}customElements.define("fig-popover",y);class L extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"}),this.dialog=document.createElement("dialog"),this.contentSlot=document.createElement("slot")}connectedCallback(){this.modal=this.hasAttribute("modal")&&this.getAttribute("modal")!=="false",this.appendChild(this.dialog),this.shadowRoot.appendChild(this.contentSlot),this.contentSlot.addEventListener("slotchange",this.slotChange.bind(this)),requestAnimationFrame(()=>{this.#j()})}#j(){this.dialog.querySelectorAll("fig-button[close-dialog]").forEach((j)=>{j.removeEventListener("click",this.close),j.addEventListener("click",this.close.bind(this))})}disconnectedCallback(){this.contentSlot.removeEventListener("slotchange",this.slotChange)}slotChange(){while(this.dialog.firstChild)this.dialog.firstChild.remove();this.contentSlot.assignedNodes().forEach((j)=>{if(j!==this.dialog)this.dialog.appendChild(j.cloneNode(!0))}),this.#j()}static get observedAttributes(){return["open","modal"]}attributeChangedCallback(j,K,J){switch(j){case"open":if(this.open=J==="true"&&J!=="false",this?.show)this[this.open?"show":"close"]();break;case"modal":this.modal=J==="true"&&J!=="false";break}}show(){if(this.modal)this.dialog.showModal();else this.dialog.show()}close(){this.dialog.close()}}customElements.define("fig-dialog",L);class k extends HTMLElement{#j;#J;#K;#Q;#W;#X;constructor(){super()}connectedCallback(){if(this.#j=this.querySelector("[popover]"),this.#J=this,this.#Q=Number(this.getAttribute("delay"))||0,this.#X=this.getAttribute("trigger-action")||"click",this.#K=`tooltip-${U()}`,this.#j){if(this.#j.setAttribute("id",this.#K),this.#j.setAttribute("role","tooltip"),this.#j.setAttribute("popover","manual"),this.#j.style["position-anchor"]=`--${this.#K}`,this.#J.setAttribute("popovertarget",this.#K),this.#J.setAttribute("popovertargetaction","toggle"),this.#J.style["anchor-name"]=`--${this.#K}`,this.#X==="hover")this.#J.addEventListener("mouseover",this.handleOpen.bind(this)),this.#J.addEventListener("mouseout",this.handleClose.bind(this));else this.#J.addEventListener("click",this.handleToggle.bind(this));document.body.append(this.#j)}}handleClose(){clearTimeout(this.#W),this.#j.hidePopover()}handleToggle(){if(this.#j.matches(":popover-open"))this.handleClose();else this.handleOpen()}handleOpen(){clearTimeout(this.#W),this.#W=setTimeout(()=>{this.#j.showPopover()},this.#Q)}}window.customElements.define("fig-popover-2",k);class A extends HTMLElement{constructor(){super()}connectedCallback(){this.setAttribute("label",this.innerText),this.addEventListener("click",this.handleClick.bind(this))}disconnectedCallback(){this.removeEventListener("click",this.handleClick)}handleClick(){this.setAttribute("selected","true")}}window.customElements.define("fig-tab",A);class O extends HTMLElement{constructor(){super()}connectedCallback(){this.name=this.getAttribute("name")||"tabs",this.addEventListener("click",this.handleClick.bind(this))}disconnectedCallback(){this.removeEventListener("click",this.handleClick)}handleClick(j){const K=j.target;if(K.nodeName.toLowerCase()==="fig-tab"){const J=this.querySelectorAll("fig-tab");for(let Q of J)if(Q===K)this.selectedTab=Q;else Q.removeAttribute("selected")}}}window.customElements.define("fig-tabs",O);class B extends HTMLElement{#j;#J;constructor(){super()}connectedCallback(){this.addEventListener("click",this.handleClick.bind(this))}disconnectedCallback(){this.removeEventListener("click",this.handleClick)}handleClick(){this.setAttribute("selected","true")}get value(){return this.#j}set value(j){this.#j=j,this.setAttribute("value",j)}get selected(){return this.#J}set selected(j){this.#J=j,this.setAttribute("selected",j)}static get observedAttributes(){return["selected","value"]}attributeChangedCallback(j,K,J){switch(j){case"value":this.#j=J;break;case"selected":this.#J=J;break}}}window.customElements.define("fig-segment",B);class R extends HTMLElement{constructor(){super()}connectedCallback(){this.name=this.getAttribute("name")||"segmented-control",this.addEventListener("click",this.handleClick.bind(this))}handleClick(j){const K=j.target;if(K.nodeName.toLowerCase()==="fig-segment"){const J=this.querySelectorAll("fig-segment");for(let Q of J)if(Q===K)this.selectedSegment=Q;else Q.removeAttribute("selected")}}}window.customElements.define("fig-segmented-control",R);class N extends HTMLElement{#j={range:{min:0,max:100,step:1},hue:{min:0,max:255,step:1},delta:{min:-100,max:100,step:1},stepper:{min:0,max:100,step:25},opacity:{min:0,max:100,step:0.1,color:"#FF0000"}};constructor(){super()}#J(){this.value=Number(this.getAttribute("value")||0),this.default=this.getAttribute("default")||null,this.type=this.getAttribute("type")||"range",this.text=this.getAttribute("text")||!1,this.units=this.getAttribute("units")||"",this.transform=Number(this.getAttribute("transform")||1),this.disabled=this.getAttribute("disabled")?!0:!1;const j=this.#j[this.type];if(this.min=Number(this.getAttribute("min")||j.min),this.max=Number(this.getAttribute("max")||j.max),this.step=Number(this.getAttribute("step")||j.step),this.color=this.getAttribute("color")||j?.color,this.color)this.style.setProperty("--color",this.color);let K="",J=`<div class="fig-slider-input-container">
|
|
25
|
-
<input
|
|
26
|
-
type="range"
|
|
27
|
-
${this.disabled?"disabled":""}
|
|
28
|
-
min="${this.min}"
|
|
29
|
-
max="${this.max}"
|
|
30
|
-
step="${this.step}"
|
|
31
|
-
class="${this.type}"
|
|
32
|
-
value="${this.value}">
|
|
33
|
-
${this.initialInnerHTML}
|
|
34
|
-
</div>`;if(this.text)K=`${J}
|
|
35
|
-
<fig-input-text
|
|
36
|
-
placeholder="##"
|
|
37
|
-
type="number"
|
|
38
|
-
min="${this.min}"
|
|
39
|
-
max="${this.max}"
|
|
40
|
-
transform="${this.transform}"
|
|
41
|
-
step="${this.step}"
|
|
42
|
-
value="${this.value}">
|
|
43
|
-
${this.units?`<span slot="append">${this.units}</span>`:""}
|
|
44
|
-
</fig-input-text>`;else K=J;this.innerHTML=K,requestAnimationFrame(()=>{if(this.input=this.querySelector("[type=range]"),this.input.removeEventListener("input",this.handleInput),this.input.addEventListener("input",this.handleInput.bind(this)),this.default)this.style.setProperty("--default",this.#K(this.default));if(this.datalist=this.querySelector("datalist"),this.figInputText=this.querySelector("fig-input-text"),this.datalist)this.datalist.setAttribute("id",this.datalist.getAttribute("id")||U()),this.input.setAttribute("list",this.datalist.getAttribute("id"));if(this.figInputText)this.figInputText.removeEventListener("input",this.handleTextInput),this.figInputText.addEventListener("input",this.handleTextInput.bind(this));this.handleInput()})}connectedCallback(){this.initialInnerHTML=this.innerHTML,this.#J()}static get observedAttributes(){return["value","step","min","max","type","disabled","color","units","transform"]}focus(){this.input.focus()}attributeChangedCallback(j,K,J){if(this.input)switch(j){case"color":this.color=J,this.style.setProperty("--color",this.color);break;case"disabled":if(this.disabled=this.input.disabled=J==="true"||J===void 0&&J!==null,this.figInputText)this.figInputText.disabled=this.disabled,this.figInputText.setAttribute("disabled",this.disabled);break;case"value":if(this.value=J,this.figInputText)this.figInputText.setAttribute("value",J);break;case"transform":if(this.transform=Number(J)||1,this.figInputText)this.figInputText.setAttribute("transform",this.transform);break;case"min":case"max":case"step":case"type":case"text":case"units":this[j]=J,this.#J();break;default:this[j]=this.input[j]=J,this.handleInput();break}}handleTextInput(){if(this.figInputText)this.value=this.input.value=this.figInputText.value,this.#Q()}#K(j){let K=Number(this.input.min),J=Number(this.input.max);return(j-K)/(J-K)}#Q(){let j=this.#K(this.value),K=this.#K(this.default);this.style.setProperty("--slider-complete",j),this.style.setProperty("--default",K),this.style.setProperty("--unchanged",j===K?1:0)}handleInput(){let j=this.input.value;if(this.value=j,this.#Q(),this.figInputText)this.figInputText.setAttribute("value",j)}}window.customElements.define("fig-slider",N);class q extends HTMLElement{constructor(){super()}connectedCallback(){if(this.multiline=this.hasAttribute("multiline")||!1,this.value=this.getAttribute("value")||"",this.type=this.getAttribute("type")||"text",this.type==="number"){if(this.getAttribute("step"))this.step=Number(this.getAttribute("step"));if(this.getAttribute("min"))this.min=Number(this.getAttribute("min"));if(this.getAttribute("max"))this.max=Number(this.getAttribute("max"));if(this.transform=Number(this.getAttribute("transform")||1),this.getAttribute("value"))this.value=Number(this.value)}this.placeholder=this.getAttribute("placeholder")||"";let j=`<input
|
|
45
|
-
type="${this.type}"
|
|
46
|
-
placeholder="${this.placeholder}"
|
|
47
|
-
value="${this.type==="number"?this.#j(this.value):this.value}" />`;if(this.multiline)j=`<textarea
|
|
48
|
-
placeholder="${this.placeholder}">${this.value}</textarea>`;requestAnimationFrame(()=>{const K=this.querySelector("[slot=append]"),J=this.querySelector("[slot=prepend]");if(this.innerHTML=j,J)J.addEventListener("click",this.focus.bind(this)),this.prepend(J);if(K)K.addEventListener("click",this.focus.bind(this)),this.append(K);if(this.input=this.querySelector("input,textarea"),this.type==="number"){if(this.getAttribute("min"))this.input.setAttribute("min",this.#j(this.min));if(this.getAttribute("max"))this.input.setAttribute("max",this.#j(this.max));if(this.getAttribute("step"))this.input.setAttribute("step",this.#j(this.step))}this.input.addEventListener("input",this.#J.bind(this))})}focus(){this.input.focus()}#j(j){return j*(this.transform||1)}#J(j){let K=j.target.value;if(this.type==="number")this.value=K/(this.transform||1);else this.value=K}static get observedAttributes(){return["value","placeholder","label","disabled","type","step","min","max","transform"]}attributeChangedCallback(j,K,J){if(this.input)switch(j){case"disabled":this.disabled=this.input.disabled=J;break;case"transform":if(this.type==="number")this.transform=Number(J)||1,this.min=this.#j(this.min),this.max=this.#j(this.max),this.step=this.#j(this.step),this.value=this.#j(this.value);break;default:let Q=J;if(this.type==="number")Q=this.#j(Q);if(this[j]=this.input[j]=Q,this.input)this.input.setAttribute(j,Q);break}}}window.customElements.define("fig-input-text",q);class T extends HTMLElement{constructor(){super()}connectedCallback(){this.src=this.getAttribute("src"),this.name=this.getAttribute("name"),this.initials=this.getInitials(this.name),this.setAttribute("initials",this.initials),this.setSrc(this.src),requestAnimationFrame(()=>{this.img=this.querySelector("img")})}setSrc(j){if(this.src=j,j)this.innerHTML=`<img src="${this.src}" ${this.name?`alt="${this.name}"`:""} />`}getInitials(j){return j?j.split(" ").map((K)=>K[0]).join(""):""}static get observedAttributes(){return["src","href","name"]}attributeChangedCallback(j,K,J){if(this[j]=J,j==="name")this.img?.setAttribute("alt",J),this.name=J,this.initials=this.getInitials(this.name),this.setAttribute("initials",this.initials);else if(j==="src")this.src=J,this.setSrc(this.src)}}window.customElements.define("fig-avatar",T);class S extends HTMLElement{constructor(){super()}connectedCallback(){requestAnimationFrame(()=>{if(this.label=this.querySelector("label"),this.input=Array.from(this.childNodes).find((j)=>j.nodeName.toLowerCase().startsWith("fig-")),this.input&&this.label){this.label.addEventListener("click",this.focus.bind(this));let j=this.input.getAttribute("id")||U();this.input.setAttribute("id",j),this.label.setAttribute("for",j)}})}focus(){this.input.focus()}}window.customElements.define("fig-field",S);class C extends HTMLElement{#j;#J;textInput;#K;constructor(){super()}connectedCallback(){this.#j=this.convertToRGBA(this.getAttribute("value"));const j=(this.#j.a*100).toFixed(0);this.value=this.rgbAlphaToHex({r:this.#j.r,g:this.#j.g,b:this.#j.b},j);let K="";if(this.getAttribute("text")){let J=`<fig-input-text placeholder="Text" value="${this.getAttribute("value")}"></fig-input-text>`;if(this.getAttribute("alpha")==="true")J+=`<fig-tooltip text="Opacity">
|
|
49
|
-
<fig-input-text
|
|
50
|
-
placeholder="##"
|
|
51
|
-
type="number"
|
|
52
|
-
min="0"
|
|
53
|
-
max="100"
|
|
54
|
-
value="${j}">
|
|
55
|
-
<span slot="append">%</slot>
|
|
56
|
-
</fig-input-text>
|
|
57
|
-
</fig-tooltip>`;K=`<div class="input-combo">
|
|
58
|
-
<fig-chit type="color" disabled="false" value="${this.value}"></fig-chit>
|
|
59
|
-
${J}
|
|
60
|
-
</div>`}else K=`<fig-chit type="color" disabled="false" value="${this.value}"></fig-chit>`;this.innerHTML=K,this.style.setProperty("--alpha",this.#j.a),requestAnimationFrame(()=>{if(this.#J=this.querySelector("input[type=color]"),this.textInput=this.querySelector("input[type=text]"),this.#K=this.querySelector("input[type=number]"),this.#J.disabled=this.hasAttribute("disabled"),this.#J.addEventListener("input",this.handleInput.bind(this)),this.textInput)this.textInput.value=this.#J.value=this.rgbAlphaToHex(this.#j,1);if(this.#K)this.#K.addEventListener("input",this.handleAlphaInput.bind(this))})}handleAlphaInput(j){j.stopPropagation(),this.#j=this.convertToRGBA(this.#J.value),this.#j.a=Number(this.#K.value)/100,this.value=this.rgbAlphaToHex({r:this.#j.r,g:this.#j.g,b:this.#j.b},this.#j.a),this.style.setProperty("--alpha",this.#j.a);const K=new CustomEvent("input",{bubbles:!0,cancelable:!0});this.dispatchEvent(K)}focus(){this.#J.focus()}handleInput(j){j.stopPropagation();let K=this.#j.a;if(this.#j=this.convertToRGBA(this.#J.value),this.#j.a=K,this.textInput)this.textInput.value=this.#J.value;if(this.style.setProperty("--alpha",this.#j.a),this.value=this.rgbAlphaToHex({r:this.#j.r,g:this.#j.g,b:this.#j.b},K),this.alpha=K,this.#K)this.#K.value=this.#j.a.toFixed(0);const J=new CustomEvent("input",{bubbles:!0,cancelable:!0});this.dispatchEvent(J)}static get observedAttributes(){return["value","style"]}attributeChangedCallback(j,K,J){}rgbAlphaToHex({r:j,g:K,b:J},Q=1){j=Math.max(0,Math.min(255,Math.round(j))),K=Math.max(0,Math.min(255,Math.round(K))),J=Math.max(0,Math.min(255,Math.round(J))),Q=Math.max(0,Math.min(1,Q));const X=j.toString(16).padStart(2,"0"),W=K.toString(16).padStart(2,"0"),_=J.toString(16).padStart(2,"0");if(Q===1)return`#${X}${W}${_}`;const Z=Math.round(Q*255).toString(16).padStart(2,"0");return`#${X}${W}${_}${Z}`}convertToRGBA(j){let K,J,Q,X=1;if(j.startsWith("#")){let W=j.slice(1);if(W.length===8)X=parseInt(W.slice(6),16)/255,W=W.slice(0,6);K=parseInt(W.slice(0,2),16),J=parseInt(W.slice(2,4),16),Q=parseInt(W.slice(4,6),16)}else if(j.startsWith("rgba")||j.startsWith("rgb")){let W=j.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)/);if(W)K=parseInt(W[1]),J=parseInt(W[2]),Q=parseInt(W[3]),X=W[4]?parseFloat(W[4]):1}else if(j.startsWith("hsla")||j.startsWith("hsl")){let W=j.match(/hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*(\d+(?:\.\d+)?))?\)/);if(W){let _=parseInt(W[1])/360,$=parseInt(W[2])/100,Z=parseInt(W[3])/100;if(X=W[4]?parseFloat(W[4]):1,$===0)K=J=Q=Z;else{let H=(z,D,Y)=>{if(Y<0)Y+=1;if(Y>1)Y-=1;if(Y<0.16666666666666666)return z+(D-z)*6*Y;if(Y<0.5)return D;if(Y<0.6666666666666666)return z+(D-z)*(0.6666666666666666-Y)*6;return z},E=Z<0.5?Z*(1+$):Z+$-Z*$,M=2*Z-E;K=H(M,E,_+0.3333333333333333),J=H(M,E,_),Q=H(M,E,_-0.3333333333333333)}K=Math.round(K*255),J=Math.round(J*255),Q=Math.round(Q*255)}}else return null;return{r:K,g:J,b:Q,a:X}}}window.customElements.define("fig-input-color",C);class G extends HTMLElement{constructor(){super();this.input=document.createElement("input"),this.name=this.getAttribute("name")||"checkbox",this.value=this.getAttribute("value")||"",this.input.setAttribute("id",U()),this.input.setAttribute("name",this.name),this.input.setAttribute("type","checkbox"),this.labelElement=document.createElement("label"),this.labelElement.setAttribute("for",this.input.id)}connectedCallback(){if(this.checked=this.input.checked=this.hasAttribute("checked")&&this.getAttribute("checked")!=="false",this.input.addEventListener("change",this.handleInput.bind(this)),this.hasAttribute("disabled"))this.input.disabled=!0;if(this.hasAttribute("indeterminate"))this.input.indeterminate=!0,this.input.setAttribute("indeterminate","true");this.append(this.input),this.append(this.labelElement),this.render()}static get observedAttributes(){return["disabled","label","checked","name","value"]}render(){}focus(){this.input.focus()}disconnectedCallback(){this.input.remove()}attributeChangedCallback(j,K,J){switch(j){case"label":this.labelElement.innerText=J;break;case"checked":this.checked=this.input.checked=this.hasAttribute("checked")&&this.getAttribute("checked")!=="false";break;default:this.input[j]=J,this.input.setAttribute(j,J);break}}handleInput(j){this.input.indeterminate=!1,this.input.removeAttribute("indeterminate"),this.value=this.input.value}}window.customElements.define("fig-checkbox",G);class x extends G{constructor(){super();this.input.setAttribute("type","radio"),this.input.setAttribute("name",this.getAttribute("name")||"radio")}}window.customElements.define("fig-radio",x);class I extends G{render(){this.input.setAttribute("class","switch")}}window.customElements.define("fig-switch",I);class v extends HTMLElement{constructor(){super()}}window.customElements.define("fig-bell",v);class F extends HTMLElement{constructor(){super()}}window.customElements.define("fig-badge",F);class f extends HTMLElement{constructor(){super()}}window.customElements.define("fig-accordion",f);class b extends HTMLElement{constructor(){super()}getOptionsFromAttribute(){return(this.getAttribute("options")||"").split(",")}connectedCallback(){this.options=this.getOptionsFromAttribute(),this.placeholder=this.getAttribute("placeholder")||"",this.value=this.getAttribute("value")||"",this.innerHTML=`<div class="input-combo">
|
|
61
|
-
<fig-input-text placeholder="${this.placeholder}">
|
|
62
|
-
</fig-input-text>
|
|
63
|
-
<fig-button type="select" variant="input" icon>
|
|
64
|
-
<svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
|
65
|
-
<path d='M5.87868 7.12132L8 9.24264L10.1213 7.12132' stroke='currentColor' stroke-opacity="0.9" stroke-linecap='round'/>
|
|
66
|
-
</svg>
|
|
67
|
-
<fig-dropdown type="dropdown">
|
|
68
|
-
${this.options.map((j)=>`<option>${j}</option>`).join("")}
|
|
69
|
-
</fig-dropdown>
|
|
70
|
-
</fig-button>
|
|
71
|
-
</div>`,requestAnimationFrame(()=>{this.input=this.querySelector("fig-input-text"),this.select=this.querySelector("fig-dropdown"),this.select.addEventListener("input",this.handleSelectInput.bind(this))})}handleSelectInput(j){this.value=j.target.parentNode.value,this.setAttribute("value",this.value)}handleInput(j){this.value=this.input.value}static get observedAttributes(){return["options","placeholder","value"]}attributeChangedCallback(j,K,J){if(j==="options"){if(this.options=J.split(","),this.dropdown)this.dropdown.innerHTML=this.options.map((Q)=>`<option>${Q}</option>`).join("")}if(j==="placeholder")this.placeholder=J;if(j==="value")this.value=J,this.input.setAttribute("value",J)}}window.customElements.define("fig-combo-input",b);class h extends HTMLElement{constructor(){super()}connectedCallback(){this.type=this.getAttribute("type")||"color",this.src=this.getAttribute("src")||"",this.value=this.getAttribute("value")||"",this.size=this.getAttribute("size")||"small",this.disabled=this.getAttribute("disabled")==="true"?!0:!1,this.innerHTML=`<input type="color" value="${this.value}" />`,this.#j(this.src),requestAnimationFrame(()=>{this.input=this.querySelector("input")})}#j(j){if(j)this.src=j,this.style.setProperty("--src",`url(${j})`);else this.style.removeProperty("--src")}static get observedAttributes(){return["src","value","disabled"]}attributeChangedCallback(j,K,J){switch(j){case"src":this.#j(J);break;case"disabled":this.disabled=J.toLowerCase()==="true";break;default:if(this.input)this.input[j]=J;this.#j(this.src);break}}}window.customElements.define("fig-chit",h);class d extends HTMLElement{constructor(){super()}#j(){return`<fig-chit type="image" size="large" ${this.src?`src="${this.src}"`:""} disabled="true"></fig-chit>${this.upload?`<fig-button variant="primary" type="upload">
|
|
72
|
-
${this.label}
|
|
73
|
-
<input type="file" accept="image/*" />
|
|
74
|
-
</fig-button>`:""}`}connectedCallback(){this.src=this.getAttribute("src")||"",this.upload=this.getAttribute("upload")==="true",this.label=this.getAttribute("label")||"Upload",this.size=this.getAttribute("size")||"small",this.innerHTML=this.#j(),this.#J()}#J(){requestAnimationFrame(()=>{if(this.chit=this.querySelector("fig-chit"),this.upload)this.uploadButton=this.querySelector("fig-button"),this.fileInput=this.uploadButton?.querySelector("input"),this.fileInput.addEventListener("change",this.handleFileInput.bind(this))})}handleFileInput(j){this.src=URL.createObjectURL(j.target.files[0]),this.setAttribute("src",this.src),this.chit.setAttribute("src",this.src)}static get observedAttributes(){return["src","upload"]}attributeChangedCallback(j,K,J){if(j==="src"){if(this.src=J,this.chit)this.chit.setAttribute("src",this.src)}if(j==="upload")this.upload=J.toLowerCase()==="true",this.innerHTML=this.#j(),this.#J();if(j==="size")this.size=J}}window.customElements.define("fig-image",d);
|