@rogieking/figui3 8.9.18 → 8.9.19
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 +4 -5
- package/.cursor/skills/figui3/SKILL.md +1 -1
- package/components.css +5 -2
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +2 -2
- package/dist/fig.css +1 -1
- package/dist/fig.js +4 -4
- package/fig-editor.css +4 -2
- package/fig-editor.js +16 -8
- package/fig.js +100 -6
- package/package.json +1 -1
package/fig-editor.css
CHANGED
|
@@ -174,8 +174,10 @@ fig-fill-picker {
|
|
|
174
174
|
display: block;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
-
fig-
|
|
178
|
-
|
|
177
|
+
.fig-fill-picker-tab:is([data-tab="solid"], [data-tab="gradient"]) {
|
|
178
|
+
fig-preview {
|
|
179
|
+
overflow: visible;
|
|
180
|
+
}
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
.fig-fill-picker-color-area {
|
package/fig-editor.js
CHANGED
|
@@ -2078,9 +2078,13 @@ class FigFillPicker extends HTMLElement {
|
|
|
2078
2078
|
bg = "";
|
|
2079
2079
|
}
|
|
2080
2080
|
break;
|
|
2081
|
-
default:
|
|
2082
|
-
const slot =
|
|
2083
|
-
|
|
2081
|
+
default: {
|
|
2082
|
+
const slot =
|
|
2083
|
+
this.#customSlots[this.#fillType]?.element ||
|
|
2084
|
+
this.querySelector(`[slot="mode-${this.#fillType}"]`);
|
|
2085
|
+
bg = slot?.getAttribute("swatch-background") || "";
|
|
2086
|
+
break;
|
|
2087
|
+
}
|
|
2084
2088
|
}
|
|
2085
2089
|
|
|
2086
2090
|
this.#swatch.setAttribute("background", bg);
|
|
@@ -4573,11 +4577,16 @@ class FigFillPicker extends HTMLElement {
|
|
|
4573
4577
|
existing?.getTracks?.().filter((track) => track.readyState !== "ended") ??
|
|
4574
4578
|
[];
|
|
4575
4579
|
if (existing && liveTracks.length) {
|
|
4576
|
-
const
|
|
4577
|
-
|
|
4580
|
+
const liveId =
|
|
4581
|
+
existing.getVideoTracks?.()?.[0]?.getSettings?.()?.deviceId ||
|
|
4582
|
+
this.#webcam.deviceId ||
|
|
4583
|
+
null;
|
|
4584
|
+
// Reuse the live stream only when it is already the requested device.
|
|
4585
|
+
// An unknown liveId is not a match — otherwise the camera select cannot switch.
|
|
4586
|
+
if (!requested || requested === liveId) {
|
|
4578
4587
|
attachPreview(existing);
|
|
4579
4588
|
this.#emitWebcamStream();
|
|
4580
|
-
populateCameras(null, requested ||
|
|
4589
|
+
populateCameras(null, requested || liveId);
|
|
4581
4590
|
return;
|
|
4582
4591
|
}
|
|
4583
4592
|
}
|
|
@@ -4638,8 +4647,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
4638
4647
|
cameraSelect.addEventListener("change", (e) => {
|
|
4639
4648
|
const next =
|
|
4640
4649
|
typeof e.detail === "string" ? e.detail : e.target?.value;
|
|
4641
|
-
if (!next) return;
|
|
4642
|
-
this.#webcam.deviceId = next;
|
|
4650
|
+
if (!next || next === this.#webcam.deviceId) return;
|
|
4643
4651
|
startWebcam(next);
|
|
4644
4652
|
});
|
|
4645
4653
|
|
package/fig.js
CHANGED
|
@@ -8979,6 +8979,7 @@ class FigInputFill extends HTMLElement {
|
|
|
8979
8979
|
scale: 50,
|
|
8980
8980
|
opacity: 1,
|
|
8981
8981
|
};
|
|
8982
|
+
#custom = {};
|
|
8982
8983
|
|
|
8983
8984
|
constructor() {
|
|
8984
8985
|
super();
|
|
@@ -9066,6 +9067,11 @@ class FigInputFill extends HTMLElement {
|
|
|
9066
9067
|
if (parsed.opacity !== undefined)
|
|
9067
9068
|
this.#webcam.opacity = parsed.opacity;
|
|
9068
9069
|
break;
|
|
9070
|
+
default: {
|
|
9071
|
+
const { type: _type, ...rest } = parsed;
|
|
9072
|
+
this.#custom = rest;
|
|
9073
|
+
break;
|
|
9074
|
+
}
|
|
9069
9075
|
}
|
|
9070
9076
|
} catch (e) {
|
|
9071
9077
|
// If not JSON, treat as hex color
|
|
@@ -9142,9 +9148,9 @@ class FigInputFill extends HTMLElement {
|
|
|
9142
9148
|
case "webcam":
|
|
9143
9149
|
return this.#webcam.snapshot
|
|
9144
9150
|
? figCssUrl(this.#webcam.snapshot)
|
|
9145
|
-
: "
|
|
9151
|
+
: "";
|
|
9146
9152
|
default:
|
|
9147
|
-
return
|
|
9153
|
+
return this.#customSwatchBackground();
|
|
9148
9154
|
}
|
|
9149
9155
|
}
|
|
9150
9156
|
|
|
@@ -9173,7 +9179,38 @@ class FigInputFill extends HTMLElement {
|
|
|
9173
9179
|
case "webcam":
|
|
9174
9180
|
return this.#webcam.opacity ?? 1;
|
|
9175
9181
|
default:
|
|
9176
|
-
return
|
|
9182
|
+
return this.#normalizeFillOpacity(
|
|
9183
|
+
this.#custom.opacity ?? this.#custom.alpha,
|
|
9184
|
+
1,
|
|
9185
|
+
);
|
|
9186
|
+
}
|
|
9187
|
+
}
|
|
9188
|
+
|
|
9189
|
+
#customModeSlot() {
|
|
9190
|
+
return this.querySelector(`[slot="mode-${this.#fillType}"]`);
|
|
9191
|
+
}
|
|
9192
|
+
|
|
9193
|
+
#customTypeLabel() {
|
|
9194
|
+
const slotLabel = this.#customModeSlot()?.getAttribute("label");
|
|
9195
|
+
if (slotLabel) return slotLabel;
|
|
9196
|
+
if (!this.#fillType) return "Fill";
|
|
9197
|
+
return this.#fillType.charAt(0).toUpperCase() + this.#fillType.slice(1);
|
|
9198
|
+
}
|
|
9199
|
+
|
|
9200
|
+
#customSwatchBackground() {
|
|
9201
|
+
return (
|
|
9202
|
+
this.#custom.swatchBackground ||
|
|
9203
|
+
this.#custom.background ||
|
|
9204
|
+
this.#custom.css ||
|
|
9205
|
+
this.#customModeSlot()?.getAttribute("swatch-background") ||
|
|
9206
|
+
""
|
|
9207
|
+
);
|
|
9208
|
+
}
|
|
9209
|
+
|
|
9210
|
+
#adoptModeSlots() {
|
|
9211
|
+
if (!this.#fillPicker) return;
|
|
9212
|
+
for (const slot of [...this.querySelectorAll(":scope > [slot^='mode-']")]) {
|
|
9213
|
+
this.#fillPicker.append(slot);
|
|
9177
9214
|
}
|
|
9178
9215
|
}
|
|
9179
9216
|
|
|
@@ -9268,6 +9305,13 @@ class FigInputFill extends HTMLElement {
|
|
|
9268
9305
|
label = "Webcam";
|
|
9269
9306
|
opacity = this.#webcam.opacity ?? 1;
|
|
9270
9307
|
break;
|
|
9308
|
+
default:
|
|
9309
|
+
label = this.#customTypeLabel();
|
|
9310
|
+
opacity = this.#normalizeFillOpacity(
|
|
9311
|
+
this.#custom.opacity ?? this.#custom.alpha,
|
|
9312
|
+
1,
|
|
9313
|
+
);
|
|
9314
|
+
break;
|
|
9271
9315
|
}
|
|
9272
9316
|
|
|
9273
9317
|
return [
|
|
@@ -9290,6 +9334,7 @@ class FigInputFill extends HTMLElement {
|
|
|
9290
9334
|
alpha: this.#fillPickerSwatchAlpha(),
|
|
9291
9335
|
disabled,
|
|
9292
9336
|
});
|
|
9337
|
+
const modeSlots = [...this.querySelectorAll("[slot^='mode-']")];
|
|
9293
9338
|
const picker = figCreateElement(
|
|
9294
9339
|
"fig-fill-picker",
|
|
9295
9340
|
{
|
|
@@ -9297,7 +9342,7 @@ class FigInputFill extends HTMLElement {
|
|
|
9297
9342
|
disabled,
|
|
9298
9343
|
...fpAttrs,
|
|
9299
9344
|
},
|
|
9300
|
-
swatch,
|
|
9345
|
+
[swatch, ...modeSlots],
|
|
9301
9346
|
);
|
|
9302
9347
|
const combo = figCreateElement(
|
|
9303
9348
|
"div",
|
|
@@ -9307,6 +9352,11 @@ class FigInputFill extends HTMLElement {
|
|
|
9307
9352
|
this.replaceChildren(combo);
|
|
9308
9353
|
|
|
9309
9354
|
this.#setupEventListeners();
|
|
9355
|
+
queueMicrotask(() => {
|
|
9356
|
+
this.#adoptModeSlots();
|
|
9357
|
+
this.#syncSwatch();
|
|
9358
|
+
this.#updateControls();
|
|
9359
|
+
});
|
|
9310
9360
|
}
|
|
9311
9361
|
|
|
9312
9362
|
#setupEventListeners() {
|
|
@@ -9375,6 +9425,11 @@ class FigInputFill extends HTMLElement {
|
|
|
9375
9425
|
this.#webcam.snapshot = detail.image.url;
|
|
9376
9426
|
}
|
|
9377
9427
|
break;
|
|
9428
|
+
default: {
|
|
9429
|
+
const { type: _type, colorSpace: _colorSpace, ...rest } = detail;
|
|
9430
|
+
this.#custom = rest;
|
|
9431
|
+
break;
|
|
9432
|
+
}
|
|
9378
9433
|
}
|
|
9379
9434
|
// Update controls (don't re-render to keep dialog open)
|
|
9380
9435
|
if (typeChanged) {
|
|
@@ -9441,6 +9496,9 @@ class FigInputFill extends HTMLElement {
|
|
|
9441
9496
|
case "webcam":
|
|
9442
9497
|
this.#webcam.opacity = alpha;
|
|
9443
9498
|
break;
|
|
9499
|
+
default:
|
|
9500
|
+
this.#custom.opacity = alpha;
|
|
9501
|
+
break;
|
|
9444
9502
|
}
|
|
9445
9503
|
this.#updateFillPicker();
|
|
9446
9504
|
this.#syncSwatch();
|
|
@@ -9510,6 +9568,22 @@ class FigInputFill extends HTMLElement {
|
|
|
9510
9568
|
);
|
|
9511
9569
|
}
|
|
9512
9570
|
break;
|
|
9571
|
+
default: {
|
|
9572
|
+
const label = this.querySelector(".fig-input-fill-label");
|
|
9573
|
+
if (label) label.textContent = this.#customTypeLabel();
|
|
9574
|
+
if (this.#opacityInput) {
|
|
9575
|
+
this.#opacityInput.setAttribute(
|
|
9576
|
+
"value",
|
|
9577
|
+
Math.round(
|
|
9578
|
+
this.#normalizeFillOpacity(
|
|
9579
|
+
this.#custom.opacity ?? this.#custom.alpha,
|
|
9580
|
+
1,
|
|
9581
|
+
) * 100,
|
|
9582
|
+
),
|
|
9583
|
+
);
|
|
9584
|
+
}
|
|
9585
|
+
break;
|
|
9586
|
+
}
|
|
9513
9587
|
}
|
|
9514
9588
|
}
|
|
9515
9589
|
|
|
@@ -9587,6 +9661,9 @@ class FigInputFill extends HTMLElement {
|
|
|
9587
9661
|
case "webcam":
|
|
9588
9662
|
this.#webcam.opacity = alpha;
|
|
9589
9663
|
break;
|
|
9664
|
+
default:
|
|
9665
|
+
this.#custom.opacity = alpha;
|
|
9666
|
+
break;
|
|
9590
9667
|
}
|
|
9591
9668
|
this.#updateFillPicker();
|
|
9592
9669
|
this.#updateSwatchAlpha(alpha);
|
|
@@ -9703,7 +9780,7 @@ class FigInputFill extends HTMLElement {
|
|
|
9703
9780
|
webcam: this.#webcamValue(),
|
|
9704
9781
|
};
|
|
9705
9782
|
default:
|
|
9706
|
-
return { type: this.#fillType };
|
|
9783
|
+
return { type: this.#fillType, ...this.#custom };
|
|
9707
9784
|
}
|
|
9708
9785
|
}
|
|
9709
9786
|
|
|
@@ -11886,7 +11963,24 @@ class FigSwatch extends HTMLElement {
|
|
|
11886
11963
|
}
|
|
11887
11964
|
|
|
11888
11965
|
#render() {
|
|
11889
|
-
const
|
|
11966
|
+
const rawAttr = this.getAttribute("background");
|
|
11967
|
+
const emptyMedia = this.hasAttribute("background") && !rawAttr?.trim();
|
|
11968
|
+
if (emptyMedia) {
|
|
11969
|
+
if (this.#type !== "image" || this.input) {
|
|
11970
|
+
this.#type = "image";
|
|
11971
|
+
this.setAttribute("data-type", "image");
|
|
11972
|
+
if (this.input) {
|
|
11973
|
+
this.input.removeEventListener("input", this.#boundHandleInput);
|
|
11974
|
+
}
|
|
11975
|
+
this.replaceChildren(document.createElement("div"));
|
|
11976
|
+
this.input = null;
|
|
11977
|
+
this.#syncA11y();
|
|
11978
|
+
}
|
|
11979
|
+
this.style.setProperty("--swatch-background", "none");
|
|
11980
|
+
return;
|
|
11981
|
+
}
|
|
11982
|
+
|
|
11983
|
+
const rawBg = rawAttr || "#D9D9D9";
|
|
11890
11984
|
const isVar = rawBg.includes("var(");
|
|
11891
11985
|
const bg = isVar ? this.#resolveBackground(rawBg) : rawBg;
|
|
11892
11986
|
const newType = this.#detectType(bg);
|
package/package.json
CHANGED