@rogieking/figui3 11.5.0 → 11.6.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/.cursor/skills/fig-editor/SKILL.md +2 -1
- package/.cursor/skills/fig-editor/components.md +87 -0
- package/.cursor/skills/fig-editor/reference.md +37 -0
- package/.cursor/skills/figui3/components.md +6 -1
- package/.cursor/skills/figui3/react.md +1 -0
- package/CHANGELOG.md +17 -0
- package/README.md +80 -3
- package/components.css +27 -0
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +3 -3
- package/dist/fig.css +1 -1
- package/dist/fig.js +5 -5
- package/fig-editor.css +4 -168
- package/fig-editor.js +46 -7
- package/fig-gradient-editor.css +76 -0
- package/fig-gradient-editor.js +598 -0
- package/fig-popup-easing.css +8 -0
- package/fig-popup-easing.js +141 -0
- package/fig-popup-gradient.css +11 -0
- package/fig-popup-gradient.js +138 -0
- package/fig-popup-palette.css +7 -0
- package/fig-popup-palette.js +173 -0
- package/fig.js +256 -97
- package/package.json +9 -1
package/fig.js
CHANGED
|
@@ -10889,7 +10889,6 @@ class FigInputPalette extends HTMLElement {
|
|
|
10889
10889
|
#renderRAF = null;
|
|
10890
10890
|
#pickerDefinitionPromise = null;
|
|
10891
10891
|
#pickerPopup = null;
|
|
10892
|
-
#pickerEditor = null;
|
|
10893
10892
|
#syncingValueAttribute = false;
|
|
10894
10893
|
#boundHandleKeyDown = this.#handleKeyDown.bind(this);
|
|
10895
10894
|
#boundHandleHostFocus = () => this.focus();
|
|
@@ -11168,13 +11167,13 @@ class FigInputPalette extends HTMLElement {
|
|
|
11168
11167
|
#renderPickerWhenAvailable() {
|
|
11169
11168
|
if (
|
|
11170
11169
|
this.#editMode !== "picker" ||
|
|
11171
|
-
customElements.get("fig-palette
|
|
11170
|
+
customElements.get("fig-popup-palette")
|
|
11172
11171
|
) {
|
|
11173
11172
|
this.#syncPickerOpenState();
|
|
11174
11173
|
return;
|
|
11175
11174
|
}
|
|
11176
11175
|
this.#pickerDefinitionPromise ??= customElements
|
|
11177
|
-
.whenDefined("fig-palette
|
|
11176
|
+
.whenDefined("fig-popup-palette")
|
|
11178
11177
|
.then(() => {
|
|
11179
11178
|
if (!this.isConnected || this.#editMode !== "picker") return;
|
|
11180
11179
|
this.#syncPickerOpenState();
|
|
@@ -11183,28 +11182,16 @@ class FigInputPalette extends HTMLElement {
|
|
|
11183
11182
|
|
|
11184
11183
|
#ensurePickerPopup() {
|
|
11185
11184
|
if (this.#pickerPopup?.isConnected) return this.#pickerPopup;
|
|
11186
|
-
if (!customElements.get("fig-palette
|
|
11185
|
+
if (!customElements.get("fig-popup-palette")) return null;
|
|
11187
11186
|
|
|
11188
|
-
const popup = document.createElement("dialog", {
|
|
11189
|
-
|
|
11190
|
-
|
|
11191
|
-
popup.setAttribute("
|
|
11192
|
-
popup.setAttribute("offset", "0 8");
|
|
11193
|
-
popup.setAttribute("viewport-margin", "8");
|
|
11194
|
-
popup.setAttribute("popover", "manual");
|
|
11195
|
-
popup.className = "fig-palette-editor-popup";
|
|
11187
|
+
const popup = document.createElement("dialog", {
|
|
11188
|
+
is: "fig-popup-palette",
|
|
11189
|
+
});
|
|
11190
|
+
popup.setAttribute("is", "fig-popup-palette");
|
|
11196
11191
|
popup.id = figUniqueId();
|
|
11197
11192
|
popup.anchor = this;
|
|
11198
11193
|
|
|
11199
|
-
const
|
|
11200
|
-
const content = figCreateElement(
|
|
11201
|
-
"fig-content",
|
|
11202
|
-
{ className: "fig-palette-editor-content" },
|
|
11203
|
-
editor,
|
|
11204
|
-
);
|
|
11205
|
-
popup.append(content);
|
|
11206
|
-
|
|
11207
|
-
const handleEditorEvent = (event) => {
|
|
11194
|
+
const handlePopupEvent = (event) => {
|
|
11208
11195
|
event.stopPropagation();
|
|
11209
11196
|
if (!Array.isArray(event.detail)) return;
|
|
11210
11197
|
this.#colors = event.detail.map((entry) => ({
|
|
@@ -11224,14 +11211,13 @@ class FigInputPalette extends HTMLElement {
|
|
|
11224
11211
|
}),
|
|
11225
11212
|
);
|
|
11226
11213
|
};
|
|
11227
|
-
|
|
11228
|
-
|
|
11214
|
+
popup.addEventListener("input", handlePopupEvent);
|
|
11215
|
+
popup.addEventListener("change", handlePopupEvent);
|
|
11229
11216
|
popup.addEventListener("close", this.#boundPickerClosed);
|
|
11230
11217
|
popup.addEventListener("toggle", this.#boundPickerClosed);
|
|
11231
11218
|
|
|
11232
11219
|
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
11233
11220
|
this.#pickerPopup = popup;
|
|
11234
|
-
this.#pickerEditor = editor;
|
|
11235
11221
|
this.querySelector(".palette-colors-inline")?.setAttribute(
|
|
11236
11222
|
"aria-controls",
|
|
11237
11223
|
popup.id,
|
|
@@ -11241,21 +11227,21 @@ class FigInputPalette extends HTMLElement {
|
|
|
11241
11227
|
}
|
|
11242
11228
|
|
|
11243
11229
|
#syncPickerEditor() {
|
|
11244
|
-
const
|
|
11245
|
-
if (!
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11230
|
+
const popup = this.#pickerPopup;
|
|
11231
|
+
if (!popup) return;
|
|
11232
|
+
popup.setAttribute("value", JSON.stringify(this.#colors));
|
|
11233
|
+
popup.setAttribute("min", String(this.#min));
|
|
11234
|
+
popup.setAttribute("max", String(this.#max));
|
|
11235
|
+
popup.toggleAttribute("fixed", this.#isFixed);
|
|
11250
11236
|
const disabled =
|
|
11251
11237
|
this.hasAttribute("disabled") &&
|
|
11252
11238
|
this.getAttribute("disabled") !== "false";
|
|
11253
|
-
|
|
11239
|
+
popup.toggleAttribute("disabled", disabled);
|
|
11254
11240
|
}
|
|
11255
11241
|
|
|
11256
11242
|
#syncPickerOpenState() {
|
|
11257
11243
|
if (!this.isConnected || this.#editMode !== "picker") return;
|
|
11258
|
-
if (!customElements.get("fig-palette
|
|
11244
|
+
if (!customElements.get("fig-popup-palette")) {
|
|
11259
11245
|
this.#renderPickerWhenAvailable();
|
|
11260
11246
|
return;
|
|
11261
11247
|
}
|
|
@@ -11286,7 +11272,6 @@ class FigInputPalette extends HTMLElement {
|
|
|
11286
11272
|
"aria-controls",
|
|
11287
11273
|
);
|
|
11288
11274
|
this.#pickerPopup = null;
|
|
11289
|
-
this.#pickerEditor = null;
|
|
11290
11275
|
}
|
|
11291
11276
|
|
|
11292
11277
|
#createPicker(entry, index, disabled, { inline = false } = {}) {
|
|
@@ -11545,10 +11530,11 @@ figDefineElement("fig-input-palette", FigInputPalette);
|
|
|
11545
11530
|
|
|
11546
11531
|
/* Input Gradient */
|
|
11547
11532
|
/**
|
|
11548
|
-
* A gradient-only fill input
|
|
11533
|
+
* A gradient-only fill input with inline and reusable popup editing modes.
|
|
11549
11534
|
* @attr {string} value - JSON string with gradient fill data
|
|
11550
11535
|
* @attr {string} size - Passed through to the internal fig-swatch (e.g. "large")
|
|
11551
11536
|
* @attr {boolean} disabled - Whether the input is disabled
|
|
11537
|
+
* @attr {string} edit - `"true"` for inline stops, `"false"` for preview, or `"picker"` for fig-popup-gradient
|
|
11552
11538
|
* @fires input - When the gradient value changes
|
|
11553
11539
|
* @fires change - When the gradient value is committed
|
|
11554
11540
|
*/
|
|
@@ -11561,7 +11547,20 @@ class FigInputGradient extends HTMLElement {
|
|
|
11561
11547
|
#colorObserver = null;
|
|
11562
11548
|
#repositionRAF = null;
|
|
11563
11549
|
#pickerDefinitionPromise = null;
|
|
11550
|
+
#pickerPopup = null;
|
|
11551
|
+
#syncingValueAttribute = false;
|
|
11564
11552
|
anchorElement = null;
|
|
11553
|
+
#boundPickerClosed = () => {
|
|
11554
|
+
if (!this.#pickerPopup) return;
|
|
11555
|
+
if (
|
|
11556
|
+
this.#pickerPopup.hasAttribute("open") ||
|
|
11557
|
+
this.#pickerPopup.matches?.(":open") ||
|
|
11558
|
+
this.#pickerPopup.matches?.(":popover-open")
|
|
11559
|
+
) {
|
|
11560
|
+
return;
|
|
11561
|
+
}
|
|
11562
|
+
this.classList.remove("has-popup-open");
|
|
11563
|
+
};
|
|
11565
11564
|
#gradient = {
|
|
11566
11565
|
type: "linear",
|
|
11567
11566
|
angle: 90,
|
|
@@ -11660,15 +11659,22 @@ class FigInputGradient extends HTMLElement {
|
|
|
11660
11659
|
this.#parseValue();
|
|
11661
11660
|
this.#render();
|
|
11662
11661
|
this.#renderPickerWhenAvailable();
|
|
11662
|
+
this.removeEventListener("click", this.#onPickerClick);
|
|
11663
|
+
this.addEventListener("click", this.#onPickerClick);
|
|
11663
11664
|
this.removeEventListener("keydown", this.#onPickerKeyDown);
|
|
11664
11665
|
this.addEventListener("keydown", this.#onPickerKeyDown);
|
|
11665
11666
|
if (this.#isEditable) document.addEventListener("keydown", this.#onKeyDown);
|
|
11666
11667
|
}
|
|
11667
11668
|
|
|
11668
11669
|
#renderPickerWhenAvailable() {
|
|
11669
|
-
if (
|
|
11670
|
+
if (
|
|
11671
|
+
this.#editMode !== "picker" ||
|
|
11672
|
+
customElements.get("fig-popup-gradient")
|
|
11673
|
+
) {
|
|
11674
|
+
return;
|
|
11675
|
+
}
|
|
11670
11676
|
this.#pickerDefinitionPromise ??= customElements
|
|
11671
|
-
.whenDefined("fig-
|
|
11677
|
+
.whenDefined("fig-popup-gradient")
|
|
11672
11678
|
.then(() => {
|
|
11673
11679
|
if (!this.isConnected || this.#editMode !== "picker") return;
|
|
11674
11680
|
this.#render();
|
|
@@ -11677,7 +11683,9 @@ class FigInputGradient extends HTMLElement {
|
|
|
11677
11683
|
|
|
11678
11684
|
disconnectedCallback() {
|
|
11679
11685
|
document.removeEventListener("keydown", this.#onKeyDown);
|
|
11686
|
+
this.removeEventListener("click", this.#onPickerClick);
|
|
11680
11687
|
this.removeEventListener("keydown", this.#onPickerKeyDown);
|
|
11688
|
+
this.#destroyPickerPopup();
|
|
11681
11689
|
if (this.#colorObserver) {
|
|
11682
11690
|
this.#colorObserver.disconnect();
|
|
11683
11691
|
this.#colorObserver = null;
|
|
@@ -11785,10 +11793,18 @@ class FigInputGradient extends HTMLElement {
|
|
|
11785
11793
|
if (e.key !== "Enter" && e.key !== " ") return;
|
|
11786
11794
|
if (e.altKey || e.ctrlKey || e.metaKey) return;
|
|
11787
11795
|
if (figBooleanAttribute(this, "disabled")) return;
|
|
11788
|
-
const picker = this.querySelector("fig-fill-picker");
|
|
11789
|
-
if (!picker || typeof picker.open !== "function") return;
|
|
11790
11796
|
e.preventDefault();
|
|
11791
|
-
|
|
11797
|
+
this.#openPickerPopup();
|
|
11798
|
+
};
|
|
11799
|
+
|
|
11800
|
+
#onPickerClick = () => {
|
|
11801
|
+
if (
|
|
11802
|
+
this.#editMode !== "picker" ||
|
|
11803
|
+
figBooleanAttribute(this, "disabled")
|
|
11804
|
+
) {
|
|
11805
|
+
return;
|
|
11806
|
+
}
|
|
11807
|
+
this.#openPickerPopup();
|
|
11792
11808
|
};
|
|
11793
11809
|
|
|
11794
11810
|
#parseValue() {
|
|
@@ -11900,25 +11916,16 @@ class FigInputGradient extends HTMLElement {
|
|
|
11900
11916
|
disabled,
|
|
11901
11917
|
});
|
|
11902
11918
|
|
|
11903
|
-
if (mode === "picker"
|
|
11904
|
-
|
|
11905
|
-
|
|
11906
|
-
"fig-fill-picker",
|
|
11907
|
-
{
|
|
11908
|
-
mode: "gradient",
|
|
11909
|
-
value: gradientValue,
|
|
11910
|
-
disabled,
|
|
11911
|
-
},
|
|
11912
|
-
swatch,
|
|
11913
|
-
);
|
|
11914
|
-
this.replaceChildren(picker);
|
|
11919
|
+
if (mode === "picker") {
|
|
11920
|
+
this.setAttribute("aria-haspopup", "dialog");
|
|
11921
|
+
this.replaceChildren(swatch);
|
|
11915
11922
|
this.#swatch = swatch;
|
|
11916
11923
|
this.#track = null;
|
|
11917
|
-
this.#setupPickerEvents();
|
|
11918
11924
|
this.#syncFocusTarget();
|
|
11919
11925
|
return;
|
|
11920
11926
|
}
|
|
11921
11927
|
|
|
11928
|
+
this.removeAttribute("aria-haspopup");
|
|
11922
11929
|
const editable = mode === "true" || mode === "picker";
|
|
11923
11930
|
const track = editable
|
|
11924
11931
|
? figCreateElement(
|
|
@@ -11938,36 +11945,83 @@ class FigInputGradient extends HTMLElement {
|
|
|
11938
11945
|
this.#syncFocusTarget();
|
|
11939
11946
|
}
|
|
11940
11947
|
|
|
11941
|
-
#
|
|
11942
|
-
|
|
11943
|
-
if (!
|
|
11944
|
-
picker.anchorElement = this.anchorElement || this;
|
|
11948
|
+
#ensurePickerPopup() {
|
|
11949
|
+
if (this.#pickerPopup?.isConnected) return this.#pickerPopup;
|
|
11950
|
+
if (!customElements.get("fig-popup-gradient")) return null;
|
|
11945
11951
|
|
|
11946
|
-
const
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
|
|
11952
|
+
const popup = document.createElement("dialog", {
|
|
11953
|
+
is: "fig-popup-gradient",
|
|
11954
|
+
});
|
|
11955
|
+
popup.setAttribute("is", "fig-popup-gradient");
|
|
11956
|
+
popup.id = figUniqueId();
|
|
11957
|
+
popup.anchor = this.anchorElement || this;
|
|
11958
|
+
|
|
11959
|
+
const handlePopupEvent = (event) => {
|
|
11960
|
+
event.stopPropagation();
|
|
11961
|
+
if (!event.detail?.gradient) return;
|
|
11950
11962
|
this.#gradient = this.#normalizeGradient({
|
|
11951
11963
|
...this.#gradient,
|
|
11952
|
-
...detail.gradient,
|
|
11964
|
+
...event.detail.gradient,
|
|
11953
11965
|
});
|
|
11954
|
-
|
|
11955
|
-
|
|
11966
|
+
this.#syncingValueAttribute = true;
|
|
11967
|
+
this.setAttribute("value", JSON.stringify(this.value));
|
|
11968
|
+
this.#syncingValueAttribute = false;
|
|
11969
|
+
if (typeof event.detail.css === "string" && event.detail.css) {
|
|
11970
|
+
this.#swatch?.setAttribute("background", event.detail.css);
|
|
11956
11971
|
this.#syncSwatchSize();
|
|
11957
|
-
|
|
11972
|
+
} else {
|
|
11973
|
+
this.#syncSwatch();
|
|
11958
11974
|
}
|
|
11959
|
-
this
|
|
11975
|
+
this.dispatchEvent(
|
|
11976
|
+
new CustomEvent(event.type, {
|
|
11977
|
+
bubbles: true,
|
|
11978
|
+
composed: true,
|
|
11979
|
+
detail: this.value,
|
|
11980
|
+
}),
|
|
11981
|
+
);
|
|
11960
11982
|
};
|
|
11983
|
+
popup.addEventListener("input", handlePopupEvent);
|
|
11984
|
+
popup.addEventListener("change", handlePopupEvent);
|
|
11985
|
+
popup.addEventListener("close", this.#boundPickerClosed);
|
|
11986
|
+
popup.addEventListener("toggle", this.#boundPickerClosed);
|
|
11961
11987
|
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11988
|
+
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
11989
|
+
this.#pickerPopup = popup;
|
|
11990
|
+
this.setAttribute("aria-controls", popup.id);
|
|
11991
|
+
this.#syncPickerPopup();
|
|
11992
|
+
return popup;
|
|
11993
|
+
}
|
|
11966
11994
|
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11995
|
+
#syncPickerPopup() {
|
|
11996
|
+
if (!this.#pickerPopup) return;
|
|
11997
|
+
this.#pickerPopup.setAttribute("value", JSON.stringify(this.#gradient));
|
|
11998
|
+
this.#pickerPopup.toggleAttribute(
|
|
11999
|
+
"disabled",
|
|
12000
|
+
figBooleanAttribute(this, "disabled"),
|
|
12001
|
+
);
|
|
12002
|
+
this.#pickerPopup.anchor = this.anchorElement || this;
|
|
12003
|
+
}
|
|
12004
|
+
|
|
12005
|
+
#openPickerPopup() {
|
|
12006
|
+
const popup = this.#ensurePickerPopup();
|
|
12007
|
+
if (!popup) {
|
|
12008
|
+
this.#renderPickerWhenAvailable();
|
|
12009
|
+
return;
|
|
12010
|
+
}
|
|
12011
|
+
this.#syncPickerPopup();
|
|
12012
|
+
popup.open = true;
|
|
12013
|
+
this.classList.add("has-popup-open");
|
|
12014
|
+
}
|
|
12015
|
+
|
|
12016
|
+
#destroyPickerPopup() {
|
|
12017
|
+
if (!this.#pickerPopup) return;
|
|
12018
|
+
this.#pickerPopup.removeEventListener("close", this.#boundPickerClosed);
|
|
12019
|
+
this.#pickerPopup.removeEventListener("toggle", this.#boundPickerClosed);
|
|
12020
|
+
this.#pickerPopup.open = false;
|
|
12021
|
+
this.#pickerPopup.remove();
|
|
12022
|
+
this.#pickerPopup = null;
|
|
12023
|
+
this.removeAttribute("aria-controls");
|
|
12024
|
+
this.classList.remove("has-popup-open");
|
|
11971
12025
|
}
|
|
11972
12026
|
|
|
11973
12027
|
#sampleGradientColor(position) {
|
|
@@ -12487,17 +12541,20 @@ class FigInputGradient extends HTMLElement {
|
|
|
12487
12541
|
}
|
|
12488
12542
|
|
|
12489
12543
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
12490
|
-
if (oldValue === newValue) return;
|
|
12544
|
+
if (oldValue === newValue || this.#syncingValueAttribute) return;
|
|
12491
12545
|
switch (name) {
|
|
12492
12546
|
case "value":
|
|
12493
12547
|
this.#parseValue();
|
|
12494
12548
|
this.#syncSwatch();
|
|
12495
12549
|
this.#syncHandles();
|
|
12550
|
+
this.#syncPickerPopup();
|
|
12496
12551
|
break;
|
|
12497
12552
|
case "disabled":
|
|
12498
12553
|
this.#syncDisabled();
|
|
12554
|
+
this.#syncPickerPopup();
|
|
12499
12555
|
break;
|
|
12500
12556
|
case "edit":
|
|
12557
|
+
if (this.#editMode !== "picker") this.#destroyPickerPopup();
|
|
12501
12558
|
this.#render();
|
|
12502
12559
|
this.#renderPickerWhenAvailable();
|
|
12503
12560
|
if (this.#isEditable) {
|
|
@@ -15955,7 +16012,7 @@ class FigInputFile extends HTMLElement {
|
|
|
15955
16012
|
),
|
|
15956
16013
|
)
|
|
15957
16014
|
) {
|
|
15958
|
-
return "
|
|
16015
|
+
return "audio";
|
|
15959
16016
|
}
|
|
15960
16017
|
if (
|
|
15961
16018
|
files.every((file) =>
|
|
@@ -15984,7 +16041,7 @@ class FigInputFile extends HTMLElement {
|
|
|
15984
16041
|
FIG_INPUT_FILE_AUDIO_EXTENSIONS,
|
|
15985
16042
|
)
|
|
15986
16043
|
) {
|
|
15987
|
-
return "
|
|
16044
|
+
return "audio";
|
|
15988
16045
|
}
|
|
15989
16046
|
if (
|
|
15990
16047
|
this.#hasKnownExtension(
|
|
@@ -16143,11 +16200,13 @@ class FigInputFile extends HTMLElement {
|
|
|
16143
16200
|
this.#audioIcon = null;
|
|
16144
16201
|
this.#audioWaveform = null;
|
|
16145
16202
|
this.#audioPlaying = false;
|
|
16203
|
+
this.removeAttribute("data-audio-playing");
|
|
16146
16204
|
}
|
|
16147
16205
|
|
|
16148
16206
|
#setAudioPlaybackUi(playing) {
|
|
16149
16207
|
this.#audioPlaying = playing;
|
|
16150
16208
|
this.#audioIcon?.setAttribute("name", playing ? "pause" : "play");
|
|
16209
|
+
this.toggleAttribute("data-audio-playing", playing);
|
|
16151
16210
|
this.#uploadBtn?.toggleAttribute("selected", playing);
|
|
16152
16211
|
this.#uploadBtn?.setAttribute(
|
|
16153
16212
|
"aria-label",
|
|
@@ -16351,26 +16410,27 @@ class FigInputFile extends HTMLElement {
|
|
|
16351
16410
|
? this.#createMultipleFileIcon(this.#files.length)
|
|
16352
16411
|
: showsImagePreview
|
|
16353
16412
|
? this.#createImagePreviewSwatch()
|
|
16354
|
-
: createFigIcon(
|
|
16355
|
-
|
|
16356
|
-
|
|
16413
|
+
: createFigIcon(this.#selectedFileIcon());
|
|
16414
|
+
const truncEl = document.createElement("fig-truncate");
|
|
16415
|
+
truncEl.setAttribute("position", "middle");
|
|
16416
|
+
truncEl.setAttribute("tooltip", "");
|
|
16417
|
+
const buttonLabel = showsMultiplePreview
|
|
16418
|
+
? "Multiple files"
|
|
16419
|
+
: filename;
|
|
16420
|
+
const dotIdx = buttonLabel.lastIndexOf(".");
|
|
16421
|
+
if (!showsMultiplePreview && dotIdx > 0) {
|
|
16422
|
+
truncEl.setAttribute("tail", buttonLabel.slice(dotIdx));
|
|
16423
|
+
}
|
|
16424
|
+
truncEl.textContent = buttonLabel;
|
|
16425
|
+
fileIcon.setAttribute("slot", "prepend");
|
|
16357
16426
|
if (showsAudioPreview) {
|
|
16358
|
-
|
|
16359
|
-
|
|
16360
|
-
this.#
|
|
16427
|
+
fileIcon.classList.add("fig-input-file-audio-icon");
|
|
16428
|
+
truncEl.classList.add("fig-input-file-audio-label");
|
|
16429
|
+
this.#audioIcon = createFigIcon("play");
|
|
16430
|
+
this.#audioIcon.classList.add("fig-input-file-audio-control");
|
|
16431
|
+
this.#audioIcon.setAttribute("slot", "prepend");
|
|
16432
|
+
this.#uploadBtn.append(fileIcon, this.#audioIcon, truncEl);
|
|
16361
16433
|
} else {
|
|
16362
|
-
const truncEl = document.createElement("fig-truncate");
|
|
16363
|
-
truncEl.setAttribute("position", "middle");
|
|
16364
|
-
truncEl.setAttribute("tooltip", "");
|
|
16365
|
-
const buttonLabel = showsMultiplePreview
|
|
16366
|
-
? "Multiple files"
|
|
16367
|
-
: filename;
|
|
16368
|
-
const dotIdx = buttonLabel.lastIndexOf(".");
|
|
16369
|
-
if (!showsMultiplePreview && dotIdx > 0) {
|
|
16370
|
-
truncEl.setAttribute("tail", buttonLabel.slice(dotIdx));
|
|
16371
|
-
}
|
|
16372
|
-
truncEl.textContent = buttonLabel;
|
|
16373
|
-
fileIcon.setAttribute("slot", "prepend");
|
|
16374
16434
|
this.#uploadBtn.append(fileIcon, truncEl);
|
|
16375
16435
|
}
|
|
16376
16436
|
|
|
@@ -16489,6 +16549,8 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16489
16549
|
#durationBarWidth = 10;
|
|
16490
16550
|
#durationBarHeight = 10;
|
|
16491
16551
|
#durationBarRadius = 3;
|
|
16552
|
+
#pickerDefinitionPromise = null;
|
|
16553
|
+
#pickerPopup = null;
|
|
16492
16554
|
|
|
16493
16555
|
static PRESETS = [
|
|
16494
16556
|
{ group: null, name: "Linear", type: "bezier", value: [0, 0, 1, 1] },
|
|
@@ -16587,6 +16649,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16587
16649
|
this.#resizeObserver.disconnect();
|
|
16588
16650
|
this.#resizeObserver = null;
|
|
16589
16651
|
}
|
|
16652
|
+
this.#destroyPickerPopup();
|
|
16590
16653
|
}
|
|
16591
16654
|
|
|
16592
16655
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -16602,6 +16665,9 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16602
16665
|
}
|
|
16603
16666
|
|
|
16604
16667
|
if (name === "edit" || name === "presets" || name === "text") {
|
|
16668
|
+
if (name === "edit" && newValue !== "false") {
|
|
16669
|
+
this.#destroyPickerPopup();
|
|
16670
|
+
}
|
|
16605
16671
|
if (this.isConnected) this.#render();
|
|
16606
16672
|
return;
|
|
16607
16673
|
}
|
|
@@ -16613,6 +16679,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16613
16679
|
this.#applyModeConstraint();
|
|
16614
16680
|
this.#presetName = this.#matchPreset();
|
|
16615
16681
|
if (this.isConnected) this.#render();
|
|
16682
|
+
this.#syncPickerPopup();
|
|
16616
16683
|
return;
|
|
16617
16684
|
}
|
|
16618
16685
|
|
|
@@ -16631,6 +16698,9 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16631
16698
|
if (name === "precision") {
|
|
16632
16699
|
this.#precision = parseInt(newValue || "2");
|
|
16633
16700
|
}
|
|
16701
|
+
if (name === "value" || name === "mode" || name === "precision") {
|
|
16702
|
+
this.#syncPickerPopup();
|
|
16703
|
+
}
|
|
16634
16704
|
}
|
|
16635
16705
|
|
|
16636
16706
|
get value() {
|
|
@@ -17092,7 +17162,14 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17092
17162
|
let parent = dropdown;
|
|
17093
17163
|
for (const preset of FigEasingCurve.PRESETS) {
|
|
17094
17164
|
if (!this.#allowsPreset(preset)) continue;
|
|
17095
|
-
if (
|
|
17165
|
+
if (
|
|
17166
|
+
!this.#isEditEnabled() &&
|
|
17167
|
+
!customElements.get("fig-popup-easing") &&
|
|
17168
|
+
!preset.value &&
|
|
17169
|
+
!preset.spring
|
|
17170
|
+
) {
|
|
17171
|
+
continue;
|
|
17172
|
+
}
|
|
17096
17173
|
if (preset.group !== currentGroup) {
|
|
17097
17174
|
currentGroup = preset.group;
|
|
17098
17175
|
parent = currentGroup
|
|
@@ -17114,7 +17191,14 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17114
17191
|
let currentGroup = undefined;
|
|
17115
17192
|
for (const p of FigEasingCurve.PRESETS) {
|
|
17116
17193
|
if (!this.#allowsPreset(p)) continue;
|
|
17117
|
-
if (
|
|
17194
|
+
if (
|
|
17195
|
+
!this.#isEditEnabled() &&
|
|
17196
|
+
!customElements.get("fig-popup-easing") &&
|
|
17197
|
+
!p.value &&
|
|
17198
|
+
!p.spring
|
|
17199
|
+
) {
|
|
17200
|
+
continue;
|
|
17201
|
+
}
|
|
17118
17202
|
if (p.group !== currentGroup) {
|
|
17119
17203
|
if (p.group) {
|
|
17120
17204
|
options.appendChild(
|
|
@@ -17733,7 +17817,12 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17733
17817
|
|
|
17734
17818
|
#refreshCustomPresetIcons() {
|
|
17735
17819
|
if (!this.#select) return;
|
|
17736
|
-
if (
|
|
17820
|
+
if (
|
|
17821
|
+
!this.#isEditEnabled() &&
|
|
17822
|
+
!customElements.get("fig-popup-easing")
|
|
17823
|
+
) {
|
|
17824
|
+
return;
|
|
17825
|
+
}
|
|
17737
17826
|
const bezierIcon = FigEasingCurve.#createCurveIcon(
|
|
17738
17827
|
this.#cp1.x,
|
|
17739
17828
|
this.#cp1.y,
|
|
@@ -17942,6 +18031,22 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17942
18031
|
}
|
|
17943
18032
|
|
|
17944
18033
|
if (this.#select) {
|
|
18034
|
+
if (!this.#isEditEnabled() && this.#select.tagName === "FIG-SELECT") {
|
|
18035
|
+
const openPicker = (event) => {
|
|
18036
|
+
if (!customElements.get("fig-popup-easing")) return;
|
|
18037
|
+
event.preventDefault();
|
|
18038
|
+
event.stopImmediatePropagation();
|
|
18039
|
+
this.#openPickerPopup();
|
|
18040
|
+
};
|
|
18041
|
+
this.#select.addEventListener("click", openPicker, true);
|
|
18042
|
+
this.#select.addEventListener(
|
|
18043
|
+
"keydown",
|
|
18044
|
+
(event) => {
|
|
18045
|
+
if (event.key === "Enter" || event.key === " ") openPicker(event);
|
|
18046
|
+
},
|
|
18047
|
+
true,
|
|
18048
|
+
);
|
|
18049
|
+
}
|
|
17945
18050
|
this.#select.addEventListener("input", (e) => {
|
|
17946
18051
|
e.stopPropagation();
|
|
17947
18052
|
});
|
|
@@ -18009,6 +18114,59 @@ class FigEasingCurve extends HTMLElement {
|
|
|
18009
18114
|
}
|
|
18010
18115
|
}
|
|
18011
18116
|
|
|
18117
|
+
#openPickerPopup() {
|
|
18118
|
+
if (!customElements.get("fig-popup-easing")) {
|
|
18119
|
+
this.#pickerDefinitionPromise ??= customElements
|
|
18120
|
+
.whenDefined("fig-popup-easing")
|
|
18121
|
+
.then(() => {
|
|
18122
|
+
if (!this.isConnected || this.#isEditEnabled()) return;
|
|
18123
|
+
this.#openPickerPopup();
|
|
18124
|
+
});
|
|
18125
|
+
return;
|
|
18126
|
+
}
|
|
18127
|
+
|
|
18128
|
+
let popup = this.#pickerPopup;
|
|
18129
|
+
if (!popup?.isConnected) {
|
|
18130
|
+
popup = document.createElement("dialog", { is: "fig-popup-easing" });
|
|
18131
|
+
popup.setAttribute("is", "fig-popup-easing");
|
|
18132
|
+
popup.id = figUniqueId();
|
|
18133
|
+
popup.anchor = this.#select;
|
|
18134
|
+
const handlePopupEvent = (event) => {
|
|
18135
|
+
event.stopPropagation();
|
|
18136
|
+
this.value = popup.value;
|
|
18137
|
+
this.#emit(event.type);
|
|
18138
|
+
};
|
|
18139
|
+
popup.addEventListener("input", handlePopupEvent);
|
|
18140
|
+
popup.addEventListener("change", handlePopupEvent);
|
|
18141
|
+
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
18142
|
+
this.#pickerPopup = popup;
|
|
18143
|
+
this.#select?.setAttribute("aria-controls", popup.id);
|
|
18144
|
+
}
|
|
18145
|
+
|
|
18146
|
+
this.#syncPickerPopup();
|
|
18147
|
+
popup.open = true;
|
|
18148
|
+
}
|
|
18149
|
+
|
|
18150
|
+
#syncPickerPopup() {
|
|
18151
|
+
const popup = this.#pickerPopup;
|
|
18152
|
+
if (!popup) return;
|
|
18153
|
+
popup.anchor = this.#select;
|
|
18154
|
+
popup.setAttribute("value", this.value);
|
|
18155
|
+
for (const name of ["mode", "precision"]) {
|
|
18156
|
+
const value = this.getAttribute(name);
|
|
18157
|
+
if (value === null) popup.removeAttribute(name);
|
|
18158
|
+
else popup.setAttribute(name, value);
|
|
18159
|
+
}
|
|
18160
|
+
}
|
|
18161
|
+
|
|
18162
|
+
#destroyPickerPopup() {
|
|
18163
|
+
if (!this.#pickerPopup) return;
|
|
18164
|
+
this.#pickerPopup.open = false;
|
|
18165
|
+
this.#pickerPopup.remove();
|
|
18166
|
+
this.#select?.removeAttribute("aria-controls");
|
|
18167
|
+
this.#pickerPopup = null;
|
|
18168
|
+
}
|
|
18169
|
+
|
|
18012
18170
|
#clientToSVG(e) {
|
|
18013
18171
|
const ctm = this.#svg.getScreenCTM();
|
|
18014
18172
|
if (!ctm) return { x: 0, y: 0 };
|
|
@@ -20783,6 +20941,7 @@ const FIG_ICON_TOKENS = {
|
|
|
20783
20941
|
upload: "--icon-24-upload",
|
|
20784
20942
|
image: "--icon-24-image",
|
|
20785
20943
|
video: { medium: "--icon-24-video", small: "--icon-16-video" },
|
|
20944
|
+
audio: "--icon-24-audio",
|
|
20786
20945
|
sound: { medium: "--icon-24-sound", small: "--icon-16-sound" },
|
|
20787
20946
|
"sound-off": {
|
|
20788
20947
|
medium: "--icon-24-sound-off",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rogieking/figui3",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.6.0",
|
|
4
4
|
"description": "A lightweight web components library for building Figma plugin and widget UIs with native look and feel",
|
|
5
5
|
"author": "Rogie King",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -38,11 +38,19 @@
|
|
|
38
38
|
"fig.js",
|
|
39
39
|
"fig-layer.js",
|
|
40
40
|
"fig-property.js",
|
|
41
|
+
"fig-gradient-editor.js",
|
|
42
|
+
"fig-popup-easing.js",
|
|
43
|
+
"fig-popup-gradient.js",
|
|
44
|
+
"fig-popup-palette.js",
|
|
41
45
|
"fig-editor.js",
|
|
42
46
|
"fig-lab.js",
|
|
43
47
|
"fig.css",
|
|
44
48
|
"fig-layer.css",
|
|
45
49
|
"fig-property.css",
|
|
50
|
+
"fig-gradient-editor.css",
|
|
51
|
+
"fig-popup-easing.css",
|
|
52
|
+
"fig-popup-gradient.css",
|
|
53
|
+
"fig-popup-palette.css",
|
|
46
54
|
"fig-editor.css",
|
|
47
55
|
"fig-lab.css",
|
|
48
56
|
"base.css",
|