@rogieking/figui3 4.13.1 → 4.15.1
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/.cursor/skills/figui3/SKILL.md +1 -1
- package/README.md +24 -2
- package/components.css +91 -71
- package/dist/components.css +1 -1
- package/dist/fig.css +1 -1
- package/dist/fig.js +75 -75
- package/fig.js +117 -44
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -16,6 +16,15 @@ function figIsWebKitOrIOSBrowser() {
|
|
|
16
16
|
return isIOSBrowser || isDesktopWebKit;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/** @param {string} name @param {{ size?: string, className?: string }} [options] */
|
|
20
|
+
function createFigIcon(name, options = {}) {
|
|
21
|
+
const icon = document.createElement("fig-icon");
|
|
22
|
+
if (name) icon.setAttribute("name", name);
|
|
23
|
+
if (options.size) icon.setAttribute("size", options.size);
|
|
24
|
+
if (options.className) icon.className = options.className;
|
|
25
|
+
return icon;
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
function figSupportsCustomizedBuiltIns() {
|
|
20
29
|
if (
|
|
21
30
|
typeof window === "undefined" ||
|
|
@@ -1234,10 +1243,7 @@ class FigDialog extends HTMLDialogElement {
|
|
|
1234
1243
|
btn.setAttribute("variant", "ghost");
|
|
1235
1244
|
btn.setAttribute("icon", "");
|
|
1236
1245
|
btn.setAttribute("close-dialog", "");
|
|
1237
|
-
|
|
1238
|
-
icon.className = "fig-mask-icon";
|
|
1239
|
-
icon.style.setProperty("--icon", "var(--icon-close)");
|
|
1240
|
-
btn.appendChild(icon);
|
|
1246
|
+
btn.appendChild(createFigIcon("close"));
|
|
1241
1247
|
tooltip.appendChild(btn);
|
|
1242
1248
|
header.appendChild(h3);
|
|
1243
1249
|
header.appendChild(tooltip);
|
|
@@ -4907,8 +4913,10 @@ class FigField extends HTMLElement {
|
|
|
4907
4913
|
this.#toggleable = !!(this.input && "open" in this.input);
|
|
4908
4914
|
|
|
4909
4915
|
if (this.#toggleable && this.label) {
|
|
4910
|
-
this.#chevron =
|
|
4911
|
-
|
|
4916
|
+
this.#chevron = createFigIcon("chevron", {
|
|
4917
|
+
size: "small",
|
|
4918
|
+
className: "fig-field-chevron",
|
|
4919
|
+
});
|
|
4912
4920
|
this.insertBefore(this.#chevron, this.label);
|
|
4913
4921
|
|
|
4914
4922
|
this.#boundToggle = (e) => {
|
|
@@ -6423,9 +6431,10 @@ customElements.define("fig-input-fill", FigInputFill);
|
|
|
6423
6431
|
/* Input Palette */
|
|
6424
6432
|
/**
|
|
6425
6433
|
* A palette of solid colors, each rendered as a fig-input-color swatch.
|
|
6426
|
-
* Manages an internal array of colors with add support.
|
|
6434
|
+
* Manages an internal array of colors with optional add/remove support.
|
|
6427
6435
|
* @attr {string} value - JSON array of hex strings or {color,alpha} objects, or comma-separated hex
|
|
6428
6436
|
* @attr {boolean} disabled - Whether the palette is disabled
|
|
6437
|
+
* @attr {boolean} fixed - When set (or `fixed="true"`), palette length is locked — no add or remove
|
|
6429
6438
|
* @attr {number} min - Minimum number of colors (default: 2)
|
|
6430
6439
|
* @attr {number} max - Maximum number of colors (default: 8); add button hidden at max
|
|
6431
6440
|
* @fires input - During color editing (detail: full color array)
|
|
@@ -6438,7 +6447,7 @@ class FigInputPalette extends HTMLElement {
|
|
|
6438
6447
|
#renderRAF = null;
|
|
6439
6448
|
|
|
6440
6449
|
static get observedAttributes() {
|
|
6441
|
-
return ["value", "disabled", "min", "max", "open", "
|
|
6450
|
+
return ["value", "disabled", "min", "max", "open", "fixed"];
|
|
6442
6451
|
}
|
|
6443
6452
|
|
|
6444
6453
|
get open() {
|
|
@@ -6462,8 +6471,10 @@ class FigInputPalette extends HTMLElement {
|
|
|
6462
6471
|
}
|
|
6463
6472
|
}
|
|
6464
6473
|
|
|
6465
|
-
get #
|
|
6466
|
-
return
|
|
6474
|
+
get #isFixed() {
|
|
6475
|
+
return (
|
|
6476
|
+
this.hasAttribute("fixed") && this.getAttribute("fixed") !== "false"
|
|
6477
|
+
);
|
|
6467
6478
|
}
|
|
6468
6479
|
|
|
6469
6480
|
get #min() {
|
|
@@ -6508,7 +6519,7 @@ class FigInputPalette extends HTMLElement {
|
|
|
6508
6519
|
break;
|
|
6509
6520
|
case "min":
|
|
6510
6521
|
case "max":
|
|
6511
|
-
case "
|
|
6522
|
+
case "fixed":
|
|
6512
6523
|
this.#render();
|
|
6513
6524
|
break;
|
|
6514
6525
|
case "open":
|
|
@@ -6618,13 +6629,15 @@ class FigInputPalette extends HTMLElement {
|
|
|
6618
6629
|
inlineWrap.appendChild(wrap);
|
|
6619
6630
|
this.appendChild(inlineWrap);
|
|
6620
6631
|
|
|
6621
|
-
if (this.#
|
|
6632
|
+
if (!this.#isFixed) this.#createAddButton(disabled, this);
|
|
6622
6633
|
|
|
6623
6634
|
const expandedWrap = document.createElement("div");
|
|
6624
6635
|
expandedWrap.className = "palette-colors-expanded";
|
|
6625
6636
|
this.#colors.forEach((entry, i) => {
|
|
6626
6637
|
expandedWrap.appendChild(this.#createPicker(entry, i, disabled));
|
|
6627
|
-
|
|
6638
|
+
if (!this.#isFixed) {
|
|
6639
|
+
expandedWrap.appendChild(this.#createRemoveButton(i, disabled));
|
|
6640
|
+
}
|
|
6628
6641
|
});
|
|
6629
6642
|
this.appendChild(expandedWrap);
|
|
6630
6643
|
}
|
|
@@ -6639,14 +6652,12 @@ class FigInputPalette extends HTMLElement {
|
|
|
6639
6652
|
: entry.color;
|
|
6640
6653
|
const ic = document.createElement("fig-input-color");
|
|
6641
6654
|
ic.setAttribute("value", hexAlpha);
|
|
6642
|
-
ic.setAttribute("picker", "figma");
|
|
6643
|
-
ic.setAttribute("picker-anchor", "self");
|
|
6644
6655
|
if (inline) {
|
|
6645
6656
|
ic.setAttribute("text", "false");
|
|
6646
6657
|
ic.setAttribute("alpha", "true");
|
|
6647
6658
|
} else {
|
|
6648
6659
|
ic.setAttribute("text", "true");
|
|
6649
|
-
ic.setAttribute("alpha", "false");
|
|
6660
|
+
ic.setAttribute("alpha", this.#isFixed ? "true" : "false");
|
|
6650
6661
|
ic.setAttribute("full", "");
|
|
6651
6662
|
}
|
|
6652
6663
|
if (disabled) ic.setAttribute("disabled", "");
|
|
@@ -6696,7 +6707,7 @@ class FigInputPalette extends HTMLElement {
|
|
|
6696
6707
|
btn.setAttribute("aria-label", "Remove color");
|
|
6697
6708
|
btn.className = "palette-remove-btn";
|
|
6698
6709
|
if (disabled || this.#colors.length <= this.#min) btn.setAttribute("disabled", "");
|
|
6699
|
-
btn.
|
|
6710
|
+
btn.appendChild(createFigIcon("minus"));
|
|
6700
6711
|
btn.addEventListener("click", () => {
|
|
6701
6712
|
if (this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false") return;
|
|
6702
6713
|
this.#removeColor(index);
|
|
@@ -6705,6 +6716,7 @@ class FigInputPalette extends HTMLElement {
|
|
|
6705
6716
|
}
|
|
6706
6717
|
|
|
6707
6718
|
#removeColor(index) {
|
|
6719
|
+
if (this.#isFixed) return;
|
|
6708
6720
|
if (index < 0 || index >= this.#colors.length) return;
|
|
6709
6721
|
if (this.#colors.length <= this.#min) return;
|
|
6710
6722
|
this.#colors.splice(index, 1);
|
|
@@ -6722,7 +6734,7 @@ class FigInputPalette extends HTMLElement {
|
|
|
6722
6734
|
addBtn.setAttribute("aria-label", "Add color");
|
|
6723
6735
|
addBtn.className = "palette-add-btn";
|
|
6724
6736
|
if (disabled || atMax) addBtn.setAttribute("disabled", "");
|
|
6725
|
-
addBtn.
|
|
6737
|
+
addBtn.appendChild(createFigIcon("add"));
|
|
6726
6738
|
addBtn.addEventListener("click", () => {
|
|
6727
6739
|
if (
|
|
6728
6740
|
this.hasAttribute("disabled") &&
|
|
@@ -6739,6 +6751,7 @@ class FigInputPalette extends HTMLElement {
|
|
|
6739
6751
|
}
|
|
6740
6752
|
|
|
6741
6753
|
#addColor(entry) {
|
|
6754
|
+
if (this.#isFixed) return;
|
|
6742
6755
|
this.#colors.push(entry);
|
|
6743
6756
|
const disabled =
|
|
6744
6757
|
this.hasAttribute("disabled") &&
|
|
@@ -9024,10 +9037,9 @@ class FigMediaControls extends HTMLElement {
|
|
|
9024
9037
|
btn.setAttribute("size", "small");
|
|
9025
9038
|
btn.setAttribute("icon", "true");
|
|
9026
9039
|
btn.setAttribute("aria-label", "Play");
|
|
9027
|
-
const icon =
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
icon.style.setProperty("--size", "1.5rem");
|
|
9040
|
+
const icon = createFigIcon("play", {
|
|
9041
|
+
className: "fig-media-controls-play-icon",
|
|
9042
|
+
});
|
|
9031
9043
|
btn.append(icon);
|
|
9032
9044
|
tooltip.append(btn);
|
|
9033
9045
|
btn.addEventListener("click", (e) => {
|
|
@@ -9090,10 +9102,7 @@ class FigMediaControls extends HTMLElement {
|
|
|
9090
9102
|
this.#playTooltip?.setAttribute("text", playing ? "Pause" : "Play");
|
|
9091
9103
|
const icon = this.#playBtn.querySelector(".fig-media-controls-play-icon");
|
|
9092
9104
|
if (icon) {
|
|
9093
|
-
icon.
|
|
9094
|
-
"--icon",
|
|
9095
|
-
playing ? "var(--icon-pause)" : "var(--icon-play)",
|
|
9096
|
-
);
|
|
9105
|
+
icon.setAttribute("name", playing ? "pause" : "play");
|
|
9097
9106
|
}
|
|
9098
9107
|
}
|
|
9099
9108
|
|
|
@@ -9338,7 +9347,7 @@ class FigInputFile extends HTMLElement {
|
|
|
9338
9347
|
this.#clearBtn.setAttribute("icon", "true");
|
|
9339
9348
|
this.#clearBtn.className = "fig-input-file-clear";
|
|
9340
9349
|
if (disabled) this.#clearBtn.setAttribute("disabled", "");
|
|
9341
|
-
this.#clearBtn.
|
|
9350
|
+
this.#clearBtn.replaceChildren(createFigIcon("minus"));
|
|
9342
9351
|
this.#clearBtn.addEventListener("click", this.#onClear);
|
|
9343
9352
|
clearTooltip.appendChild(this.#clearBtn);
|
|
9344
9353
|
this.appendChild(clearTooltip);
|
|
@@ -11194,7 +11203,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
11194
11203
|
</div>
|
|
11195
11204
|
<fig-tooltip text="Reset">
|
|
11196
11205
|
<fig-button variant="ghost" icon="true" class="fig-joystick-reset" aria-label="Reset to default">
|
|
11197
|
-
<
|
|
11206
|
+
<fig-icon name="reset" size="small"></fig-icon>
|
|
11198
11207
|
</fig-button>
|
|
11199
11208
|
</fig-tooltip>
|
|
11200
11209
|
</div>
|
|
@@ -11709,8 +11718,10 @@ class FigGroup extends HTMLElement {
|
|
|
11709
11718
|
|
|
11710
11719
|
if (isCollapsible) {
|
|
11711
11720
|
if (!h3.querySelector(".fig-group-chevron")) {
|
|
11712
|
-
const chevron =
|
|
11713
|
-
|
|
11721
|
+
const chevron = createFigIcon("chevron", {
|
|
11722
|
+
size: "small",
|
|
11723
|
+
className: "fig-group-chevron",
|
|
11724
|
+
});
|
|
11714
11725
|
h3.prepend(chevron);
|
|
11715
11726
|
}
|
|
11716
11727
|
this.#chevron = h3.querySelector(".fig-group-chevron");
|
|
@@ -11752,7 +11763,71 @@ customElements.define("fig-footer", FigFooter);
|
|
|
11752
11763
|
class FigSpinner extends HTMLElement {}
|
|
11753
11764
|
customElements.define("fig-spinner", FigSpinner);
|
|
11754
11765
|
|
|
11755
|
-
|
|
11766
|
+
/** @type {Record<string, string>} */
|
|
11767
|
+
const FIG_ICON_TOKENS = {
|
|
11768
|
+
chevron: "--icon-16-chevron",
|
|
11769
|
+
checkmark: "--icon-16-checkmark",
|
|
11770
|
+
reset: "--icon-16-reset",
|
|
11771
|
+
"arrow-left": "--icon-16-arrow-left",
|
|
11772
|
+
steppers: "--icon-24-steppers",
|
|
11773
|
+
eyedropper: "--icon-24-eyedropper",
|
|
11774
|
+
add: "--icon-24-add",
|
|
11775
|
+
minus: "--icon-24-minus",
|
|
11776
|
+
back: "--icon-24-back",
|
|
11777
|
+
forward: "--icon-24-forward",
|
|
11778
|
+
close: "--icon-24-close",
|
|
11779
|
+
rotate: "--icon-24-rotate",
|
|
11780
|
+
swap: "--icon-24-swap",
|
|
11781
|
+
play: "--icon-24-play",
|
|
11782
|
+
pause: "--icon-24-pause",
|
|
11783
|
+
};
|
|
11784
|
+
|
|
11785
|
+
function figIconCssVar(name) {
|
|
11786
|
+
const token = name && FIG_ICON_TOKENS[name];
|
|
11787
|
+
return token ? `var(${token})` : "";
|
|
11788
|
+
}
|
|
11789
|
+
|
|
11790
|
+
/**
|
|
11791
|
+
* Masked icon using design-token SVGs from :root.
|
|
11792
|
+
* @attr {string} name - Icon name (chevron, add, close, …)
|
|
11793
|
+
* @attr {'small'|'medium'} size - Display size; medium (default) uses --spacer-4, small uses --spacer-3
|
|
11794
|
+
* @attr {string} color - Icon fill color (applied as background-color for the mask)
|
|
11795
|
+
*/
|
|
11796
|
+
class FigIcon extends HTMLElement {
|
|
11797
|
+
static get observedAttributes() {
|
|
11798
|
+
return ["name", "size", "color"];
|
|
11799
|
+
}
|
|
11800
|
+
|
|
11801
|
+
connectedCallback() {
|
|
11802
|
+
this.#sync();
|
|
11803
|
+
}
|
|
11804
|
+
|
|
11805
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
11806
|
+
if (oldValue !== newValue) this.#sync();
|
|
11807
|
+
}
|
|
11808
|
+
|
|
11809
|
+
#sync() {
|
|
11810
|
+
const iconName = this.getAttribute("name");
|
|
11811
|
+
const cssVar = figIconCssVar(iconName);
|
|
11812
|
+
if (cssVar) this.style.setProperty("--icon", cssVar);
|
|
11813
|
+
else this.style.removeProperty("--icon");
|
|
11814
|
+
|
|
11815
|
+
const size = this.getAttribute("size") || "medium";
|
|
11816
|
+
if (size === "small") {
|
|
11817
|
+
this.style.setProperty("--size", "var(--spacer-3)");
|
|
11818
|
+
} else {
|
|
11819
|
+
this.style.removeProperty("--size");
|
|
11820
|
+
}
|
|
11821
|
+
|
|
11822
|
+
const color = this.getAttribute("color");
|
|
11823
|
+
if (color) this.style.backgroundColor = color;
|
|
11824
|
+
else this.style.removeProperty("background-color");
|
|
11825
|
+
|
|
11826
|
+
if (!this.hasAttribute("aria-hidden")) {
|
|
11827
|
+
this.setAttribute("aria-hidden", "true");
|
|
11828
|
+
}
|
|
11829
|
+
}
|
|
11830
|
+
}
|
|
11756
11831
|
customElements.define("fig-icon", FigIcon);
|
|
11757
11832
|
|
|
11758
11833
|
class FigContent extends HTMLElement {}
|
|
@@ -12135,7 +12210,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
12135
12210
|
${headerContent}
|
|
12136
12211
|
${gamutDropdown}
|
|
12137
12212
|
<fig-button icon variant="ghost" class="fig-fill-picker-close">
|
|
12138
|
-
<
|
|
12213
|
+
<fig-icon name="close"></fig-icon>
|
|
12139
12214
|
</fig-button>
|
|
12140
12215
|
</fig-header>
|
|
12141
12216
|
<fig-content>
|
|
@@ -12305,7 +12380,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
12305
12380
|
></fig-handle>
|
|
12306
12381
|
</fig-preview>
|
|
12307
12382
|
<div class="fig-fill-picker-sliders">
|
|
12308
|
-
<fig-tooltip text="Sample color"><fig-button icon variant="ghost" class="fig-fill-picker-eyedropper"><
|
|
12383
|
+
<fig-tooltip text="Sample color"><fig-button icon variant="ghost" class="fig-fill-picker-eyedropper"><fig-icon name="eyedropper"></fig-icon></fig-button></fig-tooltip>
|
|
12309
12384
|
<fig-slider type="hue" variant="neue" min="0" max="360" value="${
|
|
12310
12385
|
this.#color.h
|
|
12311
12386
|
}"></fig-slider>
|
|
@@ -12821,7 +12896,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
12821
12896
|
</div>
|
|
12822
12897
|
<fig-tooltip text="Flip gradient">
|
|
12823
12898
|
<fig-button icon variant="ghost" class="fig-fill-picker-gradient-flip">
|
|
12824
|
-
<
|
|
12899
|
+
<fig-icon name="swap"></fig-icon>
|
|
12825
12900
|
</fig-button>
|
|
12826
12901
|
</fig-tooltip>
|
|
12827
12902
|
</fig-field>
|
|
@@ -12853,7 +12928,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
12853
12928
|
<fig-header class="fig-fill-picker-gradient-stops-header" borderless>
|
|
12854
12929
|
<span>Stops</span>
|
|
12855
12930
|
<fig-button icon variant="ghost" class="fig-fill-picker-gradient-add" title="Add stop">
|
|
12856
|
-
<
|
|
12931
|
+
<fig-icon name="add"></fig-icon>
|
|
12857
12932
|
</fig-button>
|
|
12858
12933
|
</fig-header>
|
|
12859
12934
|
<div class="fig-fill-picker-gradient-stops-list"></div>
|
|
@@ -13090,7 +13165,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
13090
13165
|
<fig-button icon variant="ghost" class="fig-fill-picker-stop-remove" ${
|
|
13091
13166
|
this.#gradient.stops.length <= 2 ? "disabled" : ""
|
|
13092
13167
|
}>
|
|
13093
|
-
<
|
|
13168
|
+
<fig-icon name="minus"></fig-icon>
|
|
13094
13169
|
</fig-button>
|
|
13095
13170
|
</fig-field>
|
|
13096
13171
|
`,
|
|
@@ -14004,8 +14079,8 @@ class FigColorTip extends HTMLElement {
|
|
|
14004
14079
|
#render() {
|
|
14005
14080
|
const mode = this.#controlMode;
|
|
14006
14081
|
if (mode === "add" || mode === "remove") {
|
|
14007
|
-
const
|
|
14008
|
-
this.innerHTML = `<fig-button icon variant="ghost"><
|
|
14082
|
+
const iconName = mode === "add" ? "add" : "minus";
|
|
14083
|
+
this.innerHTML = `<fig-button icon variant="ghost"><fig-icon name="${iconName}"></fig-icon></fig-button>`;
|
|
14009
14084
|
this.#fillPicker = null;
|
|
14010
14085
|
this.#chit = null;
|
|
14011
14086
|
this.addEventListener("click", this.#handleControlClick);
|
|
@@ -14758,11 +14833,10 @@ class FigChooser extends HTMLElement {
|
|
|
14758
14833
|
if (this.#navStart) return;
|
|
14759
14834
|
|
|
14760
14835
|
const makeChevron = () => {
|
|
14761
|
-
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14765
|
-
return icon;
|
|
14836
|
+
return createFigIcon("chevron", {
|
|
14837
|
+
size: "small",
|
|
14838
|
+
className: "fig-chooser-nav-chevron",
|
|
14839
|
+
});
|
|
14766
14840
|
};
|
|
14767
14841
|
|
|
14768
14842
|
this.#navStart = document.createElement("button");
|
|
@@ -15087,7 +15161,6 @@ class FigHandle extends HTMLElement {
|
|
|
15087
15161
|
}
|
|
15088
15162
|
|
|
15089
15163
|
connectedCallback() {
|
|
15090
|
-
if (!this.hasAttribute("type")) this.setAttribute("type", "canvas");
|
|
15091
15164
|
this.#syncDrag();
|
|
15092
15165
|
this.#syncHitArea();
|
|
15093
15166
|
this.addEventListener("click", this.#handleSelect);
|
package/package.json
CHANGED