@rogieking/figui3 3.13.1 → 3.14.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/components.css +43 -23
- package/fig.js +415 -163
- package/package.json +1 -1
package/components.css
CHANGED
|
@@ -1204,10 +1204,8 @@ fig-chit {
|
|
|
1204
1204
|
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
1205
1205
|
}
|
|
1206
1206
|
|
|
1207
|
+
&[size="medium"],
|
|
1207
1208
|
&[size="large"] {
|
|
1208
|
-
--size: 1.75rem;
|
|
1209
|
-
|
|
1210
|
-
/* Large size: swatch fills the whole area */
|
|
1211
1209
|
input[type="color"] {
|
|
1212
1210
|
padding: 0;
|
|
1213
1211
|
width: var(--size);
|
|
@@ -1233,7 +1231,6 @@ fig-chit {
|
|
|
1233
1231
|
inset 0 0 0 3px var(--figma-color-bg);
|
|
1234
1232
|
}
|
|
1235
1233
|
|
|
1236
|
-
/* Large gradient/image: also fill the area */
|
|
1237
1234
|
&[data-type="gradient"]::after,
|
|
1238
1235
|
&[data-type="image"]::after,
|
|
1239
1236
|
&[data-type="gradient"]::before,
|
|
@@ -1244,6 +1241,14 @@ fig-chit {
|
|
|
1244
1241
|
}
|
|
1245
1242
|
}
|
|
1246
1243
|
|
|
1244
|
+
&[size="medium"] {
|
|
1245
|
+
--size: 1.5rem;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
&[size="large"] {
|
|
1249
|
+
--size: 2rem;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1247
1252
|
&[disabled] {
|
|
1248
1253
|
pointer-events: none;
|
|
1249
1254
|
}
|
|
@@ -3174,14 +3179,12 @@ fig-input-gradient {
|
|
|
3174
3179
|
}
|
|
3175
3180
|
fig-chit {
|
|
3176
3181
|
flex: 1 1 auto;
|
|
3177
|
-
width: 100
|
|
3178
|
-
min-width: 0;
|
|
3182
|
+
width: 100% !important;
|
|
3183
|
+
min-width: 0 !important;
|
|
3179
3184
|
&::before,
|
|
3180
3185
|
&::after {
|
|
3181
|
-
width:
|
|
3182
|
-
height: auto;
|
|
3186
|
+
width: 100% !important;
|
|
3183
3187
|
place-self: stretch;
|
|
3184
|
-
border-radius: var(--radius-large) !important;
|
|
3185
3188
|
}
|
|
3186
3189
|
&[data-type="gradient"]::after {
|
|
3187
3190
|
width: calc(100% - 0.625rem);
|
|
@@ -3193,12 +3196,18 @@ fig-input-gradient {
|
|
|
3193
3196
|
|
|
3194
3197
|
.fig-input-gradient-track {
|
|
3195
3198
|
position: absolute;
|
|
3196
|
-
|
|
3199
|
+
display: flex;
|
|
3200
|
+
align-items: center;
|
|
3201
|
+
inset: 0;
|
|
3197
3202
|
pointer-events: auto;
|
|
3198
3203
|
|
|
3199
3204
|
fig-handle {
|
|
3200
3205
|
pointer-events: auto;
|
|
3201
3206
|
cursor: default;
|
|
3207
|
+
|
|
3208
|
+
&:hover {
|
|
3209
|
+
z-index: 5;
|
|
3210
|
+
}
|
|
3202
3211
|
}
|
|
3203
3212
|
}
|
|
3204
3213
|
}
|
|
@@ -4244,12 +4253,6 @@ fig-preview {
|
|
|
4244
4253
|
}
|
|
4245
4254
|
|
|
4246
4255
|
.fig-fill-picker-color-area fig-handle {
|
|
4247
|
-
--width: 1rem;
|
|
4248
|
-
--height: 1rem;
|
|
4249
|
-
--border-radius: 50%;
|
|
4250
|
-
--box-shadow:
|
|
4251
|
-
inset 0 0 0 0.125rem var(--handle-color),
|
|
4252
|
-
0px 0 0 0.5px rgba(0, 0, 0, 0.1), var(--elevation-100-canvas);
|
|
4253
4256
|
z-index: 1;
|
|
4254
4257
|
}
|
|
4255
4258
|
|
|
@@ -4743,8 +4746,8 @@ fig-choice {
|
|
|
4743
4746
|
}
|
|
4744
4747
|
|
|
4745
4748
|
fig-handle {
|
|
4746
|
-
--width: 0.
|
|
4747
|
-
--height: 0.
|
|
4749
|
+
--width: 0.875rem;
|
|
4750
|
+
--height: 0.875rem;
|
|
4748
4751
|
--fill: var(--figma-color-bg-brand);
|
|
4749
4752
|
--border-radius: 50%;
|
|
4750
4753
|
--ring-width: 1.25px;
|
|
@@ -4754,15 +4757,27 @@ fig-handle {
|
|
|
4754
4757
|
--outline: none;
|
|
4755
4758
|
--border: none;
|
|
4756
4759
|
|
|
4757
|
-
display: inline-
|
|
4760
|
+
display: inline-grid;
|
|
4761
|
+
place-items: center;
|
|
4758
4762
|
width: var(--width);
|
|
4759
4763
|
height: var(--height);
|
|
4760
|
-
background: var(--
|
|
4764
|
+
background: var(--handle-color);
|
|
4761
4765
|
border-radius: var(--border-radius);
|
|
4762
4766
|
box-shadow: var(--box-shadow);
|
|
4763
4767
|
outline: var(--outline);
|
|
4764
4768
|
border: var(--border);
|
|
4765
4769
|
|
|
4770
|
+
&::before {
|
|
4771
|
+
content: "";
|
|
4772
|
+
color-scheme: light only;
|
|
4773
|
+
width: calc(var(--width) - 4px);
|
|
4774
|
+
height: calc(var(--height) - 4px);
|
|
4775
|
+
background: var(--fill);
|
|
4776
|
+
border-radius: var(--border-radius);
|
|
4777
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-bordertranslucent);
|
|
4778
|
+
place-self: center;
|
|
4779
|
+
}
|
|
4780
|
+
|
|
4766
4781
|
&[size="small"] {
|
|
4767
4782
|
--width: 0.5625rem;
|
|
4768
4783
|
--height: 0.5625rem;
|
|
@@ -4772,10 +4787,10 @@ fig-handle {
|
|
|
4772
4787
|
position: absolute;
|
|
4773
4788
|
touch-action: none;
|
|
4774
4789
|
}
|
|
4775
|
-
|
|
4790
|
+
&:hover,
|
|
4776
4791
|
&[selected]:not([selected="false"]) {
|
|
4777
4792
|
outline: var(--ring-width) solid var(--figma-color-border-selected);
|
|
4778
|
-
outline-offset:
|
|
4793
|
+
outline-offset: 0;
|
|
4779
4794
|
}
|
|
4780
4795
|
|
|
4781
4796
|
&[disabled]:not([disabled="false"]),
|
|
@@ -4786,7 +4801,7 @@ fig-handle {
|
|
|
4786
4801
|
}
|
|
4787
4802
|
|
|
4788
4803
|
&[type="color"],
|
|
4789
|
-
&[
|
|
4804
|
+
&[control] {
|
|
4790
4805
|
overflow: visible;
|
|
4791
4806
|
|
|
4792
4807
|
fig-color-tip {
|
|
@@ -4823,6 +4838,11 @@ fig-color-tip {
|
|
|
4823
4838
|
drop-shadow(0px 2.5px 6px rgba(0, 0, 0, 0.13))
|
|
4824
4839
|
drop-shadow(0px 0px 0.5px rgba(0, 0, 0, 0.15));
|
|
4825
4840
|
|
|
4841
|
+
&[control="add"],
|
|
4842
|
+
&[control="remove"] {
|
|
4843
|
+
cursor: pointer;
|
|
4844
|
+
}
|
|
4845
|
+
|
|
4826
4846
|
fig-chit {
|
|
4827
4847
|
input[type="color"] {
|
|
4828
4848
|
background: transparent;
|
package/fig.js
CHANGED
|
@@ -591,6 +591,7 @@ class FigTooltip extends HTMLElement {
|
|
|
591
591
|
this.#stopObserving();
|
|
592
592
|
if (this.popup) {
|
|
593
593
|
this.popup.remove();
|
|
594
|
+
this.popup = null;
|
|
594
595
|
}
|
|
595
596
|
// Remove the click outside listener if it was added
|
|
596
597
|
if (this.action === "click") {
|
|
@@ -659,7 +660,12 @@ class FigTooltip extends HTMLElement {
|
|
|
659
660
|
};
|
|
660
661
|
}
|
|
661
662
|
|
|
663
|
+
get #showPersisted() {
|
|
664
|
+
return this.hasAttribute("show") && this.getAttribute("show") !== "false";
|
|
665
|
+
}
|
|
666
|
+
|
|
662
667
|
showDelayedPopup() {
|
|
668
|
+
if (this.#showPersisted) return;
|
|
663
669
|
this.render();
|
|
664
670
|
clearTimeout(this.timeout);
|
|
665
671
|
const warm =
|
|
@@ -669,10 +675,12 @@ class FigTooltip extends HTMLElement {
|
|
|
669
675
|
}
|
|
670
676
|
|
|
671
677
|
showPopup() {
|
|
678
|
+
if (!this.popup) this.render();
|
|
679
|
+
this.popup.style.display = "block";
|
|
680
|
+
this.popup.style.visibility = "hidden";
|
|
672
681
|
this.#repositionPopup();
|
|
673
682
|
this.popup.style.opacity = "1";
|
|
674
683
|
this.popup.style.visibility = "visible";
|
|
675
|
-
this.popup.style.display = "block";
|
|
676
684
|
this.popup.style.pointerEvents = "all";
|
|
677
685
|
this.popup.style.zIndex = figGetHighestZIndex() + 1;
|
|
678
686
|
|
|
@@ -725,6 +733,7 @@ class FigTooltip extends HTMLElement {
|
|
|
725
733
|
}
|
|
726
734
|
|
|
727
735
|
hidePopup() {
|
|
736
|
+
if (this.#showPersisted) return;
|
|
728
737
|
clearTimeout(this.timeout);
|
|
729
738
|
clearTimeout(this.#touchTimeout);
|
|
730
739
|
this.#stopObserving();
|
|
@@ -824,7 +833,28 @@ class FigTooltip extends HTMLElement {
|
|
|
824
833
|
}
|
|
825
834
|
|
|
826
835
|
static get observedAttributes() {
|
|
827
|
-
return ["action", "delay", "open"];
|
|
836
|
+
return ["action", "delay", "open", "show", "text"];
|
|
837
|
+
}
|
|
838
|
+
get text() {
|
|
839
|
+
return this.getAttribute("text") ?? "";
|
|
840
|
+
}
|
|
841
|
+
set text(value) {
|
|
842
|
+
this.setAttribute("text", value);
|
|
843
|
+
}
|
|
844
|
+
#updateText(value) {
|
|
845
|
+
if (!this.popup) return;
|
|
846
|
+
const content = this.popup.firstElementChild ?? this.popup.firstChild;
|
|
847
|
+
if (!content) return;
|
|
848
|
+
content.innerText = value;
|
|
849
|
+
content.style.width = "";
|
|
850
|
+
const textNode = content.childNodes[0];
|
|
851
|
+
if (textNode) {
|
|
852
|
+
const range = document.createRange();
|
|
853
|
+
range.setStartBefore(textNode);
|
|
854
|
+
range.setEndAfter(textNode);
|
|
855
|
+
content.style.width = `${range.getBoundingClientRect().width}px`;
|
|
856
|
+
}
|
|
857
|
+
if (this.isOpen) this.#repositionPopup();
|
|
828
858
|
}
|
|
829
859
|
get open() {
|
|
830
860
|
return this.hasAttribute("open") && this.getAttribute("open") === "true";
|
|
@@ -851,6 +881,17 @@ class FigTooltip extends HTMLElement {
|
|
|
851
881
|
});
|
|
852
882
|
}
|
|
853
883
|
}
|
|
884
|
+
if (name === "show") {
|
|
885
|
+
const on = newValue !== null && newValue !== "false";
|
|
886
|
+
if (on) {
|
|
887
|
+
this.showPopup();
|
|
888
|
+
} else {
|
|
889
|
+
this.hidePopup();
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
if (name === "text") {
|
|
893
|
+
this.#updateText(newValue ?? "");
|
|
894
|
+
}
|
|
854
895
|
}
|
|
855
896
|
|
|
856
897
|
#hideOnChromeOpen(e) {
|
|
@@ -5651,8 +5692,10 @@ customElements.define("fig-input-fill", FigInputFill);
|
|
|
5651
5692
|
* @fires change - When the gradient value is committed
|
|
5652
5693
|
*/
|
|
5653
5694
|
class FigInputGradient extends HTMLElement {
|
|
5654
|
-
#
|
|
5695
|
+
#chit;
|
|
5655
5696
|
#track;
|
|
5697
|
+
#handleDragging = false;
|
|
5698
|
+
#arrowTooltipTimer = null;
|
|
5656
5699
|
#colorObserver = null;
|
|
5657
5700
|
#gradient = {
|
|
5658
5701
|
type: "linear",
|
|
@@ -5670,14 +5713,96 @@ class FigInputGradient extends HTMLElement {
|
|
|
5670
5713
|
}
|
|
5671
5714
|
|
|
5672
5715
|
static get observedAttributes() {
|
|
5673
|
-
return ["value", "disabled"
|
|
5716
|
+
return ["value", "disabled"];
|
|
5674
5717
|
}
|
|
5675
5718
|
|
|
5676
5719
|
connectedCallback() {
|
|
5677
5720
|
this.#parseValue();
|
|
5678
5721
|
this.#render();
|
|
5722
|
+
document.addEventListener("keydown", this.#onKeyDown);
|
|
5679
5723
|
}
|
|
5680
5724
|
|
|
5725
|
+
disconnectedCallback() {
|
|
5726
|
+
document.removeEventListener("keydown", this.#onKeyDown);
|
|
5727
|
+
}
|
|
5728
|
+
|
|
5729
|
+
#onKeyDown = (e) => {
|
|
5730
|
+
const active = document.activeElement;
|
|
5731
|
+
const isTyping =
|
|
5732
|
+
active &&
|
|
5733
|
+
(active.tagName === "INPUT" ||
|
|
5734
|
+
active.tagName === "TEXTAREA" ||
|
|
5735
|
+
active.isContentEditable);
|
|
5736
|
+
if (!this.#track) return;
|
|
5737
|
+
|
|
5738
|
+
if (e.key === "Tab" && !isTyping) {
|
|
5739
|
+
const selected = this.#track.querySelector(
|
|
5740
|
+
"fig-handle[selected]:not(.fig-input-gradient-ghost)",
|
|
5741
|
+
);
|
|
5742
|
+
if (!selected) return;
|
|
5743
|
+
e.preventDefault();
|
|
5744
|
+
const handles = [
|
|
5745
|
+
...this.#track.querySelectorAll(
|
|
5746
|
+
"fig-handle:not(.fig-input-gradient-ghost)",
|
|
5747
|
+
),
|
|
5748
|
+
];
|
|
5749
|
+
const curIdx = handles.indexOf(selected);
|
|
5750
|
+
const next = e.shiftKey
|
|
5751
|
+
? (curIdx - 1 + handles.length) % handles.length
|
|
5752
|
+
: (curIdx + 1) % handles.length;
|
|
5753
|
+
selected.deselect();
|
|
5754
|
+
handles[next].select();
|
|
5755
|
+
return;
|
|
5756
|
+
}
|
|
5757
|
+
|
|
5758
|
+
if ((e.key === "ArrowLeft" || e.key === "ArrowRight") && !isTyping) {
|
|
5759
|
+
const selected = this.#track.querySelector(
|
|
5760
|
+
"fig-handle[selected]:not(.fig-input-gradient-ghost)",
|
|
5761
|
+
);
|
|
5762
|
+
if (!selected) return;
|
|
5763
|
+
const idx = parseInt(selected.dataset.stopIndex, 10);
|
|
5764
|
+
if (isNaN(idx) || !this.#gradient.stops[idx]) return;
|
|
5765
|
+
e.preventDefault();
|
|
5766
|
+
const delta = (e.key === "ArrowRight" ? 1 : -1) * (e.shiftKey ? 10 : 1);
|
|
5767
|
+
const stop = this.#gradient.stops[idx];
|
|
5768
|
+
stop.position = Math.max(0, Math.min(100, stop.position + delta));
|
|
5769
|
+
selected.setAttribute("value", `${stop.position}% 50%`);
|
|
5770
|
+
const tip = selected.closest("fig-tooltip");
|
|
5771
|
+
if (tip) {
|
|
5772
|
+
tip.text = `${Math.round(stop.position)}%`;
|
|
5773
|
+
tip.setAttribute("show", "true");
|
|
5774
|
+
tip.showPopup();
|
|
5775
|
+
selected.hideColorTip();
|
|
5776
|
+
clearTimeout(this.#arrowTooltipTimer);
|
|
5777
|
+
this.#arrowTooltipTimer = setTimeout(() => {
|
|
5778
|
+
tip.removeAttribute("show");
|
|
5779
|
+
selected.showColorTip();
|
|
5780
|
+
}, 600);
|
|
5781
|
+
}
|
|
5782
|
+
this.#syncChit();
|
|
5783
|
+
this.#emitInput();
|
|
5784
|
+
this.#emitChange();
|
|
5785
|
+
return;
|
|
5786
|
+
}
|
|
5787
|
+
|
|
5788
|
+
if (e.key !== "Delete" && e.key !== "Backspace") return;
|
|
5789
|
+
if (isTyping) return;
|
|
5790
|
+
if (this.#gradient.stops.length <= 2) return;
|
|
5791
|
+
const selected = this.#track.querySelector(
|
|
5792
|
+
"fig-handle[selected]:not(.fig-input-gradient-ghost)",
|
|
5793
|
+
);
|
|
5794
|
+
if (!selected) return;
|
|
5795
|
+
const idx = parseInt(selected.dataset.stopIndex, 10);
|
|
5796
|
+
if (isNaN(idx) || !this.#gradient.stops[idx]) return;
|
|
5797
|
+
e.preventDefault();
|
|
5798
|
+
selected.removeAttribute("selected");
|
|
5799
|
+
this.#gradient.stops.splice(idx, 1);
|
|
5800
|
+
this.#syncHandles();
|
|
5801
|
+
this.#syncChit();
|
|
5802
|
+
this.#emitInput();
|
|
5803
|
+
this.#emitChange();
|
|
5804
|
+
};
|
|
5805
|
+
|
|
5681
5806
|
#parseValue() {
|
|
5682
5807
|
const valueAttr = this.getAttribute("value");
|
|
5683
5808
|
if (!valueAttr) return;
|
|
@@ -5701,19 +5826,12 @@ class FigInputGradient extends HTMLElement {
|
|
|
5701
5826
|
}
|
|
5702
5827
|
}
|
|
5703
5828
|
|
|
5704
|
-
#
|
|
5705
|
-
const
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
attrs[name.slice(7)] = value;
|
|
5711
|
-
}
|
|
5712
|
-
}
|
|
5713
|
-
if (!attrs["dialog-position"]) attrs["dialog-position"] = "left";
|
|
5714
|
-
return Object.entries(attrs)
|
|
5715
|
-
.map(([k, v]) => `${k}="${v}"`)
|
|
5716
|
-
.join(" ");
|
|
5829
|
+
#buildGradientCSS() {
|
|
5830
|
+
const sorted = [...this.#gradient.stops].sort(
|
|
5831
|
+
(a, b) => a.position - b.position,
|
|
5832
|
+
);
|
|
5833
|
+
const stops = sorted.map((s) => `${s.color} ${s.position}%`).join(", ");
|
|
5834
|
+
return `linear-gradient(${this.#gradient.angle}deg, ${stops})`;
|
|
5717
5835
|
}
|
|
5718
5836
|
|
|
5719
5837
|
#buildStopHandles() {
|
|
@@ -5721,23 +5839,19 @@ class FigInputGradient extends HTMLElement {
|
|
|
5721
5839
|
return this.#gradient.stops
|
|
5722
5840
|
.map(
|
|
5723
5841
|
(stop, i) =>
|
|
5724
|
-
`<fig-handle drag drag-axes="x" type="color" color="${stop.color}" value="${stop.position}% 50%" data-stop-index="${i}"${disabled ? " disabled" : ""}></fig-handle>`,
|
|
5842
|
+
`<fig-tooltip action="manual" text="${Math.round(stop.position)}%"><fig-handle drag drag-axes="x" drag-surface=".fig-input-gradient-track" type="color" color="${stop.color}" value="${stop.position}% 50%" data-stop-index="${i}"${disabled ? " disabled" : ""}></fig-handle></fig-tooltip>`,
|
|
5725
5843
|
)
|
|
5726
5844
|
.join("");
|
|
5727
5845
|
}
|
|
5728
5846
|
|
|
5729
5847
|
#ghostHandle = null;
|
|
5730
|
-
#ghostTooltip = null;
|
|
5731
5848
|
|
|
5732
5849
|
#render() {
|
|
5733
5850
|
const disabled = this.hasAttribute("disabled");
|
|
5734
|
-
const fillPickerValue = JSON.stringify(this.value);
|
|
5735
|
-
const fpAttrs = this.#buildFillPickerAttrs();
|
|
5736
5851
|
this.innerHTML = `
|
|
5737
|
-
<fig-
|
|
5738
|
-
disabled ? "disabled" : ""
|
|
5739
|
-
}></fig-fill-picker>
|
|
5852
|
+
<fig-chit size="medium" background="${this.#buildGradientCSS()}"${disabled ? " disabled" : ""}></fig-chit>
|
|
5740
5853
|
<div class="fig-input-gradient-track">${this.#buildStopHandles()}</div>`;
|
|
5854
|
+
this.#chit = this.querySelector("fig-chit");
|
|
5741
5855
|
this.#track = this.querySelector(".fig-input-gradient-track");
|
|
5742
5856
|
this.#setupGhostHandle();
|
|
5743
5857
|
this.#setupEventListeners();
|
|
@@ -5768,22 +5882,31 @@ class FigInputGradient extends HTMLElement {
|
|
|
5768
5882
|
|
|
5769
5883
|
const ghost = document.createElement("fig-handle");
|
|
5770
5884
|
ghost.classList.add("fig-input-gradient-ghost");
|
|
5771
|
-
ghost.setAttribute("add", "");
|
|
5772
5885
|
ghost.style.position = "absolute";
|
|
5773
5886
|
ghost.style.top = "50%";
|
|
5774
5887
|
ghost.style.transform = "translate(-50%, -50%)";
|
|
5775
5888
|
ghost.style.pointerEvents = "none";
|
|
5776
5889
|
ghost.style.opacity = "0";
|
|
5777
5890
|
ghost.style.transition = "opacity 0.15s";
|
|
5891
|
+
ghost.style.overflow = "visible";
|
|
5892
|
+
|
|
5893
|
+
const tip = document.createElement("fig-color-tip");
|
|
5894
|
+
tip.setAttribute("control", "add");
|
|
5895
|
+
tip.style.position = "absolute";
|
|
5896
|
+
tip.style.bottom = "calc(100% + 6px)";
|
|
5897
|
+
tip.style.left = "50%";
|
|
5898
|
+
tip.style.transform = "translateX(-50%)";
|
|
5899
|
+
tip.style.zIndex = "10";
|
|
5900
|
+
ghost.appendChild(tip);
|
|
5778
5901
|
|
|
5779
5902
|
this.#track.appendChild(ghost);
|
|
5780
5903
|
this.#ghostHandle = ghost;
|
|
5781
|
-
this.#ghostTooltip = null;
|
|
5782
5904
|
|
|
5783
5905
|
this.addEventListener("pointerenter", this.#onTrackEnter);
|
|
5784
5906
|
this.addEventListener("pointermove", this.#onTrackMove);
|
|
5785
5907
|
this.addEventListener("pointerleave", this.#onTrackLeave);
|
|
5786
5908
|
this.addEventListener("click", this.#onTrackClick);
|
|
5909
|
+
this.addEventListener("dblclick", this.#onTrackDblClick);
|
|
5787
5910
|
}
|
|
5788
5911
|
|
|
5789
5912
|
#showGhost() {
|
|
@@ -5797,6 +5920,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
5797
5920
|
}
|
|
5798
5921
|
|
|
5799
5922
|
#onTrackEnter = () => {
|
|
5923
|
+
if (this.#handleDragging) return;
|
|
5800
5924
|
this.#showGhost();
|
|
5801
5925
|
};
|
|
5802
5926
|
|
|
@@ -5805,6 +5929,10 @@ class FigInputGradient extends HTMLElement {
|
|
|
5805
5929
|
};
|
|
5806
5930
|
|
|
5807
5931
|
#onTrackMove = (e) => {
|
|
5932
|
+
if (this.#handleDragging) {
|
|
5933
|
+
this.#hideGhost();
|
|
5934
|
+
return;
|
|
5935
|
+
}
|
|
5808
5936
|
if (!this.#ghostHandle || !this.#track) return;
|
|
5809
5937
|
if (e.target.closest("fig-handle:not(.fig-input-gradient-ghost)")) {
|
|
5810
5938
|
this.#hideGhost();
|
|
@@ -5821,9 +5949,37 @@ class FigInputGradient extends HTMLElement {
|
|
|
5821
5949
|
this.#showGhost();
|
|
5822
5950
|
};
|
|
5823
5951
|
|
|
5952
|
+
#distributeStops() {
|
|
5953
|
+
const count = this.#gradient.stops.length;
|
|
5954
|
+
if (count < 2) return;
|
|
5955
|
+
for (let i = 0; i < count; i++) {
|
|
5956
|
+
this.#gradient.stops[i].position = Math.round((i / (count - 1)) * 100);
|
|
5957
|
+
}
|
|
5958
|
+
this.#syncHandles();
|
|
5959
|
+
this.#syncChit();
|
|
5960
|
+
this.#emitInput();
|
|
5961
|
+
this.#emitChange();
|
|
5962
|
+
this.#track?.querySelectorAll("fig-handle[selected]").forEach((h) => {
|
|
5963
|
+
h.removeAttribute("selected");
|
|
5964
|
+
});
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5967
|
+
#onTrackDblClick = (e) => {
|
|
5968
|
+
if (!this.#track) return;
|
|
5969
|
+
if (!e.target.closest("fig-handle:not(.fig-input-gradient-ghost)")) return;
|
|
5970
|
+
this.#distributeStops();
|
|
5971
|
+
};
|
|
5972
|
+
|
|
5824
5973
|
#onTrackClick = (e) => {
|
|
5825
5974
|
if (!this.#track) return;
|
|
5826
|
-
if (
|
|
5975
|
+
if (this.#handleDragging) return;
|
|
5976
|
+
if (e.target.closest("fig-handle:not(.fig-input-gradient-ghost)")) {
|
|
5977
|
+
if (e.shiftKey) {
|
|
5978
|
+
this.#distributeStops();
|
|
5979
|
+
e.stopPropagation();
|
|
5980
|
+
}
|
|
5981
|
+
return;
|
|
5982
|
+
}
|
|
5827
5983
|
const trackRect = this.#track.getBoundingClientRect();
|
|
5828
5984
|
const pct = Math.max(
|
|
5829
5985
|
0,
|
|
@@ -5837,7 +5993,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
5837
5993
|
(s) => s.position === position && s.color === color,
|
|
5838
5994
|
);
|
|
5839
5995
|
this.#syncHandles();
|
|
5840
|
-
this.#
|
|
5996
|
+
this.#syncChit();
|
|
5841
5997
|
this.#emitInput();
|
|
5842
5998
|
this.#emitChange();
|
|
5843
5999
|
|
|
@@ -5870,6 +6026,8 @@ class FigInputGradient extends HTMLElement {
|
|
|
5870
6026
|
const stop = stops[i];
|
|
5871
6027
|
h.setAttribute("value", `${stop.position}% 50%`);
|
|
5872
6028
|
h.setAttribute("color", stop.color);
|
|
6029
|
+
const tip = h.closest("fig-tooltip");
|
|
6030
|
+
if (tip) tip.setAttribute("text", `${Math.round(stop.position)}%`);
|
|
5873
6031
|
}
|
|
5874
6032
|
}
|
|
5875
6033
|
|
|
@@ -5886,92 +6044,150 @@ class FigInputGradient extends HTMLElement {
|
|
|
5886
6044
|
});
|
|
5887
6045
|
}
|
|
5888
6046
|
|
|
5889
|
-
#
|
|
5890
|
-
if (!this.#
|
|
5891
|
-
this.#
|
|
6047
|
+
#syncStopIndices() {
|
|
6048
|
+
if (!this.#track) return;
|
|
6049
|
+
const handles = this.#track.querySelectorAll(
|
|
6050
|
+
"fig-handle:not(.fig-input-gradient-ghost)",
|
|
6051
|
+
);
|
|
6052
|
+
const stops = this.#gradient.stops;
|
|
6053
|
+
const used = new Set();
|
|
6054
|
+
handles.forEach((h) => {
|
|
6055
|
+
const pos = Math.round(parseFloat(h.getAttribute("value")) || 0);
|
|
6056
|
+
const color = (h.getAttribute("color") || "").toUpperCase();
|
|
6057
|
+
let best = -1;
|
|
6058
|
+
for (let i = 0; i < stops.length; i++) {
|
|
6059
|
+
if (used.has(i)) continue;
|
|
6060
|
+
if (
|
|
6061
|
+
stops[i].position === pos &&
|
|
6062
|
+
stops[i].color.toUpperCase() === color
|
|
6063
|
+
) {
|
|
6064
|
+
best = i;
|
|
6065
|
+
break;
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6068
|
+
if (best === -1) {
|
|
6069
|
+
let minDist = Infinity;
|
|
6070
|
+
for (let i = 0; i < stops.length; i++) {
|
|
6071
|
+
if (used.has(i)) continue;
|
|
6072
|
+
const d = Math.abs(stops[i].position - pos);
|
|
6073
|
+
if (d < minDist) {
|
|
6074
|
+
minDist = d;
|
|
6075
|
+
best = i;
|
|
6076
|
+
}
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
if (best !== -1) {
|
|
6080
|
+
used.add(best);
|
|
6081
|
+
h.dataset.stopIndex = best;
|
|
6082
|
+
}
|
|
6083
|
+
});
|
|
6084
|
+
}
|
|
6085
|
+
|
|
6086
|
+
#syncChit() {
|
|
6087
|
+
if (!this.#chit) return;
|
|
6088
|
+
this.#chit.setAttribute("background", this.#buildGradientCSS());
|
|
5892
6089
|
}
|
|
5893
6090
|
|
|
5894
6091
|
#setupEventListeners() {
|
|
5895
|
-
|
|
5896
|
-
this.#fillPicker = this.querySelector("fig-fill-picker");
|
|
5897
|
-
if (!this.#fillPicker) return;
|
|
6092
|
+
if (!this.#track) return;
|
|
5898
6093
|
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
6094
|
+
this.#track.addEventListener("input", (e) => {
|
|
6095
|
+
const handle = e.target.closest("fig-handle");
|
|
6096
|
+
if (!handle) return;
|
|
6097
|
+
e.stopPropagation();
|
|
6098
|
+
if (!this.#handleDragging) handle.style.zIndex = "5";
|
|
6099
|
+
this.#handleDragging = true;
|
|
6100
|
+
const idx = parseInt(handle.dataset.stopIndex, 10);
|
|
6101
|
+
if (isNaN(idx) || !this.#gradient.stops[idx]) return;
|
|
6102
|
+
const px = e.detail?.px ?? 0;
|
|
6103
|
+
const rawPosition = Math.round(px * 100);
|
|
6104
|
+
let position = rawPosition;
|
|
6105
|
+
const trackW = this.#track.getBoundingClientRect().width;
|
|
6106
|
+
if (e.detail?.shiftKey) {
|
|
6107
|
+
position = Math.round(position / 10) * 10;
|
|
5902
6108
|
} else {
|
|
5903
|
-
const
|
|
5904
|
-
|
|
6109
|
+
const snapPct = trackW > 0 ? (5 / trackW) * 100 : 0;
|
|
6110
|
+
for (let i = 0; i < this.#gradient.stops.length; i++) {
|
|
6111
|
+
if (i === idx) continue;
|
|
6112
|
+
if (
|
|
6113
|
+
Math.abs(this.#gradient.stops[i].position - position) <= snapPct
|
|
6114
|
+
) {
|
|
6115
|
+
position = this.#gradient.stops[i].position;
|
|
6116
|
+
break;
|
|
6117
|
+
}
|
|
6118
|
+
}
|
|
5905
6119
|
}
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
this.#emitInput();
|
|
6120
|
+
this.#gradient.stops[idx].position = position;
|
|
6121
|
+
if (position !== rawPosition) {
|
|
6122
|
+
handle.style.left = `${(position / 100) * trackW - handle.offsetWidth / 2}px`;
|
|
6123
|
+
}
|
|
6124
|
+
const tooltip = handle.closest("fig-tooltip");
|
|
6125
|
+
if (tooltip) {
|
|
6126
|
+
tooltip.text = `${Math.round(position)}%`;
|
|
6127
|
+
if (!tooltip.hasAttribute("show")) {
|
|
6128
|
+
tooltip.setAttribute("show", "true");
|
|
6129
|
+
handle.hideColorTip();
|
|
5917
6130
|
}
|
|
5918
|
-
}
|
|
6131
|
+
}
|
|
6132
|
+
this.#syncChit();
|
|
6133
|
+
this.#emitInput();
|
|
6134
|
+
});
|
|
5919
6135
|
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
6136
|
+
this.#track.addEventListener("change", (e) => {
|
|
6137
|
+
const handle = e.target.closest("fig-handle");
|
|
6138
|
+
if (!handle) return;
|
|
6139
|
+
e.stopPropagation();
|
|
6140
|
+
handle.style.zIndex = "";
|
|
6141
|
+
const tooltip = handle.closest("fig-tooltip");
|
|
6142
|
+
if (tooltip) tooltip.removeAttribute("show");
|
|
6143
|
+
handle.showColorTip();
|
|
6144
|
+
const idx = parseInt(handle.dataset.stopIndex, 10);
|
|
6145
|
+
if (isNaN(idx) || !this.#gradient.stops[idx]) return;
|
|
6146
|
+
const px = e.detail?.px ?? 0;
|
|
6147
|
+
let position = Math.round(px * 100);
|
|
6148
|
+
const trackW = this.#track.getBoundingClientRect().width;
|
|
6149
|
+
const snapPct = trackW > 0 ? (5 / trackW) * 100 : 0;
|
|
6150
|
+
for (let i = 0; i < this.#gradient.stops.length; i++) {
|
|
6151
|
+
if (i === idx) continue;
|
|
6152
|
+
if (Math.abs(this.#gradient.stops[i].position - position) <= snapPct) {
|
|
6153
|
+
position = this.#gradient.stops[i].position;
|
|
6154
|
+
break;
|
|
6155
|
+
}
|
|
6156
|
+
}
|
|
6157
|
+
this.#gradient.stops[idx].position = position;
|
|
6158
|
+
handle.style.left = `${(position / 100) * trackW - handle.offsetWidth / 2}px`;
|
|
6159
|
+
this.#gradient.stops.sort((a, b) => a.position - b.position);
|
|
6160
|
+
this.#syncStopIndices();
|
|
6161
|
+
this.#syncChit();
|
|
6162
|
+
this.#emitChange();
|
|
6163
|
+
requestAnimationFrame(() => {
|
|
6164
|
+
this.#handleDragging = false;
|
|
5923
6165
|
});
|
|
6166
|
+
});
|
|
5924
6167
|
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
this.#
|
|
6168
|
+
this.#colorObserver = new MutationObserver((mutations) => {
|
|
6169
|
+
for (const m of mutations) {
|
|
6170
|
+
if (m.attributeName !== "color") continue;
|
|
6171
|
+
const handle = m.target;
|
|
6172
|
+
if (handle.classList.contains("fig-input-gradient-ghost")) continue;
|
|
6173
|
+
const idx = parseInt(handle.dataset.stopIndex, 10);
|
|
6174
|
+
if (isNaN(idx) || !this.#gradient.stops[idx]) continue;
|
|
6175
|
+
const newColor = handle.getAttribute("color");
|
|
6176
|
+
if (newColor && newColor !== this.#gradient.stops[idx].color) {
|
|
6177
|
+
this.#gradient.stops[idx].color = newColor;
|
|
6178
|
+
this.#syncChit();
|
|
5935
6179
|
this.#emitInput();
|
|
5936
|
-
}
|
|
5937
|
-
|
|
5938
|
-
this.#track.addEventListener("change", (e) => {
|
|
5939
|
-
const handle = e.target.closest("fig-handle");
|
|
5940
|
-
if (!handle) return;
|
|
5941
|
-
e.stopPropagation();
|
|
5942
|
-
const idx = parseInt(handle.dataset.stopIndex, 10);
|
|
5943
|
-
if (isNaN(idx) || !this.#gradient.stops[idx]) return;
|
|
5944
|
-
const px = e.detail?.px ?? 0;
|
|
5945
|
-
this.#gradient.stops[idx].position = Math.round(px * 100);
|
|
5946
|
-
this.#syncFillPicker();
|
|
5947
|
-
this.#emitChange();
|
|
5948
|
-
});
|
|
5949
|
-
|
|
5950
|
-
this.#colorObserver = new MutationObserver((mutations) => {
|
|
5951
|
-
for (const m of mutations) {
|
|
5952
|
-
if (m.attributeName !== "color") continue;
|
|
5953
|
-
const handle = m.target;
|
|
5954
|
-
if (handle.classList.contains("fig-input-gradient-ghost")) continue;
|
|
5955
|
-
const idx = parseInt(handle.dataset.stopIndex, 10);
|
|
5956
|
-
if (isNaN(idx) || !this.#gradient.stops[idx]) continue;
|
|
5957
|
-
const newColor = handle.getAttribute("color");
|
|
5958
|
-
if (newColor && newColor !== this.#gradient.stops[idx].color) {
|
|
5959
|
-
this.#gradient.stops[idx].color = newColor;
|
|
5960
|
-
this.#syncFillPicker();
|
|
5961
|
-
this.#emitInput();
|
|
5962
|
-
}
|
|
5963
|
-
}
|
|
5964
|
-
});
|
|
5965
|
-
this.#track
|
|
5966
|
-
.querySelectorAll("fig-handle:not(.fig-input-gradient-ghost)")
|
|
5967
|
-
.forEach((h) => {
|
|
5968
|
-
this.#colorObserver.observe(h, {
|
|
5969
|
-
attributes: true,
|
|
5970
|
-
attributeFilter: ["color"],
|
|
5971
|
-
});
|
|
5972
|
-
});
|
|
6180
|
+
}
|
|
5973
6181
|
}
|
|
5974
6182
|
});
|
|
6183
|
+
this.#track
|
|
6184
|
+
.querySelectorAll("fig-handle:not(.fig-input-gradient-ghost)")
|
|
6185
|
+
.forEach((h) => {
|
|
6186
|
+
this.#colorObserver.observe(h, {
|
|
6187
|
+
attributes: true,
|
|
6188
|
+
attributeFilter: ["color"],
|
|
6189
|
+
});
|
|
6190
|
+
});
|
|
5975
6191
|
}
|
|
5976
6192
|
|
|
5977
6193
|
#emitInput() {
|
|
@@ -6012,15 +6228,11 @@ class FigInputGradient extends HTMLElement {
|
|
|
6012
6228
|
switch (name) {
|
|
6013
6229
|
case "value":
|
|
6014
6230
|
this.#parseValue();
|
|
6015
|
-
|
|
6016
|
-
this.#syncFillPicker();
|
|
6017
|
-
}
|
|
6231
|
+
this.#syncChit();
|
|
6018
6232
|
this.#syncHandles();
|
|
6019
6233
|
break;
|
|
6020
6234
|
case "disabled":
|
|
6021
|
-
|
|
6022
|
-
case "picker-anchor":
|
|
6023
|
-
if (this.#fillPicker) this.#render();
|
|
6235
|
+
this.#render();
|
|
6024
6236
|
break;
|
|
6025
6237
|
}
|
|
6026
6238
|
}
|
|
@@ -10295,6 +10507,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
10295
10507
|
drag
|
|
10296
10508
|
drag-surface=".fig-fill-picker-color-area"
|
|
10297
10509
|
drag-axes="x,y"
|
|
10510
|
+
drag-snapping="modifier"
|
|
10298
10511
|
></fig-handle>
|
|
10299
10512
|
</fig-preview>
|
|
10300
10513
|
<div class="fig-fill-picker-sliders">
|
|
@@ -11882,12 +12095,11 @@ class FigColorTip extends HTMLElement {
|
|
|
11882
12095
|
#boundHandleChange = this.#handlePickerChange.bind(this);
|
|
11883
12096
|
|
|
11884
12097
|
static get observedAttributes() {
|
|
11885
|
-
return ["value", "selected", "disabled", "alpha", "
|
|
12098
|
+
return ["value", "selected", "disabled", "alpha", "control"];
|
|
11886
12099
|
}
|
|
11887
12100
|
|
|
11888
|
-
get #
|
|
11889
|
-
|
|
11890
|
-
return v !== null && v !== "false";
|
|
12101
|
+
get #controlMode() {
|
|
12102
|
+
return this.getAttribute("control") || "color";
|
|
11891
12103
|
}
|
|
11892
12104
|
|
|
11893
12105
|
connectedCallback() {
|
|
@@ -11897,7 +12109,7 @@ class FigColorTip extends HTMLElement {
|
|
|
11897
12109
|
|
|
11898
12110
|
disconnectedCallback() {
|
|
11899
12111
|
this.#teardownListeners();
|
|
11900
|
-
this.removeEventListener("click", this.#
|
|
12112
|
+
this.removeEventListener("click", this.#handleControlClick);
|
|
11901
12113
|
}
|
|
11902
12114
|
|
|
11903
12115
|
#teardownListeners() {
|
|
@@ -11922,14 +12134,16 @@ class FigColorTip extends HTMLElement {
|
|
|
11922
12134
|
}
|
|
11923
12135
|
|
|
11924
12136
|
#render() {
|
|
11925
|
-
|
|
11926
|
-
|
|
12137
|
+
const mode = this.#controlMode;
|
|
12138
|
+
if (mode === "add" || mode === "remove") {
|
|
12139
|
+
const icon = mode === "add" ? "var(--icon-add)" : "var(--icon-minus)";
|
|
12140
|
+
this.innerHTML = `<fig-button icon variant="ghost"><span class="fig-mask-icon" style="--icon: ${icon}"></span></fig-button>`;
|
|
11927
12141
|
this.#fillPicker = null;
|
|
11928
12142
|
this.#chit = null;
|
|
11929
|
-
this.addEventListener("click", this.#
|
|
12143
|
+
this.addEventListener("click", this.#handleControlClick);
|
|
11930
12144
|
return;
|
|
11931
12145
|
}
|
|
11932
|
-
this.removeEventListener("click", this.#
|
|
12146
|
+
this.removeEventListener("click", this.#handleControlClick);
|
|
11933
12147
|
|
|
11934
12148
|
const color = this.#normalizeColor(this.getAttribute("value"));
|
|
11935
12149
|
const alphaAttr = this.#alphaEnabled ? "" : 'alpha="false"';
|
|
@@ -11949,9 +12163,10 @@ class FigColorTip extends HTMLElement {
|
|
|
11949
12163
|
});
|
|
11950
12164
|
}
|
|
11951
12165
|
|
|
11952
|
-
#
|
|
12166
|
+
#handleControlClick = () => {
|
|
12167
|
+
const mode = this.#controlMode;
|
|
11953
12168
|
this.dispatchEvent(
|
|
11954
|
-
new CustomEvent(
|
|
12169
|
+
new CustomEvent(mode, { bubbles: true, composed: true }),
|
|
11955
12170
|
);
|
|
11956
12171
|
};
|
|
11957
12172
|
|
|
@@ -12083,7 +12298,7 @@ class FigColorTip extends HTMLElement {
|
|
|
12083
12298
|
if (!this.isConnected) return;
|
|
12084
12299
|
|
|
12085
12300
|
switch (name) {
|
|
12086
|
-
case "
|
|
12301
|
+
case "control":
|
|
12087
12302
|
this.#render();
|
|
12088
12303
|
break;
|
|
12089
12304
|
case "value":
|
|
@@ -12695,7 +12910,7 @@ class FigHandle extends HTMLElement {
|
|
|
12695
12910
|
"drag-snapping",
|
|
12696
12911
|
"value",
|
|
12697
12912
|
"type",
|
|
12698
|
-
"
|
|
12913
|
+
"control",
|
|
12699
12914
|
];
|
|
12700
12915
|
|
|
12701
12916
|
#isDragging = false;
|
|
@@ -12704,8 +12919,16 @@ class FigHandle extends HTMLElement {
|
|
|
12704
12919
|
#applyingValue = false;
|
|
12705
12920
|
#colorTip = null;
|
|
12706
12921
|
|
|
12707
|
-
get #
|
|
12708
|
-
return this.
|
|
12922
|
+
get #controlMode() {
|
|
12923
|
+
return this.getAttribute("control") || null;
|
|
12924
|
+
}
|
|
12925
|
+
|
|
12926
|
+
get #hasControlMode() {
|
|
12927
|
+
return this.#controlMode === "add" || this.#controlMode === "remove";
|
|
12928
|
+
}
|
|
12929
|
+
|
|
12930
|
+
get #isGhost() {
|
|
12931
|
+
return this.classList.contains("fig-input-gradient-ghost");
|
|
12709
12932
|
}
|
|
12710
12933
|
|
|
12711
12934
|
get #dragEnabled() {
|
|
@@ -12838,7 +13061,7 @@ class FigHandle extends HTMLElement {
|
|
|
12838
13061
|
document.addEventListener("pointerdown", this.#handleDeselect);
|
|
12839
13062
|
const initial = this.getAttribute("value");
|
|
12840
13063
|
if (initial) this.#applyValue(initial);
|
|
12841
|
-
if (this.#
|
|
13064
|
+
if (this.#hasControlMode && !this.#isGhost) this.#showColorTip();
|
|
12842
13065
|
}
|
|
12843
13066
|
|
|
12844
13067
|
disconnectedCallback() {
|
|
@@ -12848,28 +13071,36 @@ class FigHandle extends HTMLElement {
|
|
|
12848
13071
|
document.removeEventListener("pointerdown", this.#handleDeselect);
|
|
12849
13072
|
}
|
|
12850
13073
|
|
|
12851
|
-
|
|
13074
|
+
select() {
|
|
12852
13075
|
if (this.hasAttribute("disabled")) return;
|
|
12853
|
-
|
|
13076
|
+
this.setAttribute("selected", "");
|
|
13077
|
+
if (this.getAttribute("type") === "color") this.#showColorTip();
|
|
13078
|
+
}
|
|
13079
|
+
|
|
13080
|
+
deselect() {
|
|
13081
|
+
this.removeAttribute("selected");
|
|
13082
|
+
this.#hideColorTip();
|
|
13083
|
+
}
|
|
13084
|
+
|
|
13085
|
+
#handleSelect = (e) => {
|
|
13086
|
+
if (this.#hasControlMode) return;
|
|
12854
13087
|
if (this.#didDrag) {
|
|
12855
13088
|
this.#didDrag = false;
|
|
12856
13089
|
return;
|
|
12857
13090
|
}
|
|
12858
|
-
this.
|
|
12859
|
-
if (this.getAttribute("type") === "color") this.#showColorTip();
|
|
13091
|
+
this.select();
|
|
12860
13092
|
};
|
|
12861
13093
|
|
|
12862
13094
|
#handleDeselect = (e) => {
|
|
12863
|
-
if (this.#
|
|
13095
|
+
if (this.#hasControlMode) return;
|
|
12864
13096
|
if (this.contains(e.target)) return;
|
|
12865
13097
|
if (this.#colorTip && e.target.closest?.("dialog, [popover]")) return;
|
|
12866
|
-
this.
|
|
12867
|
-
this.#hideColorTip();
|
|
13098
|
+
this.deselect();
|
|
12868
13099
|
};
|
|
12869
13100
|
|
|
12870
13101
|
attributeChangedCallback(name, _old, value) {
|
|
12871
13102
|
if (name === "color") {
|
|
12872
|
-
if (!value || value === "false") {
|
|
13103
|
+
if (!value || value === "false" || value === "true") {
|
|
12873
13104
|
this.style.removeProperty("--fill");
|
|
12874
13105
|
} else {
|
|
12875
13106
|
this.style.setProperty("--fill", value);
|
|
@@ -12879,8 +13110,9 @@ class FigHandle extends HTMLElement {
|
|
|
12879
13110
|
if (name === "value" && !this.#applyingValue && !this.#isDragging) {
|
|
12880
13111
|
this.#applyValue(value);
|
|
12881
13112
|
}
|
|
12882
|
-
if (name === "
|
|
12883
|
-
if (this.#
|
|
13113
|
+
if (name === "control" && !this.#isGhost) {
|
|
13114
|
+
if (this.#hasControlMode) {
|
|
13115
|
+
this.#hideColorTip();
|
|
12884
13116
|
this.#showColorTip();
|
|
12885
13117
|
} else {
|
|
12886
13118
|
this.#hideColorTip();
|
|
@@ -12962,28 +13194,22 @@ class FigHandle extends HTMLElement {
|
|
|
12962
13194
|
}
|
|
12963
13195
|
};
|
|
12964
13196
|
|
|
12965
|
-
const isColorType = this.getAttribute("type") === "color";
|
|
12966
|
-
if (!isColorType) {
|
|
12967
|
-
clampAndApply(e.clientX, e.clientY, e.shiftKey);
|
|
12968
|
-
}
|
|
12969
|
-
this.style.cursor = "grabbing";
|
|
12970
|
-
if (!isColorType) {
|
|
12971
|
-
this.dispatchEvent(
|
|
12972
|
-
new CustomEvent("input", {
|
|
12973
|
-
bubbles: true,
|
|
12974
|
-
detail: this.#positionDetail(containerRect),
|
|
12975
|
-
}),
|
|
12976
|
-
);
|
|
12977
|
-
}
|
|
12978
|
-
|
|
12979
13197
|
const onMove = (e) => {
|
|
12980
13198
|
if (!this.#isDragging) return;
|
|
13199
|
+
if (!this.#didDrag) {
|
|
13200
|
+
this.classList.add("dragging");
|
|
13201
|
+
this.style.cursor = "grabbing";
|
|
13202
|
+
if (!this.hasAttribute("selected")) this.select();
|
|
13203
|
+
}
|
|
12981
13204
|
this.#didDrag = true;
|
|
12982
13205
|
clampAndApply(e.clientX, e.clientY, e.shiftKey);
|
|
12983
13206
|
this.dispatchEvent(
|
|
12984
13207
|
new CustomEvent("input", {
|
|
12985
13208
|
bubbles: true,
|
|
12986
|
-
detail:
|
|
13209
|
+
detail: {
|
|
13210
|
+
...this.#positionDetail(container.getBoundingClientRect()),
|
|
13211
|
+
shiftKey: e.shiftKey,
|
|
13212
|
+
},
|
|
12987
13213
|
}),
|
|
12988
13214
|
);
|
|
12989
13215
|
};
|
|
@@ -12991,38 +13217,63 @@ class FigHandle extends HTMLElement {
|
|
|
12991
13217
|
const onUp = (e) => {
|
|
12992
13218
|
this.#isDragging = false;
|
|
12993
13219
|
this.style.cursor = "";
|
|
13220
|
+
this.classList.remove("dragging");
|
|
12994
13221
|
window.removeEventListener("pointermove", onMove);
|
|
12995
13222
|
window.removeEventListener("pointerup", onUp);
|
|
12996
|
-
if (this.#didDrag
|
|
13223
|
+
if (this.#didDrag) {
|
|
12997
13224
|
clampAndApply(e.clientX, e.clientY, e.shiftKey);
|
|
13225
|
+
this.#syncValueAttribute();
|
|
13226
|
+
this.dispatchEvent(
|
|
13227
|
+
new CustomEvent("change", {
|
|
13228
|
+
bubbles: true,
|
|
13229
|
+
detail: this.#positionDetail(container.getBoundingClientRect()),
|
|
13230
|
+
}),
|
|
13231
|
+
);
|
|
13232
|
+
const swallowClick = (evt) => {
|
|
13233
|
+
evt.stopPropagation();
|
|
13234
|
+
evt.preventDefault();
|
|
13235
|
+
};
|
|
13236
|
+
this.addEventListener("click", swallowClick, {
|
|
13237
|
+
capture: true,
|
|
13238
|
+
once: true,
|
|
13239
|
+
});
|
|
13240
|
+
} else {
|
|
13241
|
+
this.#syncValueAttribute();
|
|
12998
13242
|
}
|
|
12999
|
-
this.#
|
|
13000
|
-
this.dispatchEvent(
|
|
13001
|
-
new CustomEvent("change", {
|
|
13002
|
-
bubbles: true,
|
|
13003
|
-
detail: this.#positionDetail(container.getBoundingClientRect()),
|
|
13004
|
-
}),
|
|
13005
|
-
);
|
|
13243
|
+
this.#didDrag = false;
|
|
13006
13244
|
};
|
|
13007
13245
|
|
|
13008
13246
|
window.addEventListener("pointermove", onMove);
|
|
13009
13247
|
window.addEventListener("pointerup", onUp);
|
|
13010
13248
|
}
|
|
13011
13249
|
|
|
13250
|
+
showColorTip() {
|
|
13251
|
+
if (this.#colorTip) {
|
|
13252
|
+
this.#colorTip.style.display = "";
|
|
13253
|
+
return;
|
|
13254
|
+
}
|
|
13255
|
+
this.#showColorTip();
|
|
13256
|
+
}
|
|
13257
|
+
|
|
13258
|
+
hideColorTip() {
|
|
13259
|
+
if (!this.#colorTip) return;
|
|
13260
|
+
this.#colorTip.style.display = "none";
|
|
13261
|
+
}
|
|
13262
|
+
|
|
13012
13263
|
#showColorTip() {
|
|
13013
13264
|
if (this.#colorTip) return;
|
|
13014
13265
|
const tip = document.createElement("fig-color-tip");
|
|
13015
|
-
if (this.#
|
|
13016
|
-
tip.setAttribute("
|
|
13266
|
+
if (this.#hasControlMode) {
|
|
13267
|
+
tip.setAttribute("control", this.#controlMode);
|
|
13017
13268
|
} else {
|
|
13018
13269
|
tip.setAttribute("value", this.getAttribute("color") || "#D9D9D9");
|
|
13019
13270
|
tip.setAttribute("alpha", "true");
|
|
13020
13271
|
tip.setAttribute("selected", "");
|
|
13021
13272
|
}
|
|
13022
|
-
tip.addEventListener("pointerdown", (e) => e.stopPropagation());
|
|
13023
13273
|
tip.addEventListener("input", this.#handleColorTipInput);
|
|
13024
13274
|
tip.addEventListener("change", this.#handleColorTipChange);
|
|
13025
|
-
tip.addEventListener("add", this.#
|
|
13275
|
+
tip.addEventListener("add", this.#handleColorTipControl);
|
|
13276
|
+
tip.addEventListener("remove", this.#handleColorTipControl);
|
|
13026
13277
|
this.appendChild(tip);
|
|
13027
13278
|
this.#colorTip = tip;
|
|
13028
13279
|
}
|
|
@@ -13031,7 +13282,8 @@ class FigHandle extends HTMLElement {
|
|
|
13031
13282
|
if (!this.#colorTip) return;
|
|
13032
13283
|
this.#colorTip.removeEventListener("input", this.#handleColorTipInput);
|
|
13033
13284
|
this.#colorTip.removeEventListener("change", this.#handleColorTipChange);
|
|
13034
|
-
this.#colorTip.removeEventListener("add", this.#
|
|
13285
|
+
this.#colorTip.removeEventListener("add", this.#handleColorTipControl);
|
|
13286
|
+
this.#colorTip.removeEventListener("remove", this.#handleColorTipControl);
|
|
13035
13287
|
this.#colorTip.remove();
|
|
13036
13288
|
this.#colorTip = null;
|
|
13037
13289
|
}
|
|
@@ -13046,10 +13298,10 @@ class FigHandle extends HTMLElement {
|
|
|
13046
13298
|
if (e.detail?.color) this.setAttribute("color", e.detail.color);
|
|
13047
13299
|
};
|
|
13048
13300
|
|
|
13049
|
-
#
|
|
13301
|
+
#handleColorTipControl = (e) => {
|
|
13050
13302
|
e.stopPropagation();
|
|
13051
13303
|
this.dispatchEvent(
|
|
13052
|
-
new CustomEvent(
|
|
13304
|
+
new CustomEvent(e.type, { bubbles: true, composed: true }),
|
|
13053
13305
|
);
|
|
13054
13306
|
};
|
|
13055
13307
|
|
package/package.json
CHANGED