@rogieking/figui3 11.4.1 → 11.5.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/.cursor/skills/fig-editor/SKILL.md +8 -6
- package/.cursor/skills/fig-editor/components.md +55 -0
- package/.cursor/skills/fig-editor/reference.md +25 -0
- package/.cursor/skills/figui3/components.md +1 -0
- package/.cursor/skills/figui3/react.md +2 -0
- package/.cursor/skills/figui3/reference.md +2 -0
- package/CHANGELOG.md +27 -0
- package/README.md +43 -0
- package/components.css +60 -11
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +3 -3
- package/dist/fig-property.css +1 -0
- package/dist/fig-property.js +1 -0
- package/dist/fig.css +1 -1
- package/dist/fig.js +2 -2
- package/fig-editor.css +48 -24
- package/fig-editor.js +207 -81
- package/fig-property.css +116 -0
- package/fig-property.js +220 -0
- package/fig.js +9 -2
- package/package.json +9 -2
package/fig-editor.css
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
/* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
|
|
2
2
|
@import url("fig-layer.css");
|
|
3
|
+
@import url("fig-property.css");
|
|
4
|
+
|
|
5
|
+
fig-input-point {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
width: 8.9375rem;
|
|
8
|
+
|
|
9
|
+
&[full]:not([full="false"]) {
|
|
10
|
+
width: 100%;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
> fig-input-combo {
|
|
14
|
+
width: 100%;
|
|
15
|
+
|
|
16
|
+
> fig-input-number {
|
|
17
|
+
flex: 1 1 0;
|
|
18
|
+
width: auto;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
3
22
|
|
|
4
23
|
:root,
|
|
5
24
|
:host {
|
|
@@ -230,7 +249,8 @@ fig-fill-picker {
|
|
|
230
249
|
grid-template-rows: 1fr 1fr;
|
|
231
250
|
align-items: center;
|
|
232
251
|
padding-right: var(--spacer-3);
|
|
233
|
-
gap: var(--spacer-2);
|
|
252
|
+
row-gap: var(--spacer-2);
|
|
253
|
+
column-gap: var(--spacer-2);
|
|
234
254
|
padding-bottom: var(--spacer-1);
|
|
235
255
|
|
|
236
256
|
.fig-fill-picker-eyedropper {
|
|
@@ -261,20 +281,9 @@ fig-fill-picker {
|
|
|
261
281
|
}
|
|
262
282
|
|
|
263
283
|
.fig-fill-picker-inputs {
|
|
264
|
-
/* Override labelless 1fr/2fr split so mode select matches eyedropper width
|
|
265
|
-
and color inputs take the remaining row. */
|
|
266
|
-
&:not([direction="vertical"]):not(:has(> label)) {
|
|
267
|
-
grid-template-columns:
|
|
268
|
-
var(--fig-field-left-padding)
|
|
269
|
-
3.5rem
|
|
270
|
-
var(--spacer-2)
|
|
271
|
-
minmax(0, 1fr)
|
|
272
|
-
var(--fig-field-right-padding);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
284
|
.fig-fill-picker-input-mode {
|
|
276
285
|
width: 3.5rem;
|
|
277
|
-
flex
|
|
286
|
+
flex: unset;
|
|
278
287
|
align-self: center;
|
|
279
288
|
}
|
|
280
289
|
|
|
@@ -364,7 +373,7 @@ fig-fill-picker {
|
|
|
364
373
|
padding-right: var(--spacer-2);
|
|
365
374
|
gap: var(--spacer-1);
|
|
366
375
|
|
|
367
|
-
> *:not(
|
|
376
|
+
> *:not([slot="leading"]):not([slot="trailing"]):not(label) {
|
|
368
377
|
grid-area: unset;
|
|
369
378
|
}
|
|
370
379
|
}
|
|
@@ -454,16 +463,16 @@ fig-fill-picker {
|
|
|
454
463
|
}
|
|
455
464
|
|
|
456
465
|
.fig-fill-picker-gradient-stop-row {
|
|
457
|
-
padding-right: var(--spacer-2);
|
|
458
|
-
display: flex;
|
|
459
|
-
padding-left: var(--spacer-3);
|
|
460
|
-
gap: var(--spacer-2);
|
|
461
|
-
|
|
462
466
|
&.dragging {
|
|
463
467
|
background-color: var(--figma-color-bg-selected);
|
|
464
468
|
}
|
|
465
469
|
|
|
466
|
-
|
|
470
|
+
.fig-fill-picker-gradient-stop-inputs {
|
|
471
|
+
width: 100%;
|
|
472
|
+
min-width: 0;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.fig-fill-picker-stop-position {
|
|
467
476
|
flex: 0;
|
|
468
477
|
flex-basis: 3rem;
|
|
469
478
|
min-width: 0;
|
|
@@ -494,7 +503,7 @@ fig-fill-picker {
|
|
|
494
503
|
padding-right: var(--spacer-2);
|
|
495
504
|
gap: var(--spacer-2);
|
|
496
505
|
|
|
497
|
-
> *:not(
|
|
506
|
+
> *:not([slot="leading"]):not([slot="trailing"]):not(label) {
|
|
498
507
|
grid-area: unset;
|
|
499
508
|
}
|
|
500
509
|
|
|
@@ -937,18 +946,28 @@ fig-select-option {
|
|
|
937
946
|
pointer-events: none;
|
|
938
947
|
z-index: 1000000;
|
|
939
948
|
border-radius: 1px;
|
|
940
|
-
&::before{
|
|
949
|
+
&::before {
|
|
941
950
|
content: "";
|
|
942
951
|
position: absolute;
|
|
943
952
|
top: 0;
|
|
944
|
-
left:
|
|
953
|
+
left: 0;
|
|
945
954
|
width: 100%;
|
|
946
955
|
height: 100%;
|
|
947
956
|
background: var(--figma-color-border-selected);
|
|
948
957
|
}
|
|
949
958
|
|
|
950
959
|
&.fig-reorder-indicator-ring {
|
|
951
|
-
|
|
960
|
+
&[data-axis="vertical"]::before {
|
|
961
|
+
left: var(--spacer-1);
|
|
962
|
+
width: calc(100% - var(--spacer-1));
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
&[data-axis="horizontal"]::before {
|
|
966
|
+
top: var(--spacer-1);
|
|
967
|
+
height: calc(100% - var(--spacer-1));
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
&::after {
|
|
952
971
|
content: "";
|
|
953
972
|
position: absolute;
|
|
954
973
|
top: 1px;
|
|
@@ -959,6 +978,11 @@ fig-select-option {
|
|
|
959
978
|
border: 2px solid var(--figma-color-border-selected);
|
|
960
979
|
border-radius: 50%;
|
|
961
980
|
}
|
|
981
|
+
|
|
982
|
+
&[data-axis="horizontal"]::after {
|
|
983
|
+
top: 0;
|
|
984
|
+
left: 1px;
|
|
985
|
+
}
|
|
962
986
|
}
|
|
963
987
|
|
|
964
988
|
&[data-axis="vertical"] {
|
package/fig-editor.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
|
|
2
2
|
import "./fig.js";
|
|
3
|
+
import "./fig-property.js";
|
|
3
4
|
|
|
4
5
|
function figEditorDefineElement(name, constructor) {
|
|
5
6
|
if (!customElements.get(name)) {
|
|
@@ -82,6 +83,114 @@ function figEditorCreateElement(tagName, attributes, children) {
|
|
|
82
83
|
return figEditorAppendChildren(element, children);
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Paired X/Y number inputs for editing a point.
|
|
88
|
+
*
|
|
89
|
+
* @element fig-input-point
|
|
90
|
+
* @attr {number} x - Horizontal coordinate
|
|
91
|
+
* @attr {number} y - Vertical coordinate
|
|
92
|
+
* @attr {string} units - Unit string forwarded to both coordinate inputs
|
|
93
|
+
* @fires input - Emitted while either coordinate is edited with `{ x, y }`
|
|
94
|
+
* @fires change - Emitted when either coordinate is committed with `{ x, y }`
|
|
95
|
+
*/
|
|
96
|
+
class FigInputPoint extends HTMLElement {
|
|
97
|
+
#inputs = {};
|
|
98
|
+
|
|
99
|
+
static get observedAttributes() {
|
|
100
|
+
return ["x", "y", "units"];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
connectedCallback() {
|
|
104
|
+
this.#render();
|
|
105
|
+
this.#sync();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
109
|
+
if (oldValue === newValue || !this.isConnected) return;
|
|
110
|
+
if (name === "units") this.#syncUnits();
|
|
111
|
+
else this.#syncAxis(name);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get value() {
|
|
115
|
+
return {
|
|
116
|
+
x: this.#axisValue("x"),
|
|
117
|
+
y: this.#axisValue("y"),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#render() {
|
|
122
|
+
if (this.#inputs.x && this.#inputs.y) return;
|
|
123
|
+
|
|
124
|
+
const createInput = (axis) => {
|
|
125
|
+
const label = axis.toUpperCase();
|
|
126
|
+
const input = figEditorCreateElement(
|
|
127
|
+
"fig-input-number",
|
|
128
|
+
{
|
|
129
|
+
full: true,
|
|
130
|
+
"aria-label": `${label} coordinate`,
|
|
131
|
+
"data-axis": axis,
|
|
132
|
+
},
|
|
133
|
+
figEditorCreateElement("span", { slot: "prepend" }, label),
|
|
134
|
+
);
|
|
135
|
+
input.addEventListener("input", (event) =>
|
|
136
|
+
this.#handleInput(axis, event),
|
|
137
|
+
);
|
|
138
|
+
input.addEventListener("change", (event) =>
|
|
139
|
+
this.#handleInput(axis, event),
|
|
140
|
+
);
|
|
141
|
+
this.#inputs[axis] = input;
|
|
142
|
+
return input;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
this.replaceChildren(
|
|
146
|
+
figEditorCreateElement(
|
|
147
|
+
"fig-input-combo",
|
|
148
|
+
{ full: true },
|
|
149
|
+
["x", "y"].map(createInput),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
#sync() {
|
|
155
|
+
this.#syncAxis("x");
|
|
156
|
+
this.#syncAxis("y");
|
|
157
|
+
this.#syncUnits();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
#syncAxis(axis) {
|
|
161
|
+
const input = this.#inputs[axis];
|
|
162
|
+
if (!input) return;
|
|
163
|
+
const value = String(this.#axisValue(axis));
|
|
164
|
+
if (input.getAttribute("value") !== value) input.setAttribute("value", value);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
#syncUnits() {
|
|
168
|
+
const units = this.getAttribute("units");
|
|
169
|
+
for (const input of Object.values(this.#inputs)) {
|
|
170
|
+
if (units === null) input.removeAttribute("units");
|
|
171
|
+
else input.setAttribute("units", units);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
#axisValue(axis) {
|
|
176
|
+
const value = Number(this.getAttribute(axis));
|
|
177
|
+
return Number.isFinite(value) ? value : 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
#handleInput(axis, event) {
|
|
181
|
+
event.stopPropagation();
|
|
182
|
+
const value = Number(event.detail);
|
|
183
|
+
this.setAttribute(axis, String(Number.isFinite(value) ? value : 0));
|
|
184
|
+
this.dispatchEvent(
|
|
185
|
+
new CustomEvent(event.type, {
|
|
186
|
+
bubbles: true,
|
|
187
|
+
detail: this.value,
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
figEditorDefineElement("fig-input-point", FigInputPoint);
|
|
193
|
+
|
|
85
194
|
function figEditorNormalizePaletteValue(value) {
|
|
86
195
|
let entries = value;
|
|
87
196
|
if (typeof entries === "string") {
|
|
@@ -429,42 +538,27 @@ class FigPaletteEditor extends HTMLElement {
|
|
|
429
538
|
this.#emit(type);
|
|
430
539
|
}
|
|
431
540
|
|
|
432
|
-
#
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
);
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
const currentIndex = Number.parseInt(row?.dataset.index ?? "", 10);
|
|
448
|
-
if (
|
|
449
|
-
this.#disabled ||
|
|
450
|
-
this.#fixed ||
|
|
451
|
-
this.#colors.length <= this.#min ||
|
|
452
|
-
!Number.isInteger(currentIndex)
|
|
453
|
-
) {
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
this.#colors.splice(currentIndex, 1);
|
|
457
|
-
this.#reflectValue();
|
|
458
|
-
this.#render();
|
|
459
|
-
this.#emit("input");
|
|
460
|
-
this.#emit("change");
|
|
461
|
-
});
|
|
462
|
-
return button;
|
|
541
|
+
#removeRow(row) {
|
|
542
|
+
const currentIndex = Number.parseInt(row?.dataset.index ?? "", 10);
|
|
543
|
+
if (
|
|
544
|
+
this.#disabled ||
|
|
545
|
+
this.#fixed ||
|
|
546
|
+
this.#colors.length <= this.#min ||
|
|
547
|
+
!Number.isInteger(currentIndex)
|
|
548
|
+
) {
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
this.#colors.splice(currentIndex, 1);
|
|
552
|
+
this.#reflectValue();
|
|
553
|
+
this.#render();
|
|
554
|
+
this.#emit("input");
|
|
555
|
+
this.#emit("change");
|
|
463
556
|
}
|
|
464
557
|
|
|
465
558
|
#createRow(entry, index) {
|
|
466
559
|
const colorInput = figEditorCreateElement("fig-input-color", {
|
|
467
560
|
className: "fig-palette-editor-color",
|
|
561
|
+
slot: "input",
|
|
468
562
|
value: figEditorPaletteEntryValue(entry),
|
|
469
563
|
text: true,
|
|
470
564
|
alpha: true,
|
|
@@ -494,17 +588,22 @@ class FigPaletteEditor extends HTMLElement {
|
|
|
494
588
|
syncColor(event, "change"),
|
|
495
589
|
);
|
|
496
590
|
|
|
497
|
-
|
|
498
|
-
"fig-
|
|
591
|
+
const row = figEditorCreateElement(
|
|
592
|
+
"fig-property",
|
|
499
593
|
{
|
|
500
594
|
className: "fig-palette-editor-color-row",
|
|
501
595
|
"data-index": index,
|
|
596
|
+
leading: "drag",
|
|
597
|
+
trailing: this.#fixed ? null : "remove",
|
|
598
|
+
"show-trailing": this.#fixed ? null : true,
|
|
502
599
|
},
|
|
503
|
-
|
|
504
|
-
colorInput,
|
|
505
|
-
...(this.#fixed ? [] : [this.#createRemoveButton(index)]),
|
|
506
|
-
],
|
|
600
|
+
colorInput,
|
|
507
601
|
);
|
|
602
|
+
row.addEventListener("remove", (event) => {
|
|
603
|
+
event.stopPropagation();
|
|
604
|
+
this.#removeRow(row);
|
|
605
|
+
});
|
|
606
|
+
return row;
|
|
508
607
|
}
|
|
509
608
|
|
|
510
609
|
#handleReorder = (event) => {
|
|
@@ -594,6 +693,20 @@ class FigPaletteEditor extends HTMLElement {
|
|
|
594
693
|
children.push(figEditorCreateElement("fig-field", {}, addButton));
|
|
595
694
|
}
|
|
596
695
|
this.replaceChildren(...children);
|
|
696
|
+
this.querySelectorAll(".fig-palette-editor-color-row").forEach(
|
|
697
|
+
(row, index) => {
|
|
698
|
+
const remove = row.querySelector(
|
|
699
|
+
':scope > [data-fig-property-action="remove"]',
|
|
700
|
+
);
|
|
701
|
+
if (!remove) return;
|
|
702
|
+
remove.classList.add("fig-palette-editor-remove");
|
|
703
|
+
remove.setAttribute("aria-label", `Remove color ${index + 1}`);
|
|
704
|
+
remove.toggleAttribute(
|
|
705
|
+
"disabled",
|
|
706
|
+
this.#disabled || this.#colors.length <= this.#min,
|
|
707
|
+
);
|
|
708
|
+
},
|
|
709
|
+
);
|
|
597
710
|
}
|
|
598
711
|
}
|
|
599
712
|
figEditorDefineElement("fig-palette-editor", FigPaletteEditor);
|
|
@@ -3460,7 +3573,6 @@ class FigFillPicker extends HTMLElement {
|
|
|
3460
3573
|
eyedropperControl,
|
|
3461
3574
|
figEditorCreateElement("fig-slider", {
|
|
3462
3575
|
type: "hue",
|
|
3463
|
-
variant: "classic",
|
|
3464
3576
|
text: "false",
|
|
3465
3577
|
min: "0",
|
|
3466
3578
|
max: "360",
|
|
@@ -3470,7 +3582,6 @@ class FigFillPicker extends HTMLElement {
|
|
|
3470
3582
|
showAlpha
|
|
3471
3583
|
? figEditorCreateElement("fig-slider", {
|
|
3472
3584
|
type: "opacity",
|
|
3473
|
-
variant: "classic",
|
|
3474
3585
|
text: "false",
|
|
3475
3586
|
min: "0",
|
|
3476
3587
|
max: "100",
|
|
@@ -3929,7 +4040,14 @@ class FigFillPicker extends HTMLElement {
|
|
|
3929
4040
|
placeholder: "FFFFFF",
|
|
3930
4041
|
});
|
|
3931
4042
|
content = showAlpha
|
|
3932
|
-
?
|
|
4043
|
+
? figEditorCreateElement(
|
|
4044
|
+
"fig-input-combo",
|
|
4045
|
+
{
|
|
4046
|
+
className: "input-combo fig-fill-picker-ci-hex-row",
|
|
4047
|
+
full: true,
|
|
4048
|
+
},
|
|
4049
|
+
[hexInput, alphaField()],
|
|
4050
|
+
)
|
|
3933
4051
|
: hexInput;
|
|
3934
4052
|
}
|
|
3935
4053
|
break;
|
|
@@ -4834,41 +4952,44 @@ class FigFillPicker extends HTMLElement {
|
|
|
4834
4952
|
|
|
4835
4953
|
const rows = this.#gradient.stops.map((stop, index) =>
|
|
4836
4954
|
figEditorCreateElement(
|
|
4837
|
-
"fig-
|
|
4955
|
+
"fig-property",
|
|
4838
4956
|
{
|
|
4839
4957
|
className: "fig-fill-picker-gradient-stop-row",
|
|
4840
4958
|
"data-index": index,
|
|
4959
|
+
leading: "drag",
|
|
4960
|
+
trailing: "remove",
|
|
4961
|
+
"show-leading": "hover",
|
|
4962
|
+
"show-trailing": true,
|
|
4841
4963
|
},
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
}
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
},
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
],
|
|
4964
|
+
figEditorCreateElement(
|
|
4965
|
+
"fig-stack",
|
|
4966
|
+
{
|
|
4967
|
+
className: "fig-fill-picker-gradient-stop-inputs",
|
|
4968
|
+
slot: "input",
|
|
4969
|
+
direction: "horizontal",
|
|
4970
|
+
gap: "2",
|
|
4971
|
+
full: true,
|
|
4972
|
+
},
|
|
4973
|
+
[
|
|
4974
|
+
figEditorCreateElement("fig-input-number", {
|
|
4975
|
+
className: "fig-fill-picker-stop-position",
|
|
4976
|
+
"aria-label": "Gradient stop position",
|
|
4977
|
+
min: "0",
|
|
4978
|
+
max: "100",
|
|
4979
|
+
value: stop.position,
|
|
4980
|
+
units: "%",
|
|
4981
|
+
}),
|
|
4982
|
+
figEditorCreateElement("fig-input-color", {
|
|
4983
|
+
className: "fig-fill-picker-stop-color",
|
|
4984
|
+
"aria-label": "Gradient stop color",
|
|
4985
|
+
text: "true",
|
|
4986
|
+
alpha: "true",
|
|
4987
|
+
picker: "figma",
|
|
4988
|
+
"picker-dialog-position": "right",
|
|
4989
|
+
value: this.#formatStopColorValue(stop),
|
|
4990
|
+
}),
|
|
4991
|
+
],
|
|
4992
|
+
),
|
|
4872
4993
|
),
|
|
4873
4994
|
);
|
|
4874
4995
|
reorder.replaceChildren(...rows);
|
|
@@ -4911,16 +5032,21 @@ class FigFillPicker extends HTMLElement {
|
|
|
4911
5032
|
stopColor.addEventListener("input", syncStopColor);
|
|
4912
5033
|
stopColor.addEventListener("change", syncStopColor);
|
|
4913
5034
|
|
|
4914
|
-
row
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
5035
|
+
const remove = row.querySelector(
|
|
5036
|
+
':scope > [data-fig-property-action="remove"]',
|
|
5037
|
+
);
|
|
5038
|
+
remove.classList.add("fig-fill-picker-stop-remove");
|
|
5039
|
+
remove.setAttribute("aria-label", "Remove gradient stop");
|
|
5040
|
+
remove.toggleAttribute("disabled", this.#gradient.stops.length <= 2);
|
|
5041
|
+
row.addEventListener("remove", (event) => {
|
|
5042
|
+
event.stopPropagation();
|
|
5043
|
+
const index = parseInt(row.dataset.index, 10);
|
|
5044
|
+
if (this.#gradient.stops.length > 2) {
|
|
5045
|
+
this.#gradient.stops.splice(index, 1);
|
|
5046
|
+
this.#updateGradientUI();
|
|
5047
|
+
this.#emitInput();
|
|
5048
|
+
}
|
|
5049
|
+
});
|
|
4924
5050
|
});
|
|
4925
5051
|
}
|
|
4926
5052
|
|
package/fig-property.css
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
|
|
2
|
+
|
|
3
|
+
fig-property {
|
|
4
|
+
--fig-property-gap: var(--spacer-2);
|
|
5
|
+
--fig-property-left-padding: var(--spacer-3);
|
|
6
|
+
--fig-property-right-padding: var(--spacer-3);
|
|
7
|
+
--fig-property-top-padding: var(--spacer-1);
|
|
8
|
+
--fig-property-bottom-padding: var(--spacer-1);
|
|
9
|
+
--fig-property-label-ratio: 1fr;
|
|
10
|
+
--fig-property-input-ratio: 2fr;
|
|
11
|
+
--fig-property-trailing-gap: 0;
|
|
12
|
+
--fig-property-trailing-size: 0;
|
|
13
|
+
display: grid;
|
|
14
|
+
grid-template-columns:
|
|
15
|
+
var(--fig-property-left-padding)
|
|
16
|
+
var(
|
|
17
|
+
--fig-property-label-track,
|
|
18
|
+
minmax(0, var(--fig-property-label-ratio))
|
|
19
|
+
)
|
|
20
|
+
minmax(0, var(--fig-property-input-ratio))
|
|
21
|
+
var(--fig-property-trailing-gap)
|
|
22
|
+
var(--fig-property-trailing-size)
|
|
23
|
+
var(--fig-property-right-padding);
|
|
24
|
+
grid-template-areas: "leading label input . trailing pad";
|
|
25
|
+
align-items: start;
|
|
26
|
+
width: 100%;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
margin: 0;
|
|
29
|
+
padding: var(--fig-property-top-padding) 0
|
|
30
|
+
var(--fig-property-bottom-padding);
|
|
31
|
+
|
|
32
|
+
&[show-trailing]:not([show-trailing="hover"]):has(> fig-button[slot="trailing"][variant="ghost"]),
|
|
33
|
+
&[show-trailing]:not([show-trailing="hover"]):has(> [slot="trailing"] fig-button[variant="ghost"]) {
|
|
34
|
+
--fig-property-right-padding: var(--spacer-2);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
> :is(label, [slot="label"]) {
|
|
38
|
+
grid-area: label;
|
|
39
|
+
display: block;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
height: min(100%, var(--spacer-4));
|
|
42
|
+
margin-right: var(--fig-property-gap);
|
|
43
|
+
padding: 0;
|
|
44
|
+
align-content: center;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
font: inherit;
|
|
47
|
+
line-height: 1rem;
|
|
48
|
+
text-overflow: ellipsis;
|
|
49
|
+
white-space: nowrap;
|
|
50
|
+
user-select: none;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
> [slot="leading"] {
|
|
54
|
+
grid-area: leading;
|
|
55
|
+
height: 100%;
|
|
56
|
+
visibility: hidden;
|
|
57
|
+
color: var(--figma-color-text-secondary);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&:has(> [slot="trailing"]) {
|
|
61
|
+
--fig-property-label-track: minmax(
|
|
62
|
+
0,
|
|
63
|
+
calc(
|
|
64
|
+
(
|
|
65
|
+
100% - var(--fig-property-left-padding) -
|
|
66
|
+
var(--fig-property-right-padding)
|
|
67
|
+
) /
|
|
68
|
+
3
|
|
69
|
+
)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
> [slot="input"] {
|
|
74
|
+
grid-area: input;
|
|
75
|
+
width: 100%;
|
|
76
|
+
min-width: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
> [slot="trailing"] {
|
|
80
|
+
grid-area: trailing;
|
|
81
|
+
min-width: 0;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
visibility: hidden;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&:is(:hover) > [slot="leading"],
|
|
87
|
+
&:hover > [slot="trailing"],
|
|
88
|
+
&[show-leading]:not([show-leading="hover"]):not([show-leading="false"])
|
|
89
|
+
> [slot="leading"],
|
|
90
|
+
&[show-trailing]:not([show-trailing="hover"]):not([show-trailing="false"])
|
|
91
|
+
> [slot="trailing"] {
|
|
92
|
+
visibility: visible;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&:hover:has(> [slot="trailing"]):not([show-trailing="false"]),
|
|
96
|
+
&[show-trailing]:not([show-trailing="hover"]):not([show-trailing="false"])
|
|
97
|
+
{
|
|
98
|
+
--fig-property-trailing-gap: var(--fig-property-gap);
|
|
99
|
+
--fig-property-trailing-size: max-content;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&:hover > [slot="trailing"],
|
|
103
|
+
&[show-trailing]:not([show-trailing="hover"]):not([show-trailing="false"])
|
|
104
|
+
> [slot="trailing"] {
|
|
105
|
+
overflow: visible;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&[show-leading="false"] > [slot="leading"],
|
|
109
|
+
&[show-trailing="false"] > [slot="trailing"] {
|
|
110
|
+
display: none;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&:not(:has(> :is(label, [slot="label"]))) > [slot="input"] {
|
|
114
|
+
grid-column: label-start / input-end;
|
|
115
|
+
}
|
|
116
|
+
}
|