@rogieking/figui3 6.9.3 → 6.9.5
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/README.md +14 -7
- package/components.css +63 -42
- package/dist/components.css +1 -1
- package/dist/fig-editor.js +7 -7
- package/dist/fig-lab.css +1 -1
- package/dist/fig-lab.js +2 -2
- package/dist/fig.css +1 -1
- package/dist/fig.js +28 -28
- package/fig-editor.js +38 -38
- package/fig-lab.css +150 -19
- package/fig-lab.js +321 -5
- package/fig.js +157 -86
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -4887,6 +4887,7 @@ class FigSlider extends HTMLElement {
|
|
|
4887
4887
|
#boundRangePointerUp;
|
|
4888
4888
|
#lastSliderComplete = null;
|
|
4889
4889
|
#lastSliderDefault = null;
|
|
4890
|
+
#lastSliderDeltaDirection = null;
|
|
4890
4891
|
#lastSliderUnchanged = null;
|
|
4891
4892
|
|
|
4892
4893
|
constructor() {
|
|
@@ -5259,6 +5260,7 @@ class FigSlider extends HTMLElement {
|
|
|
5259
5260
|
#syncProperties() {
|
|
5260
5261
|
const complete = this.#calculateNormal(this.value);
|
|
5261
5262
|
const defaultValue = this.#calculateNormal(this.default);
|
|
5263
|
+
const deltaDirection = complete < defaultValue ? -1 : 1;
|
|
5262
5264
|
const unchanged = complete === defaultValue ? 1 : 0;
|
|
5263
5265
|
|
|
5264
5266
|
if (this.#lastSliderComplete !== complete) {
|
|
@@ -5269,6 +5271,10 @@ class FigSlider extends HTMLElement {
|
|
|
5269
5271
|
this.style.setProperty("--default", defaultValue);
|
|
5270
5272
|
this.#lastSliderDefault = defaultValue;
|
|
5271
5273
|
}
|
|
5274
|
+
if (this.#lastSliderDeltaDirection !== deltaDirection) {
|
|
5275
|
+
this.style.setProperty("--slider-delta-direction", deltaDirection);
|
|
5276
|
+
this.#lastSliderDeltaDirection = deltaDirection;
|
|
5277
|
+
}
|
|
5272
5278
|
if (this.#lastSliderUnchanged !== unchanged) {
|
|
5273
5279
|
this.style.setProperty("--unchanged", unchanged);
|
|
5274
5280
|
this.#lastSliderUnchanged = unchanged;
|
|
@@ -7040,12 +7046,12 @@ class FigInputColor extends HTMLElement {
|
|
|
7040
7046
|
const showText = this.getAttribute("text") !== "false";
|
|
7041
7047
|
return showText
|
|
7042
7048
|
? !!this.querySelector(":scope > .input-combo")
|
|
7043
|
-
: !!this.querySelector(":scope > fig-
|
|
7049
|
+
: !!this.querySelector(":scope > fig-swatch");
|
|
7044
7050
|
}
|
|
7045
7051
|
|
|
7046
7052
|
#refreshUI() {
|
|
7047
7053
|
this.#setValues(this.getAttribute("value"));
|
|
7048
|
-
this.#swatch = this.querySelector("fig-
|
|
7054
|
+
this.#swatch = this.querySelector("fig-swatch");
|
|
7049
7055
|
this.#fillPicker = this.querySelector("fig-fill-picker");
|
|
7050
7056
|
this.#textInput = this.querySelector("fig-input-text:not([type=number])");
|
|
7051
7057
|
this.#alphaInput = this.querySelector("fig-input-number");
|
|
@@ -7152,18 +7158,18 @@ class FigInputColor extends HTMLElement {
|
|
|
7152
7158
|
}
|
|
7153
7159
|
|
|
7154
7160
|
let swatchElement = "";
|
|
7155
|
-
swatchElement = `<fig-
|
|
7161
|
+
swatchElement = `<fig-swatch background="${this.hexOpaque}" alpha="${this.rgba.a}"${disabledAttr}></fig-swatch>`;
|
|
7156
7162
|
|
|
7157
7163
|
html = `<div class="input-combo">
|
|
7158
7164
|
${swatchElement}
|
|
7159
7165
|
${label}
|
|
7160
7166
|
</div>`;
|
|
7161
7167
|
} else {
|
|
7162
|
-
html = `<fig-
|
|
7168
|
+
html = `<fig-swatch background="${this.hexOpaque}" alpha="${this.rgba.a}"${disabledAttr}></fig-swatch>`;
|
|
7163
7169
|
}
|
|
7164
7170
|
this.innerHTML = html;
|
|
7165
7171
|
|
|
7166
|
-
this.#swatch = this.querySelector("fig-
|
|
7172
|
+
this.#swatch = this.querySelector("fig-swatch");
|
|
7167
7173
|
this.#fillPicker = this.querySelector("fig-fill-picker");
|
|
7168
7174
|
this.#textInput = this.querySelector("fig-input-text:not([type=number])");
|
|
7169
7175
|
this.#alphaInput = this.querySelector("fig-input-number");
|
|
@@ -8041,7 +8047,7 @@ class FigInputFill extends HTMLElement {
|
|
|
8041
8047
|
.join(" ");
|
|
8042
8048
|
}
|
|
8043
8049
|
|
|
8044
|
-
#
|
|
8050
|
+
#fillPickerSwatchBackground() {
|
|
8045
8051
|
switch (this.#fillType) {
|
|
8046
8052
|
case "solid":
|
|
8047
8053
|
return this.#solid.color;
|
|
@@ -8066,7 +8072,7 @@ class FigInputFill extends HTMLElement {
|
|
|
8066
8072
|
}
|
|
8067
8073
|
}
|
|
8068
8074
|
|
|
8069
|
-
#
|
|
8075
|
+
#fillPickerSwatchAlpha() {
|
|
8070
8076
|
switch (this.#fillType) {
|
|
8071
8077
|
case "solid":
|
|
8072
8078
|
return this.#solid.alpha;
|
|
@@ -8187,7 +8193,7 @@ class FigInputFill extends HTMLElement {
|
|
|
8187
8193
|
<fig-fill-picker ${fpAttrs} value='${fillPickerValue}' ${
|
|
8188
8194
|
disabled ? "disabled" : ""
|
|
8189
8195
|
}>
|
|
8190
|
-
<fig-
|
|
8196
|
+
<fig-swatch background="${this.#fillPickerSwatchBackground()}" alpha="${this.#fillPickerSwatchAlpha()}"${disabled ? " disabled" : ""}></fig-swatch>
|
|
8191
8197
|
</fig-fill-picker>
|
|
8192
8198
|
${controlsHtml}
|
|
8193
8199
|
</div>`;
|
|
@@ -8205,9 +8211,9 @@ class FigInputFill extends HTMLElement {
|
|
|
8205
8211
|
// Label click triggers fill picker
|
|
8206
8212
|
if (label && this.#fillPicker) {
|
|
8207
8213
|
label.addEventListener("click", () => {
|
|
8208
|
-
const
|
|
8209
|
-
if (
|
|
8210
|
-
|
|
8214
|
+
const swatch = this.#fillPicker.querySelector("fig-swatch");
|
|
8215
|
+
if (swatch) {
|
|
8216
|
+
swatch.click();
|
|
8211
8217
|
}
|
|
8212
8218
|
});
|
|
8213
8219
|
}
|
|
@@ -8307,8 +8313,8 @@ class FigInputFill extends HTMLElement {
|
|
|
8307
8313
|
break;
|
|
8308
8314
|
}
|
|
8309
8315
|
this.#updateFillPicker();
|
|
8310
|
-
// Update the
|
|
8311
|
-
this.#
|
|
8316
|
+
// Update the swatch's alpha
|
|
8317
|
+
this.#updateSwatchAlpha(alpha);
|
|
8312
8318
|
this.#emitInput();
|
|
8313
8319
|
});
|
|
8314
8320
|
this.#opacityInput.addEventListener("change", (e) => {
|
|
@@ -8490,9 +8496,9 @@ class FigInputFill extends HTMLElement {
|
|
|
8490
8496
|
// Label click triggers fill picker
|
|
8491
8497
|
if (label && this.#fillPicker) {
|
|
8492
8498
|
label.addEventListener("click", () => {
|
|
8493
|
-
const
|
|
8494
|
-
if (
|
|
8495
|
-
|
|
8499
|
+
const swatch = this.#fillPicker.querySelector("fig-swatch");
|
|
8500
|
+
if (swatch) {
|
|
8501
|
+
swatch.click();
|
|
8496
8502
|
}
|
|
8497
8503
|
});
|
|
8498
8504
|
}
|
|
@@ -8536,7 +8542,7 @@ class FigInputFill extends HTMLElement {
|
|
|
8536
8542
|
break;
|
|
8537
8543
|
}
|
|
8538
8544
|
this.#updateFillPicker();
|
|
8539
|
-
this.#
|
|
8545
|
+
this.#updateSwatchAlpha(alpha);
|
|
8540
8546
|
this.#emitInput();
|
|
8541
8547
|
});
|
|
8542
8548
|
this.#opacityInput.addEventListener("change", (e) => {
|
|
@@ -8552,11 +8558,11 @@ class FigInputFill extends HTMLElement {
|
|
|
8552
8558
|
}
|
|
8553
8559
|
}
|
|
8554
8560
|
|
|
8555
|
-
#
|
|
8561
|
+
#updateSwatchAlpha(alpha) {
|
|
8556
8562
|
if (this.#fillPicker) {
|
|
8557
|
-
const
|
|
8558
|
-
if (
|
|
8559
|
-
|
|
8563
|
+
const swatch = this.#fillPicker.querySelector("fig-swatch");
|
|
8564
|
+
if (swatch) {
|
|
8565
|
+
swatch.setAttribute("alpha", alpha);
|
|
8560
8566
|
}
|
|
8561
8567
|
}
|
|
8562
8568
|
}
|
|
@@ -9132,7 +9138,7 @@ customElements.define("fig-input-palette", FigInputPalette);
|
|
|
9132
9138
|
*/
|
|
9133
9139
|
class FigInputGradient extends HTMLElement {
|
|
9134
9140
|
static SHIFT_SNAP = 5;
|
|
9135
|
-
#
|
|
9141
|
+
#swatch;
|
|
9136
9142
|
#track;
|
|
9137
9143
|
#handleDragging = false;
|
|
9138
9144
|
#arrowTooltipTimer = null;
|
|
@@ -9278,7 +9284,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9278
9284
|
selected.showColorTip();
|
|
9279
9285
|
}, 600);
|
|
9280
9286
|
}
|
|
9281
|
-
this.#
|
|
9287
|
+
this.#syncSwatch();
|
|
9282
9288
|
this.#emitInput();
|
|
9283
9289
|
this.#emitChange();
|
|
9284
9290
|
return;
|
|
@@ -9297,7 +9303,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9297
9303
|
selected.removeAttribute("selected");
|
|
9298
9304
|
this.#gradient.stops.splice(idx, 1);
|
|
9299
9305
|
this.#syncHandles();
|
|
9300
|
-
this.#
|
|
9306
|
+
this.#syncSwatch();
|
|
9301
9307
|
this.#emitInput();
|
|
9302
9308
|
this.#emitChange();
|
|
9303
9309
|
};
|
|
@@ -9385,9 +9391,9 @@ class FigInputGradient extends HTMLElement {
|
|
|
9385
9391
|
const gradientValue = JSON.stringify(this.value);
|
|
9386
9392
|
this.innerHTML = `
|
|
9387
9393
|
<fig-fill-picker mode="gradient"${expAttr} value='${gradientValue}'${disabled ? " disabled" : ""}>
|
|
9388
|
-
<fig-
|
|
9394
|
+
<fig-swatch background="${this.#buildGradientCSS()}"${disabled ? " disabled" : ""}></fig-swatch>
|
|
9389
9395
|
</fig-fill-picker>`;
|
|
9390
|
-
this.#
|
|
9396
|
+
this.#swatch = this.querySelector("fig-swatch");
|
|
9391
9397
|
this.#track = null;
|
|
9392
9398
|
this.#setupPickerEvents();
|
|
9393
9399
|
this.#syncFocusTarget();
|
|
@@ -9395,9 +9401,9 @@ class FigInputGradient extends HTMLElement {
|
|
|
9395
9401
|
}
|
|
9396
9402
|
|
|
9397
9403
|
this.innerHTML = `
|
|
9398
|
-
<fig-
|
|
9404
|
+
<fig-swatch background="${this.#buildGradientCSS()}"${disabled ? " disabled" : ""}></fig-swatch>
|
|
9399
9405
|
${mode === "true" || mode === "picker" ? `<div class="fig-input-gradient-track">${this.#buildStopHandles()}</div>` : ""}`;
|
|
9400
|
-
this.#
|
|
9406
|
+
this.#swatch = this.querySelector("fig-swatch");
|
|
9401
9407
|
this.#track = this.querySelector(".fig-input-gradient-track");
|
|
9402
9408
|
|
|
9403
9409
|
if (mode === "true" || mode === "picker") {
|
|
@@ -9420,7 +9426,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9420
9426
|
...this.#gradient,
|
|
9421
9427
|
...detail.gradient,
|
|
9422
9428
|
});
|
|
9423
|
-
this.#
|
|
9429
|
+
this.#syncSwatch();
|
|
9424
9430
|
};
|
|
9425
9431
|
|
|
9426
9432
|
picker.addEventListener("input", (e) => {
|
|
@@ -9514,7 +9520,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9514
9520
|
this.#gradient.stops[i].position = Math.round((i / (count - 1)) * 100);
|
|
9515
9521
|
}
|
|
9516
9522
|
this.#syncHandles();
|
|
9517
|
-
this.#
|
|
9523
|
+
this.#syncSwatch();
|
|
9518
9524
|
this.#emitInput();
|
|
9519
9525
|
this.#emitChange();
|
|
9520
9526
|
}
|
|
@@ -9565,7 +9571,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9565
9571
|
(s) => s.position === position && s.color === color,
|
|
9566
9572
|
);
|
|
9567
9573
|
this.#syncHandles();
|
|
9568
|
-
this.#
|
|
9574
|
+
this.#syncSwatch();
|
|
9569
9575
|
this.#emitInput();
|
|
9570
9576
|
this.#emitChange();
|
|
9571
9577
|
|
|
@@ -9702,9 +9708,9 @@ class FigInputGradient extends HTMLElement {
|
|
|
9702
9708
|
});
|
|
9703
9709
|
}
|
|
9704
9710
|
|
|
9705
|
-
#
|
|
9706
|
-
if (!this.#
|
|
9707
|
-
this.#
|
|
9711
|
+
#syncSwatch() {
|
|
9712
|
+
if (!this.#swatch) return;
|
|
9713
|
+
this.#swatch.setAttribute("background", this.#buildGradientCSS());
|
|
9708
9714
|
}
|
|
9709
9715
|
|
|
9710
9716
|
#setupEventListeners() {
|
|
@@ -9731,7 +9737,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9731
9737
|
);
|
|
9732
9738
|
this.#addedOnPointerDown = true;
|
|
9733
9739
|
this.#syncHandles();
|
|
9734
|
-
this.#
|
|
9740
|
+
this.#syncSwatch();
|
|
9735
9741
|
this.#emitInput();
|
|
9736
9742
|
this.#hideGhost();
|
|
9737
9743
|
|
|
@@ -9775,7 +9781,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9775
9781
|
"color",
|
|
9776
9782
|
this.#stopColorCSS(this.#gradient.stops[idx]),
|
|
9777
9783
|
);
|
|
9778
|
-
this.#
|
|
9784
|
+
this.#syncSwatch();
|
|
9779
9785
|
this.#emitInput();
|
|
9780
9786
|
}
|
|
9781
9787
|
return;
|
|
@@ -9816,7 +9822,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9816
9822
|
handle.hideColorTip();
|
|
9817
9823
|
}
|
|
9818
9824
|
}
|
|
9819
|
-
this.#
|
|
9825
|
+
this.#syncSwatch();
|
|
9820
9826
|
this.#emitInput();
|
|
9821
9827
|
});
|
|
9822
9828
|
|
|
@@ -9835,7 +9841,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9835
9841
|
"color",
|
|
9836
9842
|
this.#stopColorCSS(this.#gradient.stops[idx]),
|
|
9837
9843
|
);
|
|
9838
|
-
this.#
|
|
9844
|
+
this.#syncSwatch();
|
|
9839
9845
|
this.#emitChange();
|
|
9840
9846
|
}
|
|
9841
9847
|
return;
|
|
@@ -9861,7 +9867,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9861
9867
|
handle.style.left = `${(position / 100) * trackW}px`;
|
|
9862
9868
|
this.#gradient.stops.sort((a, b) => a.position - b.position);
|
|
9863
9869
|
this.#syncStopIndices();
|
|
9864
|
-
this.#
|
|
9870
|
+
this.#syncSwatch();
|
|
9865
9871
|
this.#emitChange();
|
|
9866
9872
|
requestAnimationFrame(() => {
|
|
9867
9873
|
this.#handleDragging = false;
|
|
@@ -9879,7 +9885,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9879
9885
|
if (!newColor || !newColor.startsWith("#")) continue;
|
|
9880
9886
|
if (newColor !== this.#gradient.stops[idx].color) {
|
|
9881
9887
|
this.#gradient.stops[idx].color = newColor;
|
|
9882
|
-
this.#
|
|
9888
|
+
this.#syncSwatch();
|
|
9883
9889
|
this.#emitInput();
|
|
9884
9890
|
}
|
|
9885
9891
|
}
|
|
@@ -9944,7 +9950,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
9944
9950
|
switch (name) {
|
|
9945
9951
|
case "value":
|
|
9946
9952
|
this.#parseValue();
|
|
9947
|
-
this.#
|
|
9953
|
+
this.#syncSwatch();
|
|
9948
9954
|
this.#syncHandles();
|
|
9949
9955
|
break;
|
|
9950
9956
|
case "disabled":
|
|
@@ -9967,9 +9973,9 @@ class FigInputGradient extends HTMLElement {
|
|
|
9967
9973
|
#syncDisabled() {
|
|
9968
9974
|
const disabled = this.hasAttribute("disabled");
|
|
9969
9975
|
this.#syncFocusTarget();
|
|
9970
|
-
if (this.#
|
|
9971
|
-
if (disabled) this.#
|
|
9972
|
-
else this.#
|
|
9976
|
+
if (this.#swatch) {
|
|
9977
|
+
if (disabled) this.#swatch.setAttribute("disabled", "");
|
|
9978
|
+
else this.#swatch.removeAttribute("disabled");
|
|
9973
9979
|
}
|
|
9974
9980
|
if (this.#track) {
|
|
9975
9981
|
for (const handle of this.#track.querySelectorAll("fig-handle")) {
|
|
@@ -10507,7 +10513,7 @@ class FigComboInput extends HTMLElement {
|
|
|
10507
10513
|
}
|
|
10508
10514
|
customElements.define("fig-combo-input", FigComboInput);
|
|
10509
10515
|
|
|
10510
|
-
/*
|
|
10516
|
+
/* Swatch */
|
|
10511
10517
|
/**
|
|
10512
10518
|
* A color/gradient/image swatch element.
|
|
10513
10519
|
* @attr {string} background - Any CSS background value: color (#FF0000, rgba(...)), gradient (linear-gradient(...)), or image (url(...))
|
|
@@ -10516,7 +10522,7 @@ customElements.define("fig-combo-input", FigComboInput);
|
|
|
10516
10522
|
* @attr {boolean} disabled - Whether the chip is disabled
|
|
10517
10523
|
* @attr {number} alpha - Opacity value (0-1) to display the color with transparency
|
|
10518
10524
|
*/
|
|
10519
|
-
class
|
|
10525
|
+
class FigSwatch extends HTMLElement {
|
|
10520
10526
|
#type = "color"; // 'color', 'gradient', 'image'
|
|
10521
10527
|
#boundHandleInput = null;
|
|
10522
10528
|
#internalUpdate = false; // Flag to prevent re-render during internal input
|
|
@@ -10627,7 +10633,7 @@ class FigChit extends HTMLElement {
|
|
|
10627
10633
|
rawBg,
|
|
10628
10634
|
);
|
|
10629
10635
|
this.style.setProperty(
|
|
10630
|
-
"--
|
|
10636
|
+
"--swatch-background",
|
|
10631
10637
|
isImage ? rawBg : `linear-gradient(${rawBg}, ${rawBg})`,
|
|
10632
10638
|
);
|
|
10633
10639
|
}
|
|
@@ -10691,7 +10697,7 @@ class FigChit extends HTMLElement {
|
|
|
10691
10697
|
newValue,
|
|
10692
10698
|
);
|
|
10693
10699
|
this.style.setProperty(
|
|
10694
|
-
"--
|
|
10700
|
+
"--swatch-background",
|
|
10695
10701
|
isImg ? newValue : `linear-gradient(${newValue}, ${newValue})`,
|
|
10696
10702
|
);
|
|
10697
10703
|
return;
|
|
@@ -10721,8 +10727,6 @@ class FigChit extends HTMLElement {
|
|
|
10721
10727
|
}
|
|
10722
10728
|
}
|
|
10723
10729
|
}
|
|
10724
|
-
customElements.define("fig-chit", FigChit);
|
|
10725
|
-
class FigSwatch extends FigChit {}
|
|
10726
10730
|
customElements.define("fig-swatch", FigSwatch);
|
|
10727
10731
|
|
|
10728
10732
|
/* Media */
|
|
@@ -10860,7 +10864,7 @@ class FigMedia extends HTMLElement {
|
|
|
10860
10864
|
this.style.setProperty("--fig-media-fit", fit);
|
|
10861
10865
|
}
|
|
10862
10866
|
|
|
10863
|
-
this.querySelectorAll("fig-
|
|
10867
|
+
this.querySelectorAll("fig-swatch[data-generated]").forEach((el) => el.remove());
|
|
10864
10868
|
this.#ensurePreviewElement();
|
|
10865
10869
|
this.#ensureMediaElement();
|
|
10866
10870
|
this.#syncGeneratedMediaElement();
|
|
@@ -14707,8 +14711,8 @@ customElements.define("fig-input-combo", FigInputCombo);
|
|
|
14707
14711
|
*/
|
|
14708
14712
|
class FigColorTip extends HTMLElement {
|
|
14709
14713
|
#fillPicker = null;
|
|
14710
|
-
#
|
|
14711
|
-
#
|
|
14714
|
+
#swatch = null;
|
|
14715
|
+
#swatchSelectedObserver = null;
|
|
14712
14716
|
#boundHandleInput = this.#handlePickerInput.bind(this);
|
|
14713
14717
|
#boundHandleChange = this.#handlePickerChange.bind(this);
|
|
14714
14718
|
|
|
@@ -14744,33 +14748,33 @@ class FigColorTip extends HTMLElement {
|
|
|
14744
14748
|
this.#fillPicker.removeEventListener("input", this.#boundHandleInput);
|
|
14745
14749
|
this.#fillPicker.removeEventListener("change", this.#boundHandleChange);
|
|
14746
14750
|
}
|
|
14747
|
-
if (this.#
|
|
14748
|
-
this.#
|
|
14749
|
-
this.#
|
|
14751
|
+
if (this.#swatch) {
|
|
14752
|
+
this.#swatch.removeEventListener("input", this.#boundHandleInput);
|
|
14753
|
+
this.#swatch.removeEventListener("change", this.#boundHandleChange);
|
|
14750
14754
|
}
|
|
14751
|
-
if (this.#
|
|
14752
|
-
this.#
|
|
14753
|
-
this.#
|
|
14755
|
+
if (this.#swatchSelectedObserver) {
|
|
14756
|
+
this.#swatchSelectedObserver.disconnect();
|
|
14757
|
+
this.#swatchSelectedObserver = null;
|
|
14754
14758
|
}
|
|
14755
14759
|
}
|
|
14756
14760
|
|
|
14757
|
-
#
|
|
14758
|
-
if (this.#
|
|
14759
|
-
this.#
|
|
14760
|
-
this.#
|
|
14761
|
+
#observeSwatchSelected() {
|
|
14762
|
+
if (this.#swatchSelectedObserver) {
|
|
14763
|
+
this.#swatchSelectedObserver.disconnect();
|
|
14764
|
+
this.#swatchSelectedObserver = null;
|
|
14761
14765
|
}
|
|
14762
|
-
if (!this.#
|
|
14763
|
-
this.#
|
|
14764
|
-
const
|
|
14765
|
-
this.#
|
|
14766
|
-
this.#
|
|
14767
|
-
if (
|
|
14766
|
+
if (!this.#swatch) return;
|
|
14767
|
+
this.#swatchSelectedObserver = new MutationObserver(() => {
|
|
14768
|
+
const swatchSelected =
|
|
14769
|
+
this.#swatch?.hasAttribute("selected") &&
|
|
14770
|
+
this.#swatch.getAttribute("selected") !== "false";
|
|
14771
|
+
if (swatchSelected) {
|
|
14768
14772
|
if (!this.hasAttribute("selected")) this.setAttribute("selected", "");
|
|
14769
14773
|
} else if (this.hasAttribute("selected")) {
|
|
14770
14774
|
this.removeAttribute("selected");
|
|
14771
14775
|
}
|
|
14772
14776
|
});
|
|
14773
|
-
this.#
|
|
14777
|
+
this.#swatchSelectedObserver.observe(this.#swatch, {
|
|
14774
14778
|
attributes: true,
|
|
14775
14779
|
attributeFilter: ["selected"],
|
|
14776
14780
|
});
|
|
@@ -14788,7 +14792,7 @@ class FigColorTip extends HTMLElement {
|
|
|
14788
14792
|
const label = this.getAttribute("aria-label") || (mode === "add" ? "Add color stop" : "Remove color stop");
|
|
14789
14793
|
this.innerHTML = `<fig-button icon variant="ghost" aria-label="${label}"><fig-icon name="${iconName}"></fig-icon></fig-button>`;
|
|
14790
14794
|
this.#fillPicker = null;
|
|
14791
|
-
this.#
|
|
14795
|
+
this.#swatch = null;
|
|
14792
14796
|
this.addEventListener("click", this.#handleControlClick);
|
|
14793
14797
|
this.#syncA11y();
|
|
14794
14798
|
return;
|
|
@@ -14807,23 +14811,23 @@ class FigColorTip extends HTMLElement {
|
|
|
14807
14811
|
opacity: Math.round(alpha * 100),
|
|
14808
14812
|
})
|
|
14809
14813
|
: JSON.stringify({ type: "solid", color });
|
|
14810
|
-
const
|
|
14814
|
+
const swatchAlphaAttr = alpha < 1 ? ` alpha="${alpha}"` : "";
|
|
14811
14815
|
this.innerHTML = hasFigFillPicker()
|
|
14812
14816
|
? `<fig-fill-picker mode="solid" ${alphaAttr} value='${pickerValue}'>
|
|
14813
|
-
<fig-
|
|
14817
|
+
<fig-swatch background="${color}"${swatchAlphaAttr}></fig-swatch>
|
|
14814
14818
|
</fig-fill-picker>`
|
|
14815
|
-
: `<fig-
|
|
14819
|
+
: `<fig-swatch background="${color}"${swatchAlphaAttr}></fig-swatch>`;
|
|
14816
14820
|
|
|
14817
14821
|
this.#fillPicker = this.querySelector("fig-fill-picker");
|
|
14818
|
-
this.#
|
|
14822
|
+
this.#swatch = this.querySelector("fig-swatch");
|
|
14819
14823
|
this.#teardownListeners();
|
|
14820
14824
|
this.#fillPicker?.addEventListener("input", this.#boundHandleInput);
|
|
14821
14825
|
this.#fillPicker?.addEventListener("change", this.#boundHandleChange);
|
|
14822
14826
|
if (!this.#fillPicker) {
|
|
14823
|
-
this.#
|
|
14824
|
-
this.#
|
|
14827
|
+
this.#swatch?.addEventListener("input", this.#boundHandleInput);
|
|
14828
|
+
this.#swatch?.addEventListener("change", this.#boundHandleChange);
|
|
14825
14829
|
}
|
|
14826
|
-
this.#
|
|
14830
|
+
this.#observeSwatchSelected();
|
|
14827
14831
|
this.#syncA11y();
|
|
14828
14832
|
}
|
|
14829
14833
|
|
|
@@ -14938,18 +14942,18 @@ class FigColorTip extends HTMLElement {
|
|
|
14938
14942
|
}
|
|
14939
14943
|
}
|
|
14940
14944
|
|
|
14941
|
-
if (this.#
|
|
14945
|
+
if (this.#swatch) {
|
|
14942
14946
|
this.#syncA11y();
|
|
14943
|
-
this.#
|
|
14947
|
+
this.#swatch.setAttribute("background", color);
|
|
14944
14948
|
if (alpha < 1) {
|
|
14945
|
-
this.#
|
|
14949
|
+
this.#swatch.setAttribute("alpha", String(alpha));
|
|
14946
14950
|
} else {
|
|
14947
|
-
this.#
|
|
14951
|
+
this.#swatch.removeAttribute("alpha");
|
|
14948
14952
|
}
|
|
14949
14953
|
if (this.hasAttribute("disabled")) {
|
|
14950
|
-
this.#
|
|
14954
|
+
this.#swatch.setAttribute("disabled", "");
|
|
14951
14955
|
} else {
|
|
14952
|
-
this.#
|
|
14956
|
+
this.#swatch.removeAttribute("disabled");
|
|
14953
14957
|
}
|
|
14954
14958
|
}
|
|
14955
14959
|
}
|
|
@@ -14971,7 +14975,7 @@ class FigColorTip extends HTMLElement {
|
|
|
14971
14975
|
return;
|
|
14972
14976
|
}
|
|
14973
14977
|
|
|
14974
|
-
const target = this.#fillPicker || this.#
|
|
14978
|
+
const target = this.#fillPicker || this.#swatch;
|
|
14975
14979
|
if (!target) return;
|
|
14976
14980
|
const label = this.getAttribute("aria-label") || "Color stop";
|
|
14977
14981
|
const labelledBy = this.getAttribute("aria-labelledby");
|
|
@@ -16706,20 +16710,23 @@ customElements.define("fig-menu-separator", FigMenuSeparator);
|
|
|
16706
16710
|
class FigMenu extends HTMLElement {
|
|
16707
16711
|
#popup = null;
|
|
16708
16712
|
#trigger = null;
|
|
16713
|
+
#virtualAnchor = null;
|
|
16709
16714
|
#observer = null;
|
|
16710
16715
|
#boundTriggerClick;
|
|
16716
|
+
#boundTriggerContextMenu;
|
|
16711
16717
|
#boundPopupClick;
|
|
16712
16718
|
#boundMenuKeydown;
|
|
16713
16719
|
#boundPopupClose;
|
|
16714
16720
|
#focusedIndex = -1;
|
|
16715
16721
|
|
|
16716
16722
|
static get observedAttributes() {
|
|
16717
|
-
return ["position", "offset", "closedby", "disabled", "open"];
|
|
16723
|
+
return ["position", "offset", "closedby", "disabled", "open", "trigger"];
|
|
16718
16724
|
}
|
|
16719
16725
|
|
|
16720
16726
|
constructor() {
|
|
16721
16727
|
super();
|
|
16722
16728
|
this.#boundTriggerClick = this.#handleTriggerClick.bind(this);
|
|
16729
|
+
this.#boundTriggerContextMenu = this.#handleTriggerContextMenu.bind(this);
|
|
16723
16730
|
this.#boundPopupClick = this.#handlePopupClick.bind(this);
|
|
16724
16731
|
this.#boundMenuKeydown = this.#handleMenuKeydown.bind(this);
|
|
16725
16732
|
this.#boundPopupClose = this.#handlePopupClose.bind(this);
|
|
@@ -16810,6 +16817,11 @@ class FigMenu extends HTMLElement {
|
|
|
16810
16817
|
this.querySelector(":scope > :not(fig-menu-item):not(fig-menu-separator)");
|
|
16811
16818
|
}
|
|
16812
16819
|
|
|
16820
|
+
#usesContextMenuTrigger() {
|
|
16821
|
+
const trigger = (this.getAttribute("trigger") || "").toLowerCase();
|
|
16822
|
+
return trigger === "contextmenu" || this.hasAttribute("contextmenu");
|
|
16823
|
+
}
|
|
16824
|
+
|
|
16813
16825
|
#createPopup() {
|
|
16814
16826
|
this.#popup = document.createElement("dialog", { is: "fig-popup" });
|
|
16815
16827
|
this.#popup.setAttribute("is", "fig-popup");
|
|
@@ -16847,6 +16859,7 @@ class FigMenu extends HTMLElement {
|
|
|
16847
16859
|
this.addEventListener("keydown", this.#boundMenuKeydown);
|
|
16848
16860
|
if (this.#trigger) {
|
|
16849
16861
|
this.#trigger.addEventListener("click", this.#boundTriggerClick);
|
|
16862
|
+
this.#trigger.addEventListener("contextmenu", this.#boundTriggerContextMenu);
|
|
16850
16863
|
this.#trigger.setAttribute("aria-haspopup", "menu");
|
|
16851
16864
|
this.#trigger.setAttribute("aria-expanded", "false");
|
|
16852
16865
|
this.#trigger.setAttribute("aria-controls", this.#popup.getAttribute("id"));
|
|
@@ -16861,6 +16874,7 @@ class FigMenu extends HTMLElement {
|
|
|
16861
16874
|
this.removeEventListener("keydown", this.#boundMenuKeydown);
|
|
16862
16875
|
if (this.#trigger) {
|
|
16863
16876
|
this.#trigger.removeEventListener("click", this.#boundTriggerClick);
|
|
16877
|
+
this.#trigger.removeEventListener("contextmenu", this.#boundTriggerContextMenu);
|
|
16864
16878
|
}
|
|
16865
16879
|
if (this.#popup) {
|
|
16866
16880
|
this.#popup.removeEventListener("click", this.#boundPopupClick);
|
|
@@ -16882,6 +16896,7 @@ class FigMenu extends HTMLElement {
|
|
|
16882
16896
|
this.#detectTrigger();
|
|
16883
16897
|
if (this.#trigger) {
|
|
16884
16898
|
this.#trigger.addEventListener("click", this.#boundTriggerClick);
|
|
16899
|
+
this.#trigger.addEventListener("contextmenu", this.#boundTriggerContextMenu);
|
|
16885
16900
|
this.#trigger.setAttribute("aria-haspopup", "menu");
|
|
16886
16901
|
this.#trigger.setAttribute("aria-expanded", "false");
|
|
16887
16902
|
this.#trigger.setAttribute("aria-controls", this.#popup.getAttribute("id"));
|
|
@@ -16938,6 +16953,7 @@ class FigMenu extends HTMLElement {
|
|
|
16938
16953
|
}
|
|
16939
16954
|
|
|
16940
16955
|
#handleTriggerClick(e) {
|
|
16956
|
+
if (this.#usesContextMenuTrigger()) return;
|
|
16941
16957
|
if (this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false") return;
|
|
16942
16958
|
e.stopPropagation();
|
|
16943
16959
|
const popupShowing = this.#popup?.matches?.(":open") ?? false;
|
|
@@ -16948,10 +16964,40 @@ class FigMenu extends HTMLElement {
|
|
|
16948
16964
|
if (effectiveOpen) {
|
|
16949
16965
|
this.open = false;
|
|
16950
16966
|
} else {
|
|
16967
|
+
if (this.#popup && this.#trigger) {
|
|
16968
|
+
this.#popup.anchor = this.#trigger;
|
|
16969
|
+
}
|
|
16951
16970
|
this.open = true;
|
|
16952
16971
|
}
|
|
16953
16972
|
}
|
|
16954
16973
|
|
|
16974
|
+
#handleTriggerContextMenu(e) {
|
|
16975
|
+
if (!this.#usesContextMenuTrigger()) return;
|
|
16976
|
+
if (this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false") return;
|
|
16977
|
+
e.preventDefault();
|
|
16978
|
+
e.stopPropagation();
|
|
16979
|
+
this.#showAtAfterPointerRelease(e.clientX, e.clientY);
|
|
16980
|
+
}
|
|
16981
|
+
|
|
16982
|
+
#showAtAfterPointerRelease(x, y) {
|
|
16983
|
+
let opened = false;
|
|
16984
|
+
let fallbackTimer = 0;
|
|
16985
|
+
const openMenu = () => {
|
|
16986
|
+
if (opened) return;
|
|
16987
|
+
opened = true;
|
|
16988
|
+
window.clearTimeout(fallbackTimer);
|
|
16989
|
+
window.removeEventListener("pointerup", openMenu, true);
|
|
16990
|
+
window.removeEventListener("pointercancel", openMenu, true);
|
|
16991
|
+
requestAnimationFrame(() => this.showAt(x, y));
|
|
16992
|
+
};
|
|
16993
|
+
window.addEventListener("pointerup", openMenu, { once: true, capture: true });
|
|
16994
|
+
window.addEventListener("pointercancel", openMenu, {
|
|
16995
|
+
once: true,
|
|
16996
|
+
capture: true,
|
|
16997
|
+
});
|
|
16998
|
+
fallbackTimer = window.setTimeout(openMenu, 180);
|
|
16999
|
+
}
|
|
17000
|
+
|
|
16955
17001
|
#handlePopupClick(e) {
|
|
16956
17002
|
const item = e.target.closest("fig-menu-item");
|
|
16957
17003
|
if (!item) return;
|
|
@@ -16969,6 +17015,9 @@ class FigMenu extends HTMLElement {
|
|
|
16969
17015
|
(e.key === "ArrowDown" || e.key === "Enter" || e.key === " ")
|
|
16970
17016
|
) {
|
|
16971
17017
|
e.preventDefault();
|
|
17018
|
+
if (this.#popup && this.#trigger) {
|
|
17019
|
+
this.#popup.anchor = this.#trigger;
|
|
17020
|
+
}
|
|
16972
17021
|
this.open = true;
|
|
16973
17022
|
requestAnimationFrame(() => this.#focusItemAt(0));
|
|
16974
17023
|
}
|
|
@@ -17042,6 +17091,28 @@ class FigMenu extends HTMLElement {
|
|
|
17042
17091
|
this.open = false;
|
|
17043
17092
|
}
|
|
17044
17093
|
|
|
17094
|
+
showAt(x, y) {
|
|
17095
|
+
this.#virtualAnchor = {
|
|
17096
|
+
getBoundingClientRect: () => ({
|
|
17097
|
+
width: 0,
|
|
17098
|
+
height: 0,
|
|
17099
|
+
top: y,
|
|
17100
|
+
right: x,
|
|
17101
|
+
bottom: y,
|
|
17102
|
+
left: x,
|
|
17103
|
+
x,
|
|
17104
|
+
y,
|
|
17105
|
+
}),
|
|
17106
|
+
};
|
|
17107
|
+
if (this.#popup) {
|
|
17108
|
+
this.#popup.anchor = this.#virtualAnchor;
|
|
17109
|
+
}
|
|
17110
|
+
if (this.open) this.open = false;
|
|
17111
|
+
requestAnimationFrame(() => {
|
|
17112
|
+
this.open = true;
|
|
17113
|
+
});
|
|
17114
|
+
}
|
|
17115
|
+
|
|
17045
17116
|
#openMenu() {
|
|
17046
17117
|
if (!this.#popup) return;
|
|
17047
17118
|
this.#popup.open = true;
|
package/package.json
CHANGED