@rogieking/figui3 8.9.18 → 8.9.20
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/fig-lab/SKILL.md +4 -3
- package/.cursor/skills/figui3/SKILL.md +1 -1
- package/.cursor/skills/propkit/SKILL.md +1 -1
- package/README.md +26 -4
- package/components.css +26 -12
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +3 -3
- package/dist/fig-lab.css +1 -1
- package/dist/fig-lab.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 +139 -13
- package/fig-lab.css +23 -6
- package/fig-lab.js +494 -2
- package/fig.js +126 -12
- package/package.json +1 -1
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();
|
|
@@ -9054,8 +9055,11 @@ class FigInputFill extends HTMLElement {
|
|
|
9054
9055
|
break;
|
|
9055
9056
|
case "webcam":
|
|
9056
9057
|
if (parsed.webcam && typeof parsed.webcam === "object") {
|
|
9057
|
-
const { stream: _ignored, ...rest } = parsed.webcam;
|
|
9058
|
+
const { stream: _ignored, snapshot, ...rest } = parsed.webcam;
|
|
9058
9059
|
this.#webcam = { ...this.#webcam, ...rest };
|
|
9060
|
+
if (typeof snapshot === "string" && snapshot) {
|
|
9061
|
+
this.#webcam.snapshot = snapshot;
|
|
9062
|
+
}
|
|
9059
9063
|
} else if (parsed.image?.url) {
|
|
9060
9064
|
this.#webcam.snapshot = parsed.image.url;
|
|
9061
9065
|
if (parsed.image.scaleMode)
|
|
@@ -9066,6 +9070,11 @@ class FigInputFill extends HTMLElement {
|
|
|
9066
9070
|
if (parsed.opacity !== undefined)
|
|
9067
9071
|
this.#webcam.opacity = parsed.opacity;
|
|
9068
9072
|
break;
|
|
9073
|
+
default: {
|
|
9074
|
+
const { type: _type, ...rest } = parsed;
|
|
9075
|
+
this.#custom = rest;
|
|
9076
|
+
break;
|
|
9077
|
+
}
|
|
9069
9078
|
}
|
|
9070
9079
|
} catch (e) {
|
|
9071
9080
|
// If not JSON, treat as hex color
|
|
@@ -9139,12 +9148,14 @@ class FigInputFill extends HTMLElement {
|
|
|
9139
9148
|
return this.#image.url ? figCssUrl(this.#image.url) : "#D9D9D9";
|
|
9140
9149
|
case "video":
|
|
9141
9150
|
return this.#video.poster ? figCssUrl(this.#video.poster) : "#D9D9D9";
|
|
9142
|
-
case "webcam":
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9151
|
+
case "webcam": {
|
|
9152
|
+
const snapshot =
|
|
9153
|
+
this.#webcam.snapshot ||
|
|
9154
|
+
this.#fillPicker?.value?.webcam?.snapshot;
|
|
9155
|
+
return snapshot ? figCssUrl(snapshot) : "";
|
|
9156
|
+
}
|
|
9146
9157
|
default:
|
|
9147
|
-
return
|
|
9158
|
+
return this.#customSwatchBackground();
|
|
9148
9159
|
}
|
|
9149
9160
|
}
|
|
9150
9161
|
|
|
@@ -9173,7 +9184,38 @@ class FigInputFill extends HTMLElement {
|
|
|
9173
9184
|
case "webcam":
|
|
9174
9185
|
return this.#webcam.opacity ?? 1;
|
|
9175
9186
|
default:
|
|
9176
|
-
return
|
|
9187
|
+
return this.#normalizeFillOpacity(
|
|
9188
|
+
this.#custom.opacity ?? this.#custom.alpha,
|
|
9189
|
+
1,
|
|
9190
|
+
);
|
|
9191
|
+
}
|
|
9192
|
+
}
|
|
9193
|
+
|
|
9194
|
+
#customModeSlot() {
|
|
9195
|
+
return this.querySelector(`[slot="mode-${this.#fillType}"]`);
|
|
9196
|
+
}
|
|
9197
|
+
|
|
9198
|
+
#customTypeLabel() {
|
|
9199
|
+
const slotLabel = this.#customModeSlot()?.getAttribute("label");
|
|
9200
|
+
if (slotLabel) return slotLabel;
|
|
9201
|
+
if (!this.#fillType) return "Fill";
|
|
9202
|
+
return this.#fillType.charAt(0).toUpperCase() + this.#fillType.slice(1);
|
|
9203
|
+
}
|
|
9204
|
+
|
|
9205
|
+
#customSwatchBackground() {
|
|
9206
|
+
return (
|
|
9207
|
+
this.#custom.swatchBackground ||
|
|
9208
|
+
this.#custom.background ||
|
|
9209
|
+
this.#custom.css ||
|
|
9210
|
+
this.#customModeSlot()?.getAttribute("swatch-background") ||
|
|
9211
|
+
""
|
|
9212
|
+
);
|
|
9213
|
+
}
|
|
9214
|
+
|
|
9215
|
+
#adoptModeSlots() {
|
|
9216
|
+
if (!this.#fillPicker) return;
|
|
9217
|
+
for (const slot of [...this.querySelectorAll(":scope > [slot^='mode-']")]) {
|
|
9218
|
+
this.#fillPicker.append(slot);
|
|
9177
9219
|
}
|
|
9178
9220
|
}
|
|
9179
9221
|
|
|
@@ -9268,6 +9310,13 @@ class FigInputFill extends HTMLElement {
|
|
|
9268
9310
|
label = "Webcam";
|
|
9269
9311
|
opacity = this.#webcam.opacity ?? 1;
|
|
9270
9312
|
break;
|
|
9313
|
+
default:
|
|
9314
|
+
label = this.#customTypeLabel();
|
|
9315
|
+
opacity = this.#normalizeFillOpacity(
|
|
9316
|
+
this.#custom.opacity ?? this.#custom.alpha,
|
|
9317
|
+
1,
|
|
9318
|
+
);
|
|
9319
|
+
break;
|
|
9271
9320
|
}
|
|
9272
9321
|
|
|
9273
9322
|
return [
|
|
@@ -9290,6 +9339,7 @@ class FigInputFill extends HTMLElement {
|
|
|
9290
9339
|
alpha: this.#fillPickerSwatchAlpha(),
|
|
9291
9340
|
disabled,
|
|
9292
9341
|
});
|
|
9342
|
+
const modeSlots = [...this.querySelectorAll("[slot^='mode-']")];
|
|
9293
9343
|
const picker = figCreateElement(
|
|
9294
9344
|
"fig-fill-picker",
|
|
9295
9345
|
{
|
|
@@ -9297,7 +9347,7 @@ class FigInputFill extends HTMLElement {
|
|
|
9297
9347
|
disabled,
|
|
9298
9348
|
...fpAttrs,
|
|
9299
9349
|
},
|
|
9300
|
-
swatch,
|
|
9350
|
+
[swatch, ...modeSlots],
|
|
9301
9351
|
);
|
|
9302
9352
|
const combo = figCreateElement(
|
|
9303
9353
|
"div",
|
|
@@ -9307,6 +9357,11 @@ class FigInputFill extends HTMLElement {
|
|
|
9307
9357
|
this.replaceChildren(combo);
|
|
9308
9358
|
|
|
9309
9359
|
this.#setupEventListeners();
|
|
9360
|
+
queueMicrotask(() => {
|
|
9361
|
+
this.#adoptModeSlots();
|
|
9362
|
+
this.#syncSwatch();
|
|
9363
|
+
this.#updateControls();
|
|
9364
|
+
});
|
|
9310
9365
|
}
|
|
9311
9366
|
|
|
9312
9367
|
#setupEventListeners() {
|
|
@@ -9369,12 +9424,24 @@ class FigInputFill extends HTMLElement {
|
|
|
9369
9424
|
break;
|
|
9370
9425
|
case "webcam":
|
|
9371
9426
|
if (detail.webcam) {
|
|
9372
|
-
const { stream: _ignored, ...rest } = detail.webcam;
|
|
9427
|
+
const { stream: _ignored, snapshot, ...rest } = detail.webcam;
|
|
9373
9428
|
this.#webcam = { ...this.#webcam, ...rest };
|
|
9429
|
+
if (typeof snapshot === "string" && snapshot) {
|
|
9430
|
+
this.#webcam.snapshot = snapshot;
|
|
9431
|
+
}
|
|
9374
9432
|
} else if (detail.image?.url) {
|
|
9375
9433
|
this.#webcam.snapshot = detail.image.url;
|
|
9376
9434
|
}
|
|
9435
|
+
if (!this.#webcam.snapshot) {
|
|
9436
|
+
const fromPicker = this.#fillPicker?.value?.webcam?.snapshot;
|
|
9437
|
+
if (fromPicker) this.#webcam.snapshot = fromPicker;
|
|
9438
|
+
}
|
|
9439
|
+
break;
|
|
9440
|
+
default: {
|
|
9441
|
+
const { type: _type, colorSpace: _colorSpace, ...rest } = detail;
|
|
9442
|
+
this.#custom = rest;
|
|
9377
9443
|
break;
|
|
9444
|
+
}
|
|
9378
9445
|
}
|
|
9379
9446
|
// Update controls (don't re-render to keep dialog open)
|
|
9380
9447
|
if (typeChanged) {
|
|
@@ -9441,6 +9508,9 @@ class FigInputFill extends HTMLElement {
|
|
|
9441
9508
|
case "webcam":
|
|
9442
9509
|
this.#webcam.opacity = alpha;
|
|
9443
9510
|
break;
|
|
9511
|
+
default:
|
|
9512
|
+
this.#custom.opacity = alpha;
|
|
9513
|
+
break;
|
|
9444
9514
|
}
|
|
9445
9515
|
this.#updateFillPicker();
|
|
9446
9516
|
this.#syncSwatch();
|
|
@@ -9510,6 +9580,22 @@ class FigInputFill extends HTMLElement {
|
|
|
9510
9580
|
);
|
|
9511
9581
|
}
|
|
9512
9582
|
break;
|
|
9583
|
+
default: {
|
|
9584
|
+
const label = this.querySelector(".fig-input-fill-label");
|
|
9585
|
+
if (label) label.textContent = this.#customTypeLabel();
|
|
9586
|
+
if (this.#opacityInput) {
|
|
9587
|
+
this.#opacityInput.setAttribute(
|
|
9588
|
+
"value",
|
|
9589
|
+
Math.round(
|
|
9590
|
+
this.#normalizeFillOpacity(
|
|
9591
|
+
this.#custom.opacity ?? this.#custom.alpha,
|
|
9592
|
+
1,
|
|
9593
|
+
) * 100,
|
|
9594
|
+
),
|
|
9595
|
+
);
|
|
9596
|
+
}
|
|
9597
|
+
break;
|
|
9598
|
+
}
|
|
9513
9599
|
}
|
|
9514
9600
|
}
|
|
9515
9601
|
|
|
@@ -9587,6 +9673,9 @@ class FigInputFill extends HTMLElement {
|
|
|
9587
9673
|
case "webcam":
|
|
9588
9674
|
this.#webcam.opacity = alpha;
|
|
9589
9675
|
break;
|
|
9676
|
+
default:
|
|
9677
|
+
this.#custom.opacity = alpha;
|
|
9678
|
+
break;
|
|
9590
9679
|
}
|
|
9591
9680
|
this.#updateFillPicker();
|
|
9592
9681
|
this.#updateSwatchAlpha(alpha);
|
|
@@ -9609,7 +9698,15 @@ class FigInputFill extends HTMLElement {
|
|
|
9609
9698
|
#syncSwatch() {
|
|
9610
9699
|
const swatch = this.#fillPicker?.querySelector("fig-swatch");
|
|
9611
9700
|
if (!swatch) return;
|
|
9612
|
-
|
|
9701
|
+
const background = this.#fillPickerSwatchBackground();
|
|
9702
|
+
if (this.#fillType === "webcam" && !background) {
|
|
9703
|
+
const current = swatch.getAttribute("background") || "";
|
|
9704
|
+
if (current.startsWith("url(")) {
|
|
9705
|
+
swatch.setAttribute("alpha", this.#fillPickerSwatchAlpha());
|
|
9706
|
+
return;
|
|
9707
|
+
}
|
|
9708
|
+
}
|
|
9709
|
+
swatch.setAttribute("background", background);
|
|
9613
9710
|
swatch.setAttribute("alpha", this.#fillPickerSwatchAlpha());
|
|
9614
9711
|
}
|
|
9615
9712
|
|
|
@@ -9703,7 +9800,7 @@ class FigInputFill extends HTMLElement {
|
|
|
9703
9800
|
webcam: this.#webcamValue(),
|
|
9704
9801
|
};
|
|
9705
9802
|
default:
|
|
9706
|
-
return { type: this.#fillType };
|
|
9803
|
+
return { type: this.#fillType, ...this.#custom };
|
|
9707
9804
|
}
|
|
9708
9805
|
}
|
|
9709
9806
|
|
|
@@ -11886,7 +11983,24 @@ class FigSwatch extends HTMLElement {
|
|
|
11886
11983
|
}
|
|
11887
11984
|
|
|
11888
11985
|
#render() {
|
|
11889
|
-
const
|
|
11986
|
+
const rawAttr = this.getAttribute("background");
|
|
11987
|
+
const emptyMedia = this.hasAttribute("background") && !rawAttr?.trim();
|
|
11988
|
+
if (emptyMedia) {
|
|
11989
|
+
if (this.#type !== "image" || this.input) {
|
|
11990
|
+
this.#type = "image";
|
|
11991
|
+
this.setAttribute("data-type", "image");
|
|
11992
|
+
if (this.input) {
|
|
11993
|
+
this.input.removeEventListener("input", this.#boundHandleInput);
|
|
11994
|
+
}
|
|
11995
|
+
this.replaceChildren(document.createElement("div"));
|
|
11996
|
+
this.input = null;
|
|
11997
|
+
this.#syncA11y();
|
|
11998
|
+
}
|
|
11999
|
+
this.style.setProperty("--swatch-background", "none");
|
|
12000
|
+
return;
|
|
12001
|
+
}
|
|
12002
|
+
|
|
12003
|
+
const rawBg = rawAttr || "#D9D9D9";
|
|
11890
12004
|
const isVar = rawBg.includes("var(");
|
|
11891
12005
|
const bg = isVar ? this.#resolveBackground(rawBg) : rawBg;
|
|
11892
12006
|
const newType = this.#detectType(bg);
|
package/package.json
CHANGED