@rogieking/figui3 3.20.3 → 3.21.0
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 +45 -14
- package/fig.js +282 -33
- package/package.json +1 -1
package/components.css
CHANGED
|
@@ -3146,6 +3146,7 @@ fig-input-fill {
|
|
|
3146
3146
|
}
|
|
3147
3147
|
fig-input-gradient {
|
|
3148
3148
|
--height: 1.5rem;
|
|
3149
|
+
--chit-height: var(--height);
|
|
3149
3150
|
position: relative;
|
|
3150
3151
|
height: var(--height);
|
|
3151
3152
|
width: 100%;
|
|
@@ -3157,12 +3158,34 @@ fig-input-gradient {
|
|
|
3157
3158
|
outline: 1px solid var(--figma-color-border-selected) !important;
|
|
3158
3159
|
outline-offset: -1px !important;
|
|
3159
3160
|
}
|
|
3160
|
-
|
|
3161
|
+
|
|
3162
|
+
&[edit="false"] {
|
|
3163
|
+
pointer-events: none;
|
|
3164
|
+
|
|
3165
|
+
&:focus,
|
|
3166
|
+
&:active,
|
|
3167
|
+
&:focus-within {
|
|
3168
|
+
outline: none !important;
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3172
|
+
&[edit="picker"] {
|
|
3173
|
+
& > fig-fill-picker {
|
|
3174
|
+
display: contents;
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
& > fig-chit,
|
|
3178
|
+
& > fig-fill-picker > fig-chit {
|
|
3161
3179
|
--padding: 0;
|
|
3162
3180
|
--width: 100%;
|
|
3181
|
+
--height: var(--chit-height);
|
|
3163
3182
|
flex: 1 1 auto;
|
|
3164
3183
|
width: 100% !important;
|
|
3165
3184
|
min-width: 0 !important;
|
|
3185
|
+
min-height: var(--chit-height) !important;
|
|
3186
|
+
}
|
|
3187
|
+
&[size="large"] {
|
|
3188
|
+
--height: 3rem;
|
|
3166
3189
|
}
|
|
3167
3190
|
|
|
3168
3191
|
.fig-input-gradient-track {
|
|
@@ -3194,7 +3217,7 @@ fig-input-palette {
|
|
|
3194
3217
|
display: flex;
|
|
3195
3218
|
flex-wrap: nowrap;
|
|
3196
3219
|
gap: 0;
|
|
3197
|
-
border-radius: var(--radius-
|
|
3220
|
+
border-radius: var(--radius-small);
|
|
3198
3221
|
overflow: hidden;
|
|
3199
3222
|
grid-area: inputs;
|
|
3200
3223
|
min-width: 0;
|
|
@@ -3211,9 +3234,15 @@ fig-input-palette {
|
|
|
3211
3234
|
border-radius: var(--radius-medium);
|
|
3212
3235
|
background-color: var(--figma-color-bg-secondary);
|
|
3213
3236
|
width: 100%;
|
|
3237
|
+
gap: var(--spacer-1);
|
|
3238
|
+
place-items: center;
|
|
3214
3239
|
|
|
3215
3240
|
.palette-colors {
|
|
3216
3241
|
display: flex;
|
|
3242
|
+
--palette-colors-height: calc(1.5rem - var(--spacer-1));
|
|
3243
|
+
height: var(--palette-colors-height);
|
|
3244
|
+
margin-left: var(--spacer-1);
|
|
3245
|
+
|
|
3217
3246
|
background-color: var(--figma-color-bg-secondary);
|
|
3218
3247
|
fig-input-color {
|
|
3219
3248
|
width: 100%;
|
|
@@ -3223,10 +3252,11 @@ fig-input-palette {
|
|
|
3223
3252
|
--padding: 0px;
|
|
3224
3253
|
--border-radius: 0px;
|
|
3225
3254
|
--width: 100%;
|
|
3255
|
+
--height: var(--palette-colors-height);
|
|
3256
|
+
--size: var(--palette-colors-height);
|
|
3226
3257
|
flex: 1;
|
|
3227
3258
|
min-width: 0;
|
|
3228
3259
|
width: 100% !important;
|
|
3229
|
-
height: var(--size);
|
|
3230
3260
|
border-radius: 0 !important;
|
|
3231
3261
|
input,
|
|
3232
3262
|
&::before,
|
|
@@ -3248,6 +3278,11 @@ fig-input-palette {
|
|
|
3248
3278
|
grid-template-areas: "inputs inputs";
|
|
3249
3279
|
}
|
|
3250
3280
|
}
|
|
3281
|
+
&[color-strip="false"] {
|
|
3282
|
+
.palette-colors-inline {
|
|
3283
|
+
display: none !important;
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3251
3286
|
.palette-colors-expanded {
|
|
3252
3287
|
display: none;
|
|
3253
3288
|
flex-direction: column;
|
|
@@ -4375,17 +4410,13 @@ fig-preview {
|
|
|
4375
4410
|
}
|
|
4376
4411
|
}
|
|
4377
4412
|
|
|
4378
|
-
.fig-fill-picker-gradient-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
left: 0;
|
|
4386
|
-
right: 0;
|
|
4387
|
-
bottom: 0;
|
|
4388
|
-
pointer-events: none;
|
|
4413
|
+
.fig-fill-picker-gradient-preview {
|
|
4414
|
+
display: block;
|
|
4415
|
+
.fig-fill-picker-gradient-bar-input {
|
|
4416
|
+
--width: 100%;
|
|
4417
|
+
--height: 100%;
|
|
4418
|
+
aspect-ratio: 1/1;
|
|
4419
|
+
}
|
|
4389
4420
|
}
|
|
4390
4421
|
|
|
4391
4422
|
.fig-fill-picker-gradient-stops {
|
package/fig.js
CHANGED
|
@@ -5053,6 +5053,136 @@ function gradientInterpolationClause(gradient) {
|
|
|
5053
5053
|
return `in ${normalized.interpolationSpace}`;
|
|
5054
5054
|
}
|
|
5055
5055
|
|
|
5056
|
+
function figHexToRGB(hex) {
|
|
5057
|
+
const h = hex.replace(/^#/, "");
|
|
5058
|
+
return {
|
|
5059
|
+
r: parseInt(h.substring(0, 2), 16),
|
|
5060
|
+
g: parseInt(h.substring(2, 4), 16),
|
|
5061
|
+
b: parseInt(h.substring(4, 6), 16),
|
|
5062
|
+
};
|
|
5063
|
+
}
|
|
5064
|
+
|
|
5065
|
+
function figRGBToLinear(c) {
|
|
5066
|
+
const s = c / 255;
|
|
5067
|
+
return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
5068
|
+
}
|
|
5069
|
+
|
|
5070
|
+
function figLinearToSRGB(c) {
|
|
5071
|
+
const v = c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
5072
|
+
return Math.round(Math.max(0, Math.min(1, v)) * 255);
|
|
5073
|
+
}
|
|
5074
|
+
|
|
5075
|
+
function figRGBToOklab(r, g, b) {
|
|
5076
|
+
const lr = figRGBToLinear(r);
|
|
5077
|
+
const lg = figRGBToLinear(g);
|
|
5078
|
+
const lb = figRGBToLinear(b);
|
|
5079
|
+
const l_ = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);
|
|
5080
|
+
const m_ = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);
|
|
5081
|
+
const s_ = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);
|
|
5082
|
+
return {
|
|
5083
|
+
l: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
|
|
5084
|
+
a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
|
|
5085
|
+
b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,
|
|
5086
|
+
};
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
function figOklabToRGB(L, a, b) {
|
|
5090
|
+
const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
|
|
5091
|
+
const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
|
|
5092
|
+
const s_ = L - 0.0894841775 * a - 1.291485548 * b;
|
|
5093
|
+
const l = l_ * l_ * l_;
|
|
5094
|
+
const m = m_ * m_ * m_;
|
|
5095
|
+
const s = s_ * s_ * s_;
|
|
5096
|
+
return {
|
|
5097
|
+
r: figLinearToSRGB(+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
|
|
5098
|
+
g: figLinearToSRGB(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
|
|
5099
|
+
b: figLinearToSRGB(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),
|
|
5100
|
+
};
|
|
5101
|
+
}
|
|
5102
|
+
|
|
5103
|
+
function figOklabToOklch(L, a, b) {
|
|
5104
|
+
return { l: L, c: Math.sqrt(a * a + b * b), h: (Math.atan2(b, a) * 180) / Math.PI };
|
|
5105
|
+
}
|
|
5106
|
+
|
|
5107
|
+
function figOklchToOklab(l, c, h) {
|
|
5108
|
+
const hRad = (h * Math.PI) / 180;
|
|
5109
|
+
return { l, a: c * Math.cos(hRad), b: c * Math.sin(hRad) };
|
|
5110
|
+
}
|
|
5111
|
+
|
|
5112
|
+
function figInterpolateHue(h1, h2, t, mode) {
|
|
5113
|
+
let a = ((h1 % 360) + 360) % 360;
|
|
5114
|
+
let b = ((h2 % 360) + 360) % 360;
|
|
5115
|
+
let diff = b - a;
|
|
5116
|
+
switch (mode) {
|
|
5117
|
+
case "longer":
|
|
5118
|
+
if (diff > 0 && diff < 180) diff -= 360;
|
|
5119
|
+
else if (diff < 0 && diff > -180) diff += 360;
|
|
5120
|
+
else if (diff === 0) diff = 0;
|
|
5121
|
+
break;
|
|
5122
|
+
case "increasing":
|
|
5123
|
+
if (diff < 0) diff += 360;
|
|
5124
|
+
break;
|
|
5125
|
+
case "decreasing":
|
|
5126
|
+
if (diff > 0) diff -= 360;
|
|
5127
|
+
break;
|
|
5128
|
+
default:
|
|
5129
|
+
if (diff > 180) diff -= 360;
|
|
5130
|
+
else if (diff < -180) diff += 360;
|
|
5131
|
+
break;
|
|
5132
|
+
}
|
|
5133
|
+
return ((a + diff * t) % 360 + 360) % 360;
|
|
5134
|
+
}
|
|
5135
|
+
|
|
5136
|
+
function figSampleGradientAt(stops, position, interpolationSpace, hueInterpolation) {
|
|
5137
|
+
const sorted = [...stops].sort((a, b) => a.position - b.position);
|
|
5138
|
+
const pos = position * 100;
|
|
5139
|
+
if (sorted.length === 0) return "#888888";
|
|
5140
|
+
if (pos <= sorted[0].position) return sorted[0].color;
|
|
5141
|
+
if (pos >= sorted[sorted.length - 1].position) return sorted[sorted.length - 1].color;
|
|
5142
|
+
|
|
5143
|
+
let i = 0;
|
|
5144
|
+
while (i < sorted.length - 1 && sorted[i + 1].position < pos) i++;
|
|
5145
|
+
const s1 = sorted[i];
|
|
5146
|
+
const s2 = sorted[i + 1];
|
|
5147
|
+
const range = s2.position - s1.position;
|
|
5148
|
+
const t = range > 0 ? (pos - s1.position) / range : 0;
|
|
5149
|
+
|
|
5150
|
+
const c1 = figHexToRGB(s1.color);
|
|
5151
|
+
const c2 = figHexToRGB(s2.color);
|
|
5152
|
+
|
|
5153
|
+
let r, g, b;
|
|
5154
|
+
const space = interpolationSpace || "oklab";
|
|
5155
|
+
|
|
5156
|
+
if (space === "srgb-linear") {
|
|
5157
|
+
const lr1 = figRGBToLinear(c1.r), lg1 = figRGBToLinear(c1.g), lb1 = figRGBToLinear(c1.b);
|
|
5158
|
+
const lr2 = figRGBToLinear(c2.r), lg2 = figRGBToLinear(c2.g), lb2 = figRGBToLinear(c2.b);
|
|
5159
|
+
r = figLinearToSRGB(lr1 + (lr2 - lr1) * t);
|
|
5160
|
+
g = figLinearToSRGB(lg1 + (lg2 - lg1) * t);
|
|
5161
|
+
b = figLinearToSRGB(lb1 + (lb2 - lb1) * t);
|
|
5162
|
+
} else if (space === "oklch") {
|
|
5163
|
+
const lab1 = figRGBToOklab(c1.r, c1.g, c1.b);
|
|
5164
|
+
const lab2 = figRGBToOklab(c2.r, c2.g, c2.b);
|
|
5165
|
+
const lch1 = figOklabToOklch(lab1.l, lab1.a, lab1.b);
|
|
5166
|
+
const lch2 = figOklabToOklch(lab2.l, lab2.a, lab2.b);
|
|
5167
|
+
const L = lch1.l + (lch2.l - lch1.l) * t;
|
|
5168
|
+
const C = lch1.c + (lch2.c - lch1.c) * t;
|
|
5169
|
+
const H = figInterpolateHue(lch1.h, lch2.h, t, hueInterpolation || "shorter");
|
|
5170
|
+
const lab = figOklchToOklab(L, C, H);
|
|
5171
|
+
const rgb = figOklabToRGB(lab.l, lab.a, lab.b);
|
|
5172
|
+
r = rgb.r; g = rgb.g; b = rgb.b;
|
|
5173
|
+
} else {
|
|
5174
|
+
const lab1 = figRGBToOklab(c1.r, c1.g, c1.b);
|
|
5175
|
+
const lab2 = figRGBToOklab(c2.r, c2.g, c2.b);
|
|
5176
|
+
const L = lab1.l + (lab2.l - lab1.l) * t;
|
|
5177
|
+
const a = lab1.a + (lab2.a - lab1.a) * t;
|
|
5178
|
+
const bv = lab1.b + (lab2.b - lab1.b) * t;
|
|
5179
|
+
const rgb = figOklabToRGB(L, a, bv);
|
|
5180
|
+
r = rgb.r; g = rgb.g; b = rgb.b;
|
|
5181
|
+
}
|
|
5182
|
+
|
|
5183
|
+
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`.toUpperCase();
|
|
5184
|
+
}
|
|
5185
|
+
|
|
5056
5186
|
function hslToP3(h, s, l) {
|
|
5057
5187
|
const sRGB = hslToSRGB(h, s, l);
|
|
5058
5188
|
return sRGB.map((c) => +(c / 255).toFixed(4));
|
|
@@ -6124,13 +6254,24 @@ class FigInputGradient extends HTMLElement {
|
|
|
6124
6254
|
}
|
|
6125
6255
|
|
|
6126
6256
|
static get observedAttributes() {
|
|
6127
|
-
return ["value", "disabled"];
|
|
6257
|
+
return ["value", "disabled", "edit"];
|
|
6258
|
+
}
|
|
6259
|
+
|
|
6260
|
+
get #editMode() {
|
|
6261
|
+
const attr = this.getAttribute("edit");
|
|
6262
|
+
if (attr === "false") return "false";
|
|
6263
|
+
if (attr === "picker") return "picker";
|
|
6264
|
+
return "true";
|
|
6265
|
+
}
|
|
6266
|
+
|
|
6267
|
+
get #isEditable() {
|
|
6268
|
+
return this.#editMode === "true";
|
|
6128
6269
|
}
|
|
6129
6270
|
|
|
6130
6271
|
connectedCallback() {
|
|
6131
6272
|
this.#parseValue();
|
|
6132
6273
|
this.#render();
|
|
6133
|
-
document.addEventListener("keydown", this.#onKeyDown);
|
|
6274
|
+
if (this.#isEditable) document.addEventListener("keydown", this.#onKeyDown);
|
|
6134
6275
|
}
|
|
6135
6276
|
|
|
6136
6277
|
disconnectedCallback() {
|
|
@@ -6252,7 +6393,8 @@ class FigInputGradient extends HTMLElement {
|
|
|
6252
6393
|
(a, b) => a.position - b.position,
|
|
6253
6394
|
);
|
|
6254
6395
|
const stops = sorted.map((s) => `${s.color} ${s.position}%`).join(", ");
|
|
6255
|
-
|
|
6396
|
+
const interp = gradientInterpolationClause(this.#gradient);
|
|
6397
|
+
return `linear-gradient(${this.#gradient.angle}deg ${interp}, ${stops})`;
|
|
6256
6398
|
}
|
|
6257
6399
|
|
|
6258
6400
|
#buildStopHandles() {
|
|
@@ -6270,31 +6412,69 @@ class FigInputGradient extends HTMLElement {
|
|
|
6270
6412
|
|
|
6271
6413
|
#render() {
|
|
6272
6414
|
const disabled = this.hasAttribute("disabled");
|
|
6415
|
+
const mode = this.#editMode;
|
|
6416
|
+
|
|
6417
|
+
if (mode === "picker") {
|
|
6418
|
+
const experimental = this.getAttribute("experimental");
|
|
6419
|
+
const expAttr = experimental ? ` experimental="${experimental}"` : "";
|
|
6420
|
+
const gradientValue = JSON.stringify(this.value);
|
|
6421
|
+
this.innerHTML = `
|
|
6422
|
+
<fig-fill-picker mode="gradient"${expAttr} value='${gradientValue}'${disabled ? " disabled" : ""}>
|
|
6423
|
+
<fig-chit size="medium" background="${this.#buildGradientCSS()}"${disabled ? " disabled" : ""}></fig-chit>
|
|
6424
|
+
</fig-fill-picker>`;
|
|
6425
|
+
this.#chit = this.querySelector("fig-chit");
|
|
6426
|
+
this.#track = null;
|
|
6427
|
+
this.#setupPickerEvents();
|
|
6428
|
+
return;
|
|
6429
|
+
}
|
|
6430
|
+
|
|
6273
6431
|
this.innerHTML = `
|
|
6274
6432
|
<fig-chit size="medium" background="${this.#buildGradientCSS()}"${disabled ? " disabled" : ""}></fig-chit>
|
|
6275
|
-
|
|
6433
|
+
${mode === "true" ? `<div class="fig-input-gradient-track">${this.#buildStopHandles()}</div>` : ""}`;
|
|
6276
6434
|
this.#chit = this.querySelector("fig-chit");
|
|
6277
6435
|
this.#track = this.querySelector(".fig-input-gradient-track");
|
|
6278
|
-
|
|
6279
|
-
|
|
6436
|
+
|
|
6437
|
+
if (mode === "true") {
|
|
6438
|
+
this.#setupGhostHandle();
|
|
6439
|
+
this.#setupEventListeners();
|
|
6440
|
+
requestAnimationFrame(() => this.#repositionHandles());
|
|
6441
|
+
}
|
|
6442
|
+
}
|
|
6443
|
+
|
|
6444
|
+
#setupPickerEvents() {
|
|
6445
|
+
const picker = this.querySelector("fig-fill-picker");
|
|
6446
|
+
if (!picker) return;
|
|
6447
|
+
picker.anchorElement = this;
|
|
6448
|
+
|
|
6449
|
+
const syncFromPicker = (e) => {
|
|
6450
|
+
e.stopPropagation();
|
|
6451
|
+
const detail = e.detail;
|
|
6452
|
+
if (!detail?.gradient) return;
|
|
6453
|
+
this.#gradient = normalizeGradientConfig({
|
|
6454
|
+
...this.#gradient,
|
|
6455
|
+
...detail.gradient,
|
|
6456
|
+
});
|
|
6457
|
+
this.#syncChit();
|
|
6458
|
+
};
|
|
6459
|
+
|
|
6460
|
+
picker.addEventListener("input", (e) => {
|
|
6461
|
+
syncFromPicker(e);
|
|
6462
|
+
this.#emitInput();
|
|
6463
|
+
});
|
|
6464
|
+
|
|
6465
|
+
picker.addEventListener("change", (e) => {
|
|
6466
|
+
syncFromPicker(e);
|
|
6467
|
+
this.#emitChange();
|
|
6468
|
+
});
|
|
6280
6469
|
}
|
|
6281
6470
|
|
|
6282
6471
|
#sampleGradientColor(position) {
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
} catch {
|
|
6290
|
-
/* skip invalid */
|
|
6291
|
-
}
|
|
6292
|
-
}
|
|
6293
|
-
ctx.fillStyle = grad;
|
|
6294
|
-
ctx.fillRect(0, 0, 256, 1);
|
|
6295
|
-
const px = Math.round(Math.max(0, Math.min(255, position * 255)));
|
|
6296
|
-
const [r, g, b] = ctx.getImageData(px, 0, 1, 1).data;
|
|
6297
|
-
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`.toUpperCase();
|
|
6472
|
+
return figSampleGradientAt(
|
|
6473
|
+
this.#gradient.stops,
|
|
6474
|
+
position,
|
|
6475
|
+
this.#gradient.interpolationSpace,
|
|
6476
|
+
this.#gradient.hueInterpolation,
|
|
6477
|
+
);
|
|
6298
6478
|
}
|
|
6299
6479
|
|
|
6300
6480
|
#setupGhostHandle() {
|
|
@@ -6430,6 +6610,18 @@ class FigInputGradient extends HTMLElement {
|
|
|
6430
6610
|
});
|
|
6431
6611
|
};
|
|
6432
6612
|
|
|
6613
|
+
#repositionHandles() {
|
|
6614
|
+
if (!this.#track) return;
|
|
6615
|
+
const stops = this.#gradient.stops;
|
|
6616
|
+
this.#track
|
|
6617
|
+
.querySelectorAll("fig-handle:not(.fig-input-gradient-ghost)")
|
|
6618
|
+
.forEach((h, i) => {
|
|
6619
|
+
if (i >= stops.length) return;
|
|
6620
|
+
h.removeAttribute("value");
|
|
6621
|
+
h.setAttribute("value", `${stops[i].position}% 50%`);
|
|
6622
|
+
});
|
|
6623
|
+
}
|
|
6624
|
+
|
|
6433
6625
|
#syncHandles() {
|
|
6434
6626
|
if (!this.#track) return;
|
|
6435
6627
|
const handles = this.#track.querySelectorAll(
|
|
@@ -6442,6 +6634,7 @@ class FigInputGradient extends HTMLElement {
|
|
|
6442
6634
|
this.#track.innerHTML = this.#buildStopHandles();
|
|
6443
6635
|
if (ghost) this.#track.appendChild(ghost);
|
|
6444
6636
|
this.#reobserveHandleColors();
|
|
6637
|
+
requestAnimationFrame(() => this.#repositionHandles());
|
|
6445
6638
|
return;
|
|
6446
6639
|
}
|
|
6447
6640
|
|
|
@@ -6720,6 +6913,14 @@ class FigInputGradient extends HTMLElement {
|
|
|
6720
6913
|
case "disabled":
|
|
6721
6914
|
this.#syncDisabled();
|
|
6722
6915
|
break;
|
|
6916
|
+
case "edit":
|
|
6917
|
+
this.#render();
|
|
6918
|
+
if (this.#isEditable) {
|
|
6919
|
+
document.addEventListener("keydown", this.#onKeyDown);
|
|
6920
|
+
} else {
|
|
6921
|
+
document.removeEventListener("keydown", this.#onKeyDown);
|
|
6922
|
+
}
|
|
6923
|
+
break;
|
|
6723
6924
|
}
|
|
6724
6925
|
}
|
|
6725
6926
|
|
|
@@ -11522,8 +11723,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
11522
11723
|
</fig-tooltip>
|
|
11523
11724
|
</fig-field>
|
|
11524
11725
|
<fig-preview class="fig-fill-picker-gradient-preview">
|
|
11525
|
-
<
|
|
11526
|
-
<div class="fig-fill-picker-gradient-stops-handles"></div>
|
|
11726
|
+
<fig-input-gradient class="fig-fill-picker-gradient-bar-input" edit="true" size="large" value='${JSON.stringify({ type: "gradient", gradient: gradientToValueShape(this.#gradient) })}'></fig-input-gradient>
|
|
11527
11727
|
</fig-preview>
|
|
11528
11728
|
<fig-field class="fig-fill-picker-gradient-interpolation" direction="horizontal">
|
|
11529
11729
|
<label>Mixing</label>
|
|
@@ -11654,6 +11854,30 @@ class FigFillPicker extends HTMLElement {
|
|
|
11654
11854
|
this.#updateGradientUI();
|
|
11655
11855
|
this.#emitInput();
|
|
11656
11856
|
});
|
|
11857
|
+
|
|
11858
|
+
// Embedded gradient bar input
|
|
11859
|
+
const gradientBarInput = container.querySelector(".fig-fill-picker-gradient-bar-input");
|
|
11860
|
+
if (gradientBarInput) {
|
|
11861
|
+
const syncFromBarInput = (e) => {
|
|
11862
|
+
e.stopPropagation();
|
|
11863
|
+
const detail = e.detail;
|
|
11864
|
+
if (!detail?.gradient) return;
|
|
11865
|
+
this.#gradient = normalizeGradientConfig({
|
|
11866
|
+
...this.#gradient,
|
|
11867
|
+
...detail.gradient,
|
|
11868
|
+
});
|
|
11869
|
+
this.#updateChit();
|
|
11870
|
+
this.#updateGradientStopsList();
|
|
11871
|
+
};
|
|
11872
|
+
gradientBarInput.addEventListener("input", (e) => {
|
|
11873
|
+
syncFromBarInput(e);
|
|
11874
|
+
this.#emitInput();
|
|
11875
|
+
});
|
|
11876
|
+
gradientBarInput.addEventListener("change", (e) => {
|
|
11877
|
+
syncFromBarInput(e);
|
|
11878
|
+
this.#emitChange();
|
|
11879
|
+
});
|
|
11880
|
+
}
|
|
11657
11881
|
}
|
|
11658
11882
|
|
|
11659
11883
|
#updateGradientUI() {
|
|
@@ -11699,14 +11923,14 @@ class FigFillPicker extends HTMLElement {
|
|
|
11699
11923
|
#updateGradientPreview() {
|
|
11700
11924
|
if (!this.#dialog) return;
|
|
11701
11925
|
|
|
11702
|
-
const
|
|
11703
|
-
".fig-fill-picker-gradient-
|
|
11926
|
+
const barInput = this.#dialog.querySelector(
|
|
11927
|
+
".fig-fill-picker-gradient-bar-input",
|
|
11704
11928
|
);
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11929
|
+
if (barInput) {
|
|
11930
|
+
barInput.setAttribute(
|
|
11931
|
+
"value",
|
|
11932
|
+
JSON.stringify({ type: "gradient", gradient: gradientToValueShape(this.#gradient) }),
|
|
11933
|
+
);
|
|
11710
11934
|
}
|
|
11711
11935
|
|
|
11712
11936
|
this.#updateChit();
|
|
@@ -11720,6 +11944,31 @@ class FigFillPicker extends HTMLElement {
|
|
|
11720
11944
|
);
|
|
11721
11945
|
if (!list) return;
|
|
11722
11946
|
|
|
11947
|
+
const existingRows = list.querySelectorAll(
|
|
11948
|
+
".fig-fill-picker-gradient-stop-row",
|
|
11949
|
+
);
|
|
11950
|
+
|
|
11951
|
+
if (existingRows.length === this.#gradient.stops.length) {
|
|
11952
|
+
this.#gradient.stops.forEach((stop, index) => {
|
|
11953
|
+
const row = existingRows[index];
|
|
11954
|
+
row.dataset.index = index;
|
|
11955
|
+
const posInput = row.querySelector(".fig-fill-picker-stop-position");
|
|
11956
|
+
if (posInput) posInput.setAttribute("value", stop.position);
|
|
11957
|
+
const colorInput = row.querySelector(".fig-fill-picker-stop-color");
|
|
11958
|
+
if (colorInput) colorInput.setAttribute("value", stop.color);
|
|
11959
|
+
const removeBtn = row.querySelector(".fig-fill-picker-stop-remove");
|
|
11960
|
+
if (removeBtn) {
|
|
11961
|
+
if (this.#gradient.stops.length <= 2) removeBtn.setAttribute("disabled", "");
|
|
11962
|
+
else removeBtn.removeAttribute("disabled");
|
|
11963
|
+
}
|
|
11964
|
+
});
|
|
11965
|
+
return;
|
|
11966
|
+
}
|
|
11967
|
+
|
|
11968
|
+
this.#rebuildGradientStopsList(list);
|
|
11969
|
+
}
|
|
11970
|
+
|
|
11971
|
+
#rebuildGradientStopsList(list) {
|
|
11723
11972
|
list.innerHTML = this.#gradient.stops
|
|
11724
11973
|
.map(
|
|
11725
11974
|
(stop, index) => `
|
|
@@ -11740,7 +11989,6 @@ class FigFillPicker extends HTMLElement {
|
|
|
11740
11989
|
)
|
|
11741
11990
|
.join("");
|
|
11742
11991
|
|
|
11743
|
-
// Setup event listeners for each stop
|
|
11744
11992
|
list
|
|
11745
11993
|
.querySelectorAll(".fig-fill-picker-gradient-stop-row")
|
|
11746
11994
|
.forEach((row) => {
|
|
@@ -11798,9 +12046,10 @@ class FigFillPicker extends HTMLElement {
|
|
|
11798
12046
|
const isP3 = this.#gamut === "display-p3";
|
|
11799
12047
|
const stops = gradient.stops
|
|
11800
12048
|
.map((s) => {
|
|
12049
|
+
const alpha = (s.opacity ?? 100) / 100;
|
|
11801
12050
|
const color = isP3
|
|
11802
|
-
? this.#hexToP3(s.color,
|
|
11803
|
-
: this.#hexToRGBA(s.color,
|
|
12051
|
+
? this.#hexToP3(s.color, alpha)
|
|
12052
|
+
: this.#hexToRGBA(s.color, alpha);
|
|
11804
12053
|
return `${color} ${s.position}%`;
|
|
11805
12054
|
})
|
|
11806
12055
|
.join(", ");
|
package/package.json
CHANGED