@rogieking/figui3 11.5.0 → 11.6.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/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 +28 -0
- package/README.md +84 -4
- package/components.css +30 -1
- 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 +6 -6
- 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 +404 -109
- package/package.json +9 -1
package/fig.js
CHANGED
|
@@ -2907,7 +2907,11 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2907
2907
|
_wasDragged = false;
|
|
2908
2908
|
_previousFocus = null;
|
|
2909
2909
|
_boundDocumentKeydown;
|
|
2910
|
+
_boundDocumentPointerUp;
|
|
2910
2911
|
_boundNativeClose;
|
|
2912
|
+
_boundNativeCancel;
|
|
2913
|
+
_suppressNativeCancel = false;
|
|
2914
|
+
_nativeCancelResetTimer = null;
|
|
2911
2915
|
|
|
2912
2916
|
constructor() {
|
|
2913
2917
|
super();
|
|
@@ -2929,7 +2933,10 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2929
2933
|
this._boundPointerMove = this.handlePointerMove.bind(this);
|
|
2930
2934
|
this._boundPointerUp = this.handlePointerUp.bind(this);
|
|
2931
2935
|
this._boundDocumentKeydown = this.handleDocumentKeydown.bind(this);
|
|
2936
|
+
this._boundDocumentPointerUp =
|
|
2937
|
+
this.handleDocumentPointerUp.bind(this);
|
|
2932
2938
|
this._boundNativeClose = this.handleNativeClose.bind(this);
|
|
2939
|
+
this._boundNativeCancel = this.handleNativeCancel.bind(this);
|
|
2933
2940
|
this._boundAutoClose = () => {
|
|
2934
2941
|
this.open = false;
|
|
2935
2942
|
};
|
|
@@ -2960,6 +2967,10 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2960
2967
|
if (typeof this._dragThreshold !== "number") this._dragThreshold = 3;
|
|
2961
2968
|
if (typeof this._wasDragged === "undefined") this._wasDragged = false;
|
|
2962
2969
|
if (typeof this._previousFocus === "undefined") this._previousFocus = null;
|
|
2970
|
+
if (typeof this._suppressNativeCancel === "undefined")
|
|
2971
|
+
this._suppressNativeCancel = false;
|
|
2972
|
+
if (typeof this._nativeCancelResetTimer === "undefined")
|
|
2973
|
+
this._nativeCancelResetTimer = null;
|
|
2963
2974
|
|
|
2964
2975
|
if (typeof this._boundReposition !== "function") {
|
|
2965
2976
|
this._boundReposition = () => this.queueReposition();
|
|
@@ -2995,9 +3006,16 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2995
3006
|
if (typeof this._boundDocumentKeydown !== "function") {
|
|
2996
3007
|
this._boundDocumentKeydown = this.handleDocumentKeydown.bind(this);
|
|
2997
3008
|
}
|
|
3009
|
+
if (typeof this._boundDocumentPointerUp !== "function") {
|
|
3010
|
+
this._boundDocumentPointerUp =
|
|
3011
|
+
this.handleDocumentPointerUp.bind(this);
|
|
3012
|
+
}
|
|
2998
3013
|
if (typeof this._boundNativeClose !== "function") {
|
|
2999
3014
|
this._boundNativeClose = this.handleNativeClose.bind(this);
|
|
3000
3015
|
}
|
|
3016
|
+
if (typeof this._boundNativeCancel !== "function") {
|
|
3017
|
+
this._boundNativeCancel = this.handleNativeCancel.bind(this);
|
|
3018
|
+
}
|
|
3001
3019
|
if (typeof this._boundAutoClose !== "function") {
|
|
3002
3020
|
this._boundAutoClose = () => {
|
|
3003
3021
|
this.open = false;
|
|
@@ -3092,6 +3110,8 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3092
3110
|
|
|
3093
3111
|
this.removeEventListener("close", this._boundNativeClose);
|
|
3094
3112
|
this.addEventListener("close", this._boundNativeClose);
|
|
3113
|
+
this.removeEventListener("cancel", this._boundNativeCancel);
|
|
3114
|
+
this.addEventListener("cancel", this._boundNativeCancel);
|
|
3095
3115
|
|
|
3096
3116
|
requestAnimationFrame(() => {
|
|
3097
3117
|
this.setupDragListeners();
|
|
@@ -3114,7 +3134,22 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3114
3134
|
true,
|
|
3115
3135
|
);
|
|
3116
3136
|
document.removeEventListener("keydown", this._boundDocumentKeydown, true);
|
|
3137
|
+
document.removeEventListener(
|
|
3138
|
+
"pointerup",
|
|
3139
|
+
this._boundDocumentPointerUp,
|
|
3140
|
+
true,
|
|
3141
|
+
);
|
|
3142
|
+
document.removeEventListener(
|
|
3143
|
+
"pointercancel",
|
|
3144
|
+
this._boundDocumentPointerUp,
|
|
3145
|
+
true,
|
|
3146
|
+
);
|
|
3117
3147
|
this.removeEventListener("close", this._boundNativeClose);
|
|
3148
|
+
this.removeEventListener("cancel", this._boundNativeCancel);
|
|
3149
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3150
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3151
|
+
this._nativeCancelResetTimer = null;
|
|
3152
|
+
}
|
|
3118
3153
|
if (this._rafId !== null) {
|
|
3119
3154
|
cancelAnimationFrame(this._rafId);
|
|
3120
3155
|
this._rafId = null;
|
|
@@ -3210,6 +3245,16 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3210
3245
|
true,
|
|
3211
3246
|
);
|
|
3212
3247
|
document.addEventListener("keydown", this._boundDocumentKeydown, true);
|
|
3248
|
+
document.addEventListener(
|
|
3249
|
+
"pointerup",
|
|
3250
|
+
this._boundDocumentPointerUp,
|
|
3251
|
+
true,
|
|
3252
|
+
);
|
|
3253
|
+
document.addEventListener(
|
|
3254
|
+
"pointercancel",
|
|
3255
|
+
this._boundDocumentPointerUp,
|
|
3256
|
+
true,
|
|
3257
|
+
);
|
|
3213
3258
|
this._wasDragged = false;
|
|
3214
3259
|
this.queueReposition();
|
|
3215
3260
|
this._isPopupActive = true;
|
|
@@ -3241,6 +3286,21 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3241
3286
|
true,
|
|
3242
3287
|
);
|
|
3243
3288
|
document.removeEventListener("keydown", this._boundDocumentKeydown, true);
|
|
3289
|
+
document.removeEventListener(
|
|
3290
|
+
"pointerup",
|
|
3291
|
+
this._boundDocumentPointerUp,
|
|
3292
|
+
true,
|
|
3293
|
+
);
|
|
3294
|
+
document.removeEventListener(
|
|
3295
|
+
"pointercancel",
|
|
3296
|
+
this._boundDocumentPointerUp,
|
|
3297
|
+
true,
|
|
3298
|
+
);
|
|
3299
|
+
this._suppressNativeCancel = false;
|
|
3300
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3301
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3302
|
+
this._nativeCancelResetTimer = null;
|
|
3303
|
+
}
|
|
3244
3304
|
|
|
3245
3305
|
if (
|
|
3246
3306
|
this.hasAttribute("popover") &&
|
|
@@ -3317,6 +3377,15 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3317
3377
|
if (this.hasAttribute("open")) this.removeAttribute("open");
|
|
3318
3378
|
}
|
|
3319
3379
|
|
|
3380
|
+
handleNativeCancel(event) {
|
|
3381
|
+
if (
|
|
3382
|
+
this._suppressNativeCancel &&
|
|
3383
|
+
this.getAttribute("closedby") === "any"
|
|
3384
|
+
) {
|
|
3385
|
+
event.preventDefault();
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3320
3389
|
setupObservers() {
|
|
3321
3390
|
this.teardownObservers();
|
|
3322
3391
|
|
|
@@ -3462,26 +3531,55 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3462
3531
|
// counts as inside — Node.contains() is false for slotted nodes.
|
|
3463
3532
|
const path =
|
|
3464
3533
|
typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
3465
|
-
if (path.includes(this))
|
|
3466
|
-
|
|
3534
|
+
if (path.includes(this) || this.contains(target)) {
|
|
3535
|
+
this.markOwnedPointerInteraction();
|
|
3536
|
+
return;
|
|
3537
|
+
}
|
|
3467
3538
|
|
|
3468
3539
|
const anchor = this.resolveAnchor();
|
|
3469
|
-
if (anchor && (path.includes(anchor) || anchor.contains?.(target)))
|
|
3540
|
+
if (anchor && (path.includes(anchor) || anchor.contains?.(target))) {
|
|
3541
|
+
this.markOwnedPointerInteraction();
|
|
3542
|
+
return;
|
|
3543
|
+
}
|
|
3470
3544
|
|
|
3471
|
-
if (this.isInsideDescendantPopup(target))
|
|
3545
|
+
if (this.isInsideDescendantPopup(target, path)) {
|
|
3546
|
+
this.markOwnedPointerInteraction();
|
|
3547
|
+
return;
|
|
3548
|
+
}
|
|
3472
3549
|
|
|
3550
|
+
this._suppressNativeCancel = false;
|
|
3473
3551
|
this.open = false;
|
|
3474
3552
|
}
|
|
3475
3553
|
|
|
3554
|
+
markOwnedPointerInteraction() {
|
|
3555
|
+
this._suppressNativeCancel = true;
|
|
3556
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3557
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3558
|
+
this._nativeCancelResetTimer = null;
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
|
|
3562
|
+
handleDocumentPointerUp() {
|
|
3563
|
+
if (!this._suppressNativeCancel) return;
|
|
3564
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3565
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3566
|
+
}
|
|
3567
|
+
// Native dialog light-dismiss runs after pointer dispatch. Keep the guard
|
|
3568
|
+
// through that algorithm, then allow later requestClose() calls normally.
|
|
3569
|
+
this._nativeCancelResetTimer = setTimeout(() => {
|
|
3570
|
+
this._suppressNativeCancel = false;
|
|
3571
|
+
this._nativeCancelResetTimer = null;
|
|
3572
|
+
}, 0);
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3476
3575
|
handleDocumentKeydown(event) {
|
|
3477
3576
|
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
3478
3577
|
if (!this.open) return;
|
|
3479
3578
|
if (this.getAttribute("role") === "menu") return;
|
|
3480
3579
|
const closedby = this.getAttribute("closedby");
|
|
3481
3580
|
if (closedby === "none") return;
|
|
3482
|
-
const openPopups = Array.from(
|
|
3483
|
-
|
|
3484
|
-
).filter((popup) => popup.open);
|
|
3581
|
+
const openPopups = Array.from(document.querySelectorAll("dialog[open]"))
|
|
3582
|
+
.filter((popup) => popup instanceof FigPopup && popup.open);
|
|
3485
3583
|
const topPopup = openPopups
|
|
3486
3584
|
.map((popup) => ({
|
|
3487
3585
|
popup,
|
|
@@ -3494,8 +3592,40 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3494
3592
|
this.open = false;
|
|
3495
3593
|
}
|
|
3496
3594
|
|
|
3497
|
-
|
|
3498
|
-
|
|
3595
|
+
getContainingPopup(node) {
|
|
3596
|
+
let current = node;
|
|
3597
|
+
const visited = new Set();
|
|
3598
|
+
while (current && !visited.has(current)) {
|
|
3599
|
+
visited.add(current);
|
|
3600
|
+
if (current instanceof FigPopup) return current;
|
|
3601
|
+
current =
|
|
3602
|
+
current.parentNode ??
|
|
3603
|
+
(current.getRootNode?.() instanceof ShadowRoot
|
|
3604
|
+
? current.getRootNode().host
|
|
3605
|
+
: null);
|
|
3606
|
+
}
|
|
3607
|
+
return null;
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
composedContains(node) {
|
|
3611
|
+
let current = node;
|
|
3612
|
+
const visited = new Set();
|
|
3613
|
+
while (current && !visited.has(current)) {
|
|
3614
|
+
if (current === this) return true;
|
|
3615
|
+
visited.add(current);
|
|
3616
|
+
current =
|
|
3617
|
+
current.parentNode ??
|
|
3618
|
+
(current.getRootNode?.() instanceof ShadowRoot
|
|
3619
|
+
? current.getRootNode().host
|
|
3620
|
+
: null);
|
|
3621
|
+
}
|
|
3622
|
+
return false;
|
|
3623
|
+
}
|
|
3624
|
+
|
|
3625
|
+
isInsideDescendantPopup(target, path = []) {
|
|
3626
|
+
const targetDialog =
|
|
3627
|
+
path.find((node) => node instanceof FigPopup) ??
|
|
3628
|
+
this.getContainingPopup(target);
|
|
3499
3629
|
if (!targetDialog || targetDialog === this) return false;
|
|
3500
3630
|
|
|
3501
3631
|
let current = targetDialog;
|
|
@@ -3504,8 +3634,8 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3504
3634
|
visited.add(current);
|
|
3505
3635
|
const popupAnchor = current.anchor;
|
|
3506
3636
|
if (!(popupAnchor instanceof Element)) break;
|
|
3507
|
-
if (this.
|
|
3508
|
-
current =
|
|
3637
|
+
if (this.composedContains(popupAnchor)) return true;
|
|
3638
|
+
current = this.getContainingPopup(popupAnchor);
|
|
3509
3639
|
}
|
|
3510
3640
|
return false;
|
|
3511
3641
|
}
|
|
@@ -10889,7 +11019,6 @@ class FigInputPalette extends HTMLElement {
|
|
|
10889
11019
|
#renderRAF = null;
|
|
10890
11020
|
#pickerDefinitionPromise = null;
|
|
10891
11021
|
#pickerPopup = null;
|
|
10892
|
-
#pickerEditor = null;
|
|
10893
11022
|
#syncingValueAttribute = false;
|
|
10894
11023
|
#boundHandleKeyDown = this.#handleKeyDown.bind(this);
|
|
10895
11024
|
#boundHandleHostFocus = () => this.focus();
|
|
@@ -11168,13 +11297,13 @@ class FigInputPalette extends HTMLElement {
|
|
|
11168
11297
|
#renderPickerWhenAvailable() {
|
|
11169
11298
|
if (
|
|
11170
11299
|
this.#editMode !== "picker" ||
|
|
11171
|
-
customElements.get("fig-palette
|
|
11300
|
+
customElements.get("fig-popup-palette")
|
|
11172
11301
|
) {
|
|
11173
11302
|
this.#syncPickerOpenState();
|
|
11174
11303
|
return;
|
|
11175
11304
|
}
|
|
11176
11305
|
this.#pickerDefinitionPromise ??= customElements
|
|
11177
|
-
.whenDefined("fig-palette
|
|
11306
|
+
.whenDefined("fig-popup-palette")
|
|
11178
11307
|
.then(() => {
|
|
11179
11308
|
if (!this.isConnected || this.#editMode !== "picker") return;
|
|
11180
11309
|
this.#syncPickerOpenState();
|
|
@@ -11183,28 +11312,16 @@ class FigInputPalette extends HTMLElement {
|
|
|
11183
11312
|
|
|
11184
11313
|
#ensurePickerPopup() {
|
|
11185
11314
|
if (this.#pickerPopup?.isConnected) return this.#pickerPopup;
|
|
11186
|
-
if (!customElements.get("fig-palette
|
|
11315
|
+
if (!customElements.get("fig-popup-palette")) return null;
|
|
11187
11316
|
|
|
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";
|
|
11317
|
+
const popup = document.createElement("dialog", {
|
|
11318
|
+
is: "fig-popup-palette",
|
|
11319
|
+
});
|
|
11320
|
+
popup.setAttribute("is", "fig-popup-palette");
|
|
11196
11321
|
popup.id = figUniqueId();
|
|
11197
11322
|
popup.anchor = this;
|
|
11198
11323
|
|
|
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) => {
|
|
11324
|
+
const handlePopupEvent = (event) => {
|
|
11208
11325
|
event.stopPropagation();
|
|
11209
11326
|
if (!Array.isArray(event.detail)) return;
|
|
11210
11327
|
this.#colors = event.detail.map((entry) => ({
|
|
@@ -11224,14 +11341,13 @@ class FigInputPalette extends HTMLElement {
|
|
|
11224
11341
|
}),
|
|
11225
11342
|
);
|
|
11226
11343
|
};
|
|
11227
|
-
|
|
11228
|
-
|
|
11344
|
+
popup.addEventListener("input", handlePopupEvent);
|
|
11345
|
+
popup.addEventListener("change", handlePopupEvent);
|
|
11229
11346
|
popup.addEventListener("close", this.#boundPickerClosed);
|
|
11230
11347
|
popup.addEventListener("toggle", this.#boundPickerClosed);
|
|
11231
11348
|
|
|
11232
11349
|
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
11233
11350
|
this.#pickerPopup = popup;
|
|
11234
|
-
this.#pickerEditor = editor;
|
|
11235
11351
|
this.querySelector(".palette-colors-inline")?.setAttribute(
|
|
11236
11352
|
"aria-controls",
|
|
11237
11353
|
popup.id,
|
|
@@ -11241,21 +11357,21 @@ class FigInputPalette extends HTMLElement {
|
|
|
11241
11357
|
}
|
|
11242
11358
|
|
|
11243
11359
|
#syncPickerEditor() {
|
|
11244
|
-
const
|
|
11245
|
-
if (!
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11360
|
+
const popup = this.#pickerPopup;
|
|
11361
|
+
if (!popup) return;
|
|
11362
|
+
popup.setAttribute("value", JSON.stringify(this.#colors));
|
|
11363
|
+
popup.setAttribute("min", String(this.#min));
|
|
11364
|
+
popup.setAttribute("max", String(this.#max));
|
|
11365
|
+
popup.toggleAttribute("fixed", this.#isFixed);
|
|
11250
11366
|
const disabled =
|
|
11251
11367
|
this.hasAttribute("disabled") &&
|
|
11252
11368
|
this.getAttribute("disabled") !== "false";
|
|
11253
|
-
|
|
11369
|
+
popup.toggleAttribute("disabled", disabled);
|
|
11254
11370
|
}
|
|
11255
11371
|
|
|
11256
11372
|
#syncPickerOpenState() {
|
|
11257
11373
|
if (!this.isConnected || this.#editMode !== "picker") return;
|
|
11258
|
-
if (!customElements.get("fig-palette
|
|
11374
|
+
if (!customElements.get("fig-popup-palette")) {
|
|
11259
11375
|
this.#renderPickerWhenAvailable();
|
|
11260
11376
|
return;
|
|
11261
11377
|
}
|
|
@@ -11286,7 +11402,6 @@ class FigInputPalette extends HTMLElement {
|
|
|
11286
11402
|
"aria-controls",
|
|
11287
11403
|
);
|
|
11288
11404
|
this.#pickerPopup = null;
|
|
11289
|
-
this.#pickerEditor = null;
|
|
11290
11405
|
}
|
|
11291
11406
|
|
|
11292
11407
|
#createPicker(entry, index, disabled, { inline = false } = {}) {
|
|
@@ -11545,10 +11660,11 @@ figDefineElement("fig-input-palette", FigInputPalette);
|
|
|
11545
11660
|
|
|
11546
11661
|
/* Input Gradient */
|
|
11547
11662
|
/**
|
|
11548
|
-
* A gradient-only fill input
|
|
11663
|
+
* A gradient-only fill input with inline and reusable popup editing modes.
|
|
11549
11664
|
* @attr {string} value - JSON string with gradient fill data
|
|
11550
11665
|
* @attr {string} size - Passed through to the internal fig-swatch (e.g. "large")
|
|
11551
11666
|
* @attr {boolean} disabled - Whether the input is disabled
|
|
11667
|
+
* @attr {string} edit - `"true"` for inline stops, `"false"` for preview, or `"picker"` for fig-popup-gradient
|
|
11552
11668
|
* @fires input - When the gradient value changes
|
|
11553
11669
|
* @fires change - When the gradient value is committed
|
|
11554
11670
|
*/
|
|
@@ -11561,7 +11677,20 @@ class FigInputGradient extends HTMLElement {
|
|
|
11561
11677
|
#colorObserver = null;
|
|
11562
11678
|
#repositionRAF = null;
|
|
11563
11679
|
#pickerDefinitionPromise = null;
|
|
11680
|
+
#pickerPopup = null;
|
|
11681
|
+
#syncingValueAttribute = false;
|
|
11564
11682
|
anchorElement = null;
|
|
11683
|
+
#boundPickerClosed = () => {
|
|
11684
|
+
if (!this.#pickerPopup) return;
|
|
11685
|
+
if (
|
|
11686
|
+
this.#pickerPopup.hasAttribute("open") ||
|
|
11687
|
+
this.#pickerPopup.matches?.(":open") ||
|
|
11688
|
+
this.#pickerPopup.matches?.(":popover-open")
|
|
11689
|
+
) {
|
|
11690
|
+
return;
|
|
11691
|
+
}
|
|
11692
|
+
this.classList.remove("has-popup-open");
|
|
11693
|
+
};
|
|
11565
11694
|
#gradient = {
|
|
11566
11695
|
type: "linear",
|
|
11567
11696
|
angle: 90,
|
|
@@ -11660,15 +11789,22 @@ class FigInputGradient extends HTMLElement {
|
|
|
11660
11789
|
this.#parseValue();
|
|
11661
11790
|
this.#render();
|
|
11662
11791
|
this.#renderPickerWhenAvailable();
|
|
11792
|
+
this.removeEventListener("click", this.#onPickerClick);
|
|
11793
|
+
this.addEventListener("click", this.#onPickerClick);
|
|
11663
11794
|
this.removeEventListener("keydown", this.#onPickerKeyDown);
|
|
11664
11795
|
this.addEventListener("keydown", this.#onPickerKeyDown);
|
|
11665
11796
|
if (this.#isEditable) document.addEventListener("keydown", this.#onKeyDown);
|
|
11666
11797
|
}
|
|
11667
11798
|
|
|
11668
11799
|
#renderPickerWhenAvailable() {
|
|
11669
|
-
if (
|
|
11800
|
+
if (
|
|
11801
|
+
this.#editMode !== "picker" ||
|
|
11802
|
+
customElements.get("fig-popup-gradient")
|
|
11803
|
+
) {
|
|
11804
|
+
return;
|
|
11805
|
+
}
|
|
11670
11806
|
this.#pickerDefinitionPromise ??= customElements
|
|
11671
|
-
.whenDefined("fig-
|
|
11807
|
+
.whenDefined("fig-popup-gradient")
|
|
11672
11808
|
.then(() => {
|
|
11673
11809
|
if (!this.isConnected || this.#editMode !== "picker") return;
|
|
11674
11810
|
this.#render();
|
|
@@ -11677,7 +11813,9 @@ class FigInputGradient extends HTMLElement {
|
|
|
11677
11813
|
|
|
11678
11814
|
disconnectedCallback() {
|
|
11679
11815
|
document.removeEventListener("keydown", this.#onKeyDown);
|
|
11816
|
+
this.removeEventListener("click", this.#onPickerClick);
|
|
11680
11817
|
this.removeEventListener("keydown", this.#onPickerKeyDown);
|
|
11818
|
+
this.#destroyPickerPopup();
|
|
11681
11819
|
if (this.#colorObserver) {
|
|
11682
11820
|
this.#colorObserver.disconnect();
|
|
11683
11821
|
this.#colorObserver = null;
|
|
@@ -11785,10 +11923,18 @@ class FigInputGradient extends HTMLElement {
|
|
|
11785
11923
|
if (e.key !== "Enter" && e.key !== " ") return;
|
|
11786
11924
|
if (e.altKey || e.ctrlKey || e.metaKey) return;
|
|
11787
11925
|
if (figBooleanAttribute(this, "disabled")) return;
|
|
11788
|
-
const picker = this.querySelector("fig-fill-picker");
|
|
11789
|
-
if (!picker || typeof picker.open !== "function") return;
|
|
11790
11926
|
e.preventDefault();
|
|
11791
|
-
|
|
11927
|
+
this.#openPickerPopup();
|
|
11928
|
+
};
|
|
11929
|
+
|
|
11930
|
+
#onPickerClick = () => {
|
|
11931
|
+
if (
|
|
11932
|
+
this.#editMode !== "picker" ||
|
|
11933
|
+
figBooleanAttribute(this, "disabled")
|
|
11934
|
+
) {
|
|
11935
|
+
return;
|
|
11936
|
+
}
|
|
11937
|
+
this.#openPickerPopup();
|
|
11792
11938
|
};
|
|
11793
11939
|
|
|
11794
11940
|
#parseValue() {
|
|
@@ -11900,25 +12046,16 @@ class FigInputGradient extends HTMLElement {
|
|
|
11900
12046
|
disabled,
|
|
11901
12047
|
});
|
|
11902
12048
|
|
|
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);
|
|
12049
|
+
if (mode === "picker") {
|
|
12050
|
+
this.setAttribute("aria-haspopup", "dialog");
|
|
12051
|
+
this.replaceChildren(swatch);
|
|
11915
12052
|
this.#swatch = swatch;
|
|
11916
12053
|
this.#track = null;
|
|
11917
|
-
this.#setupPickerEvents();
|
|
11918
12054
|
this.#syncFocusTarget();
|
|
11919
12055
|
return;
|
|
11920
12056
|
}
|
|
11921
12057
|
|
|
12058
|
+
this.removeAttribute("aria-haspopup");
|
|
11922
12059
|
const editable = mode === "true" || mode === "picker";
|
|
11923
12060
|
const track = editable
|
|
11924
12061
|
? figCreateElement(
|
|
@@ -11938,36 +12075,83 @@ class FigInputGradient extends HTMLElement {
|
|
|
11938
12075
|
this.#syncFocusTarget();
|
|
11939
12076
|
}
|
|
11940
12077
|
|
|
11941
|
-
#
|
|
11942
|
-
|
|
11943
|
-
if (!
|
|
11944
|
-
|
|
12078
|
+
#ensurePickerPopup() {
|
|
12079
|
+
if (this.#pickerPopup?.isConnected) return this.#pickerPopup;
|
|
12080
|
+
if (!customElements.get("fig-popup-gradient")) return null;
|
|
12081
|
+
|
|
12082
|
+
const popup = document.createElement("dialog", {
|
|
12083
|
+
is: "fig-popup-gradient",
|
|
12084
|
+
});
|
|
12085
|
+
popup.setAttribute("is", "fig-popup-gradient");
|
|
12086
|
+
popup.id = figUniqueId();
|
|
12087
|
+
popup.anchor = this.anchorElement || this;
|
|
11945
12088
|
|
|
11946
|
-
const
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
if (!detail?.gradient) return;
|
|
12089
|
+
const handlePopupEvent = (event) => {
|
|
12090
|
+
event.stopPropagation();
|
|
12091
|
+
if (!event.detail?.gradient) return;
|
|
11950
12092
|
this.#gradient = this.#normalizeGradient({
|
|
11951
12093
|
...this.#gradient,
|
|
11952
|
-
...detail.gradient,
|
|
12094
|
+
...event.detail.gradient,
|
|
11953
12095
|
});
|
|
11954
|
-
|
|
11955
|
-
|
|
12096
|
+
this.#syncingValueAttribute = true;
|
|
12097
|
+
this.setAttribute("value", JSON.stringify(this.value));
|
|
12098
|
+
this.#syncingValueAttribute = false;
|
|
12099
|
+
if (typeof event.detail.css === "string" && event.detail.css) {
|
|
12100
|
+
this.#swatch?.setAttribute("background", event.detail.css);
|
|
11956
12101
|
this.#syncSwatchSize();
|
|
11957
|
-
|
|
12102
|
+
} else {
|
|
12103
|
+
this.#syncSwatch();
|
|
11958
12104
|
}
|
|
11959
|
-
this
|
|
12105
|
+
this.dispatchEvent(
|
|
12106
|
+
new CustomEvent(event.type, {
|
|
12107
|
+
bubbles: true,
|
|
12108
|
+
composed: true,
|
|
12109
|
+
detail: this.value,
|
|
12110
|
+
}),
|
|
12111
|
+
);
|
|
11960
12112
|
};
|
|
12113
|
+
popup.addEventListener("input", handlePopupEvent);
|
|
12114
|
+
popup.addEventListener("change", handlePopupEvent);
|
|
12115
|
+
popup.addEventListener("close", this.#boundPickerClosed);
|
|
12116
|
+
popup.addEventListener("toggle", this.#boundPickerClosed);
|
|
11961
12117
|
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
12118
|
+
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
12119
|
+
this.#pickerPopup = popup;
|
|
12120
|
+
this.setAttribute("aria-controls", popup.id);
|
|
12121
|
+
this.#syncPickerPopup();
|
|
12122
|
+
return popup;
|
|
12123
|
+
}
|
|
11966
12124
|
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
12125
|
+
#syncPickerPopup() {
|
|
12126
|
+
if (!this.#pickerPopup) return;
|
|
12127
|
+
this.#pickerPopup.setAttribute("value", JSON.stringify(this.#gradient));
|
|
12128
|
+
this.#pickerPopup.toggleAttribute(
|
|
12129
|
+
"disabled",
|
|
12130
|
+
figBooleanAttribute(this, "disabled"),
|
|
12131
|
+
);
|
|
12132
|
+
this.#pickerPopup.anchor = this.anchorElement || this;
|
|
12133
|
+
}
|
|
12134
|
+
|
|
12135
|
+
#openPickerPopup() {
|
|
12136
|
+
const popup = this.#ensurePickerPopup();
|
|
12137
|
+
if (!popup) {
|
|
12138
|
+
this.#renderPickerWhenAvailable();
|
|
12139
|
+
return;
|
|
12140
|
+
}
|
|
12141
|
+
this.#syncPickerPopup();
|
|
12142
|
+
popup.open = true;
|
|
12143
|
+
this.classList.add("has-popup-open");
|
|
12144
|
+
}
|
|
12145
|
+
|
|
12146
|
+
#destroyPickerPopup() {
|
|
12147
|
+
if (!this.#pickerPopup) return;
|
|
12148
|
+
this.#pickerPopup.removeEventListener("close", this.#boundPickerClosed);
|
|
12149
|
+
this.#pickerPopup.removeEventListener("toggle", this.#boundPickerClosed);
|
|
12150
|
+
this.#pickerPopup.open = false;
|
|
12151
|
+
this.#pickerPopup.remove();
|
|
12152
|
+
this.#pickerPopup = null;
|
|
12153
|
+
this.removeAttribute("aria-controls");
|
|
12154
|
+
this.classList.remove("has-popup-open");
|
|
11971
12155
|
}
|
|
11972
12156
|
|
|
11973
12157
|
#sampleGradientColor(position) {
|
|
@@ -12253,7 +12437,13 @@ class FigInputGradient extends HTMLElement {
|
|
|
12253
12437
|
|
|
12254
12438
|
this.#track.addEventListener("pointerdown", (e) => {
|
|
12255
12439
|
if (figBooleanAttribute(this, "disabled")) return;
|
|
12256
|
-
|
|
12440
|
+
const handle = e.target.closest(
|
|
12441
|
+
"fig-handle:not(.fig-input-gradient-ghost)",
|
|
12442
|
+
);
|
|
12443
|
+
if (handle) {
|
|
12444
|
+
this.#activateStopHandle(handle);
|
|
12445
|
+
return;
|
|
12446
|
+
}
|
|
12257
12447
|
if (e.button !== 0) return;
|
|
12258
12448
|
e.preventDefault();
|
|
12259
12449
|
e.stopPropagation();
|
|
@@ -12487,17 +12677,20 @@ class FigInputGradient extends HTMLElement {
|
|
|
12487
12677
|
}
|
|
12488
12678
|
|
|
12489
12679
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
12490
|
-
if (oldValue === newValue) return;
|
|
12680
|
+
if (oldValue === newValue || this.#syncingValueAttribute) return;
|
|
12491
12681
|
switch (name) {
|
|
12492
12682
|
case "value":
|
|
12493
12683
|
this.#parseValue();
|
|
12494
12684
|
this.#syncSwatch();
|
|
12495
12685
|
this.#syncHandles();
|
|
12686
|
+
this.#syncPickerPopup();
|
|
12496
12687
|
break;
|
|
12497
12688
|
case "disabled":
|
|
12498
12689
|
this.#syncDisabled();
|
|
12690
|
+
this.#syncPickerPopup();
|
|
12499
12691
|
break;
|
|
12500
12692
|
case "edit":
|
|
12693
|
+
if (this.#editMode !== "picker") this.#destroyPickerPopup();
|
|
12501
12694
|
this.#render();
|
|
12502
12695
|
this.#renderPickerWhenAvailable();
|
|
12503
12696
|
if (this.#isEditable) {
|
|
@@ -15955,7 +16148,7 @@ class FigInputFile extends HTMLElement {
|
|
|
15955
16148
|
),
|
|
15956
16149
|
)
|
|
15957
16150
|
) {
|
|
15958
|
-
return "
|
|
16151
|
+
return "audio";
|
|
15959
16152
|
}
|
|
15960
16153
|
if (
|
|
15961
16154
|
files.every((file) =>
|
|
@@ -15984,7 +16177,7 @@ class FigInputFile extends HTMLElement {
|
|
|
15984
16177
|
FIG_INPUT_FILE_AUDIO_EXTENSIONS,
|
|
15985
16178
|
)
|
|
15986
16179
|
) {
|
|
15987
|
-
return "
|
|
16180
|
+
return "audio";
|
|
15988
16181
|
}
|
|
15989
16182
|
if (
|
|
15990
16183
|
this.#hasKnownExtension(
|
|
@@ -16143,11 +16336,13 @@ class FigInputFile extends HTMLElement {
|
|
|
16143
16336
|
this.#audioIcon = null;
|
|
16144
16337
|
this.#audioWaveform = null;
|
|
16145
16338
|
this.#audioPlaying = false;
|
|
16339
|
+
this.removeAttribute("data-audio-playing");
|
|
16146
16340
|
}
|
|
16147
16341
|
|
|
16148
16342
|
#setAudioPlaybackUi(playing) {
|
|
16149
16343
|
this.#audioPlaying = playing;
|
|
16150
16344
|
this.#audioIcon?.setAttribute("name", playing ? "pause" : "play");
|
|
16345
|
+
this.toggleAttribute("data-audio-playing", playing);
|
|
16151
16346
|
this.#uploadBtn?.toggleAttribute("selected", playing);
|
|
16152
16347
|
this.#uploadBtn?.setAttribute(
|
|
16153
16348
|
"aria-label",
|
|
@@ -16351,26 +16546,27 @@ class FigInputFile extends HTMLElement {
|
|
|
16351
16546
|
? this.#createMultipleFileIcon(this.#files.length)
|
|
16352
16547
|
: showsImagePreview
|
|
16353
16548
|
? this.#createImagePreviewSwatch()
|
|
16354
|
-
: createFigIcon(
|
|
16355
|
-
|
|
16356
|
-
|
|
16549
|
+
: createFigIcon(this.#selectedFileIcon());
|
|
16550
|
+
const truncEl = document.createElement("fig-truncate");
|
|
16551
|
+
truncEl.setAttribute("position", "middle");
|
|
16552
|
+
truncEl.setAttribute("tooltip", "");
|
|
16553
|
+
const buttonLabel = showsMultiplePreview
|
|
16554
|
+
? "Multiple files"
|
|
16555
|
+
: filename;
|
|
16556
|
+
const dotIdx = buttonLabel.lastIndexOf(".");
|
|
16557
|
+
if (!showsMultiplePreview && dotIdx > 0) {
|
|
16558
|
+
truncEl.setAttribute("tail", buttonLabel.slice(dotIdx));
|
|
16559
|
+
}
|
|
16560
|
+
truncEl.textContent = buttonLabel;
|
|
16561
|
+
fileIcon.setAttribute("slot", "prepend");
|
|
16357
16562
|
if (showsAudioPreview) {
|
|
16358
|
-
|
|
16359
|
-
|
|
16360
|
-
this.#
|
|
16563
|
+
fileIcon.classList.add("fig-input-file-audio-icon");
|
|
16564
|
+
truncEl.classList.add("fig-input-file-audio-label");
|
|
16565
|
+
this.#audioIcon = createFigIcon("play");
|
|
16566
|
+
this.#audioIcon.classList.add("fig-input-file-audio-control");
|
|
16567
|
+
this.#audioIcon.setAttribute("slot", "prepend");
|
|
16568
|
+
this.#uploadBtn.append(fileIcon, this.#audioIcon, truncEl);
|
|
16361
16569
|
} 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
16570
|
this.#uploadBtn.append(fileIcon, truncEl);
|
|
16375
16571
|
}
|
|
16376
16572
|
|
|
@@ -16489,6 +16685,8 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16489
16685
|
#durationBarWidth = 10;
|
|
16490
16686
|
#durationBarHeight = 10;
|
|
16491
16687
|
#durationBarRadius = 3;
|
|
16688
|
+
#pickerDefinitionPromise = null;
|
|
16689
|
+
#pickerPopup = null;
|
|
16492
16690
|
|
|
16493
16691
|
static PRESETS = [
|
|
16494
16692
|
{ group: null, name: "Linear", type: "bezier", value: [0, 0, 1, 1] },
|
|
@@ -16587,6 +16785,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16587
16785
|
this.#resizeObserver.disconnect();
|
|
16588
16786
|
this.#resizeObserver = null;
|
|
16589
16787
|
}
|
|
16788
|
+
this.#destroyPickerPopup();
|
|
16590
16789
|
}
|
|
16591
16790
|
|
|
16592
16791
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -16602,6 +16801,9 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16602
16801
|
}
|
|
16603
16802
|
|
|
16604
16803
|
if (name === "edit" || name === "presets" || name === "text") {
|
|
16804
|
+
if (name === "edit" && newValue !== "false") {
|
|
16805
|
+
this.#destroyPickerPopup();
|
|
16806
|
+
}
|
|
16605
16807
|
if (this.isConnected) this.#render();
|
|
16606
16808
|
return;
|
|
16607
16809
|
}
|
|
@@ -16613,6 +16815,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16613
16815
|
this.#applyModeConstraint();
|
|
16614
16816
|
this.#presetName = this.#matchPreset();
|
|
16615
16817
|
if (this.isConnected) this.#render();
|
|
16818
|
+
this.#syncPickerPopup();
|
|
16616
16819
|
return;
|
|
16617
16820
|
}
|
|
16618
16821
|
|
|
@@ -16631,6 +16834,9 @@ class FigEasingCurve extends HTMLElement {
|
|
|
16631
16834
|
if (name === "precision") {
|
|
16632
16835
|
this.#precision = parseInt(newValue || "2");
|
|
16633
16836
|
}
|
|
16837
|
+
if (name === "value" || name === "mode" || name === "precision") {
|
|
16838
|
+
this.#syncPickerPopup();
|
|
16839
|
+
}
|
|
16634
16840
|
}
|
|
16635
16841
|
|
|
16636
16842
|
get value() {
|
|
@@ -17092,7 +17298,14 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17092
17298
|
let parent = dropdown;
|
|
17093
17299
|
for (const preset of FigEasingCurve.PRESETS) {
|
|
17094
17300
|
if (!this.#allowsPreset(preset)) continue;
|
|
17095
|
-
if (
|
|
17301
|
+
if (
|
|
17302
|
+
!this.#isEditEnabled() &&
|
|
17303
|
+
!customElements.get("fig-popup-easing") &&
|
|
17304
|
+
!preset.value &&
|
|
17305
|
+
!preset.spring
|
|
17306
|
+
) {
|
|
17307
|
+
continue;
|
|
17308
|
+
}
|
|
17096
17309
|
if (preset.group !== currentGroup) {
|
|
17097
17310
|
currentGroup = preset.group;
|
|
17098
17311
|
parent = currentGroup
|
|
@@ -17114,7 +17327,14 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17114
17327
|
let currentGroup = undefined;
|
|
17115
17328
|
for (const p of FigEasingCurve.PRESETS) {
|
|
17116
17329
|
if (!this.#allowsPreset(p)) continue;
|
|
17117
|
-
if (
|
|
17330
|
+
if (
|
|
17331
|
+
!this.#isEditEnabled() &&
|
|
17332
|
+
!customElements.get("fig-popup-easing") &&
|
|
17333
|
+
!p.value &&
|
|
17334
|
+
!p.spring
|
|
17335
|
+
) {
|
|
17336
|
+
continue;
|
|
17337
|
+
}
|
|
17118
17338
|
if (p.group !== currentGroup) {
|
|
17119
17339
|
if (p.group) {
|
|
17120
17340
|
options.appendChild(
|
|
@@ -17733,7 +17953,12 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17733
17953
|
|
|
17734
17954
|
#refreshCustomPresetIcons() {
|
|
17735
17955
|
if (!this.#select) return;
|
|
17736
|
-
if (
|
|
17956
|
+
if (
|
|
17957
|
+
!this.#isEditEnabled() &&
|
|
17958
|
+
!customElements.get("fig-popup-easing")
|
|
17959
|
+
) {
|
|
17960
|
+
return;
|
|
17961
|
+
}
|
|
17737
17962
|
const bezierIcon = FigEasingCurve.#createCurveIcon(
|
|
17738
17963
|
this.#cp1.x,
|
|
17739
17964
|
this.#cp1.y,
|
|
@@ -17942,6 +18167,22 @@ class FigEasingCurve extends HTMLElement {
|
|
|
17942
18167
|
}
|
|
17943
18168
|
|
|
17944
18169
|
if (this.#select) {
|
|
18170
|
+
if (!this.#isEditEnabled() && this.#select.tagName === "FIG-SELECT") {
|
|
18171
|
+
const openPicker = (event) => {
|
|
18172
|
+
if (!customElements.get("fig-popup-easing")) return;
|
|
18173
|
+
event.preventDefault();
|
|
18174
|
+
event.stopImmediatePropagation();
|
|
18175
|
+
this.#openPickerPopup();
|
|
18176
|
+
};
|
|
18177
|
+
this.#select.addEventListener("click", openPicker, true);
|
|
18178
|
+
this.#select.addEventListener(
|
|
18179
|
+
"keydown",
|
|
18180
|
+
(event) => {
|
|
18181
|
+
if (event.key === "Enter" || event.key === " ") openPicker(event);
|
|
18182
|
+
},
|
|
18183
|
+
true,
|
|
18184
|
+
);
|
|
18185
|
+
}
|
|
17945
18186
|
this.#select.addEventListener("input", (e) => {
|
|
17946
18187
|
e.stopPropagation();
|
|
17947
18188
|
});
|
|
@@ -18009,6 +18250,59 @@ class FigEasingCurve extends HTMLElement {
|
|
|
18009
18250
|
}
|
|
18010
18251
|
}
|
|
18011
18252
|
|
|
18253
|
+
#openPickerPopup() {
|
|
18254
|
+
if (!customElements.get("fig-popup-easing")) {
|
|
18255
|
+
this.#pickerDefinitionPromise ??= customElements
|
|
18256
|
+
.whenDefined("fig-popup-easing")
|
|
18257
|
+
.then(() => {
|
|
18258
|
+
if (!this.isConnected || this.#isEditEnabled()) return;
|
|
18259
|
+
this.#openPickerPopup();
|
|
18260
|
+
});
|
|
18261
|
+
return;
|
|
18262
|
+
}
|
|
18263
|
+
|
|
18264
|
+
let popup = this.#pickerPopup;
|
|
18265
|
+
if (!popup?.isConnected) {
|
|
18266
|
+
popup = document.createElement("dialog", { is: "fig-popup-easing" });
|
|
18267
|
+
popup.setAttribute("is", "fig-popup-easing");
|
|
18268
|
+
popup.id = figUniqueId();
|
|
18269
|
+
popup.anchor = this.#select;
|
|
18270
|
+
const handlePopupEvent = (event) => {
|
|
18271
|
+
event.stopPropagation();
|
|
18272
|
+
this.value = popup.value;
|
|
18273
|
+
this.#emit(event.type);
|
|
18274
|
+
};
|
|
18275
|
+
popup.addEventListener("input", handlePopupEvent);
|
|
18276
|
+
popup.addEventListener("change", handlePopupEvent);
|
|
18277
|
+
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
18278
|
+
this.#pickerPopup = popup;
|
|
18279
|
+
this.#select?.setAttribute("aria-controls", popup.id);
|
|
18280
|
+
}
|
|
18281
|
+
|
|
18282
|
+
this.#syncPickerPopup();
|
|
18283
|
+
popup.open = true;
|
|
18284
|
+
}
|
|
18285
|
+
|
|
18286
|
+
#syncPickerPopup() {
|
|
18287
|
+
const popup = this.#pickerPopup;
|
|
18288
|
+
if (!popup) return;
|
|
18289
|
+
popup.anchor = this.#select;
|
|
18290
|
+
popup.setAttribute("value", this.value);
|
|
18291
|
+
for (const name of ["mode", "precision"]) {
|
|
18292
|
+
const value = this.getAttribute(name);
|
|
18293
|
+
if (value === null) popup.removeAttribute(name);
|
|
18294
|
+
else popup.setAttribute(name, value);
|
|
18295
|
+
}
|
|
18296
|
+
}
|
|
18297
|
+
|
|
18298
|
+
#destroyPickerPopup() {
|
|
18299
|
+
if (!this.#pickerPopup) return;
|
|
18300
|
+
this.#pickerPopup.open = false;
|
|
18301
|
+
this.#pickerPopup.remove();
|
|
18302
|
+
this.#select?.removeAttribute("aria-controls");
|
|
18303
|
+
this.#pickerPopup = null;
|
|
18304
|
+
}
|
|
18305
|
+
|
|
18012
18306
|
#clientToSVG(e) {
|
|
18013
18307
|
const ctm = this.#svg.getScreenCTM();
|
|
18014
18308
|
if (!ctm) return { x: 0, y: 0 };
|
|
@@ -20783,6 +21077,7 @@ const FIG_ICON_TOKENS = {
|
|
|
20783
21077
|
upload: "--icon-24-upload",
|
|
20784
21078
|
image: "--icon-24-image",
|
|
20785
21079
|
video: { medium: "--icon-24-video", small: "--icon-16-video" },
|
|
21080
|
+
audio: "--icon-24-audio",
|
|
20786
21081
|
sound: { medium: "--icon-24-sound", small: "--icon-16-sound" },
|
|
20787
21082
|
"sound-off": {
|
|
20788
21083
|
medium: "--icon-24-sound-off",
|