@rogieking/figui3 11.5.0 → 11.6.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 +2 -1
- package/.cursor/skills/fig-editor/components.md +87 -0
- package/.cursor/skills/fig-editor/reference.md +37 -0
- package/.cursor/skills/figui3/components.md +6 -1
- package/.cursor/skills/figui3/react.md +1 -0
- package/CHANGELOG.md +17 -0
- package/README.md +80 -3
- package/components.css +27 -0
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +3 -3
- package/dist/fig.css +1 -1
- package/dist/fig.js +5 -5
- package/fig-editor.css +4 -168
- package/fig-editor.js +46 -7
- package/fig-gradient-editor.css +76 -0
- package/fig-gradient-editor.js +598 -0
- package/fig-popup-easing.css +8 -0
- package/fig-popup-easing.js +141 -0
- package/fig-popup-gradient.css +11 -0
- package/fig-popup-gradient.js +138 -0
- package/fig-popup-palette.css +7 -0
- package/fig-popup-palette.js +173 -0
- package/fig.js +256 -97
- package/package.json +9 -1
package/fig-editor.css
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
|
|
2
2
|
@import url("fig-layer.css");
|
|
3
3
|
@import url("fig-property.css");
|
|
4
|
+
@import url("fig-gradient-editor.css");
|
|
5
|
+
@import url("fig-popup-easing.css");
|
|
6
|
+
@import url("fig-popup-gradient.css");
|
|
7
|
+
@import url("fig-popup-palette.css");
|
|
4
8
|
|
|
5
9
|
fig-input-point {
|
|
6
10
|
display: inline-flex;
|
|
@@ -159,12 +163,6 @@ dialog[is="fig-toast"] {
|
|
|
159
163
|
}
|
|
160
164
|
|
|
161
165
|
/* Palette Editor */
|
|
162
|
-
.fig-palette-editor-popup {
|
|
163
|
-
width: 12rem;
|
|
164
|
-
padding: 0;
|
|
165
|
-
pointer-events: auto;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
166
|
fig-palette-editor {
|
|
169
167
|
display: flex;
|
|
170
168
|
flex-direction: column;
|
|
@@ -330,168 +328,6 @@ fig-fill-picker {
|
|
|
330
328
|
}
|
|
331
329
|
}
|
|
332
330
|
|
|
333
|
-
/* Gradient Tab */
|
|
334
|
-
.fig-fill-picker-gradient-preview {
|
|
335
|
-
aspect-ratio: auto;
|
|
336
|
-
width: calc(100% - var(--spacer-3) * 2);
|
|
337
|
-
margin: var(--spacer-2) var(--spacer-3);
|
|
338
|
-
margin-top: var(--spacer-4);
|
|
339
|
-
margin-bottom:0;
|
|
340
|
-
background: transparent;
|
|
341
|
-
&::after{
|
|
342
|
-
display: none;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
fig-header.fig-fill-picker-gradient-header {
|
|
347
|
-
.fig-fill-picker-gradient-type {
|
|
348
|
-
display: flex;
|
|
349
|
-
flex: 0 1 auto;
|
|
350
|
-
min-width: 0;
|
|
351
|
-
width: auto;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
.fig-fill-picker-gradient-actions {
|
|
355
|
-
flex: 0 0 auto;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
.fig-fill-picker-gradient-stops {
|
|
360
|
-
.fig-fill-picker-gradient-stops-header {
|
|
361
|
-
> span {
|
|
362
|
-
flex: 1;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
fig-field.fig-fill-picker-gradient-interpolation-field {
|
|
368
|
-
display: flex;
|
|
369
|
-
align-items: center;
|
|
370
|
-
grid-template-columns: unset;
|
|
371
|
-
grid-template-areas: unset;
|
|
372
|
-
padding-left: var(--spacer-3);
|
|
373
|
-
padding-right: var(--spacer-2);
|
|
374
|
-
gap: var(--spacer-1);
|
|
375
|
-
|
|
376
|
-
> *:not([slot="leading"]):not([slot="trailing"]):not(label) {
|
|
377
|
-
grid-area: unset;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
.fig-fill-picker-gradient-interpolation-modes {
|
|
382
|
-
flex: 1 1 auto;
|
|
383
|
-
min-width: 0;
|
|
384
|
-
|
|
385
|
-
fig-interpolation-swatch {
|
|
386
|
-
pointer-events: none;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/* Transparent select trigger sits on the icon button so its menu anchors here. */
|
|
391
|
-
.fig-fill-picker-gradient-interpolation-more {
|
|
392
|
-
position: relative;
|
|
393
|
-
display: inline-flex;
|
|
394
|
-
flex: 0 0 auto;
|
|
395
|
-
|
|
396
|
-
> fig-button {
|
|
397
|
-
pointer-events: none;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
.fig-fill-picker-gradient-space {
|
|
401
|
-
position: absolute;
|
|
402
|
-
inset: 0;
|
|
403
|
-
width: 100%;
|
|
404
|
-
opacity: 0;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
&:has(.fig-fill-picker-gradient-space:hover) > fig-button,
|
|
408
|
-
&:has(.fig-fill-picker-gradient-space[open]) > fig-button {
|
|
409
|
-
background-color: var(--figma-color-bg-transparent-hover);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
&:has(.fig-fill-picker-gradient-space[data-focus-visible]) > fig-button {
|
|
413
|
-
outline: var(--figma-focus-outline);
|
|
414
|
-
outline-offset: var(--figma-focus-outline-offset);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
.fig-fill-picker-gradient-space {
|
|
419
|
-
&::part(prepend) {
|
|
420
|
-
display: none;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
fig-select-option {
|
|
424
|
-
min-height: 3rem;
|
|
425
|
-
|
|
426
|
-
&:hover::before,
|
|
427
|
-
&:focus-visible::before {
|
|
428
|
-
background-color: var(--figma-color-bg-tertiary);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
.fig-fill-picker-gradient-interpolation-label {
|
|
433
|
-
display: flex;
|
|
434
|
-
flex-direction: column;
|
|
435
|
-
justify-content: center;
|
|
436
|
-
min-width: 0;
|
|
437
|
-
line-height: 1.25;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
.fig-fill-picker-gradient-interpolation-title,
|
|
441
|
-
.fig-fill-picker-gradient-interpolation-subtitle {
|
|
442
|
-
display: block;
|
|
443
|
-
overflow: hidden;
|
|
444
|
-
text-overflow: ellipsis;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
.fig-fill-picker-gradient-interpolation-subtitle {
|
|
448
|
-
color: var(--figma-color-text-tertiary);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
fig-select-options.fig-fill-picker-gradient-interpolation-collapsed {
|
|
452
|
-
overflow: hidden;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
.fig-fill-picker-gradient-stops-list {
|
|
457
|
-
display: flex;
|
|
458
|
-
flex-direction: column;
|
|
459
|
-
|
|
460
|
-
fig-reorder {
|
|
461
|
-
display: contents;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.fig-fill-picker-gradient-stop-row {
|
|
466
|
-
&.dragging {
|
|
467
|
-
background-color: var(--figma-color-bg-selected);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
.fig-fill-picker-gradient-stop-inputs {
|
|
471
|
-
width: 100%;
|
|
472
|
-
min-width: 0;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
.fig-fill-picker-stop-position {
|
|
476
|
-
flex: 0;
|
|
477
|
-
flex-basis: 3rem;
|
|
478
|
-
min-width: 0;
|
|
479
|
-
width: 3rem;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
.fig-fill-picker-stop-color {
|
|
483
|
-
flex: 1;
|
|
484
|
-
min-width: 0;
|
|
485
|
-
fig-input-text {
|
|
486
|
-
min-width: 0;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
.fig-fill-picker-stop-remove {
|
|
491
|
-
flex-shrink: 0;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
331
|
/* Media Tabs (Image/Video/Webcam) */
|
|
496
332
|
fig-field.fig-fill-picker-media-header {
|
|
497
333
|
display: flex;
|
package/fig-editor.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
|
|
2
2
|
import "./fig.js";
|
|
3
3
|
import "./fig-property.js";
|
|
4
|
+
import { figGradientCSS } from "./fig-gradient-editor.js";
|
|
5
|
+
import "./fig-popup-easing.js";
|
|
6
|
+
import "./fig-popup-gradient.js";
|
|
7
|
+
import "./fig-popup-palette.js";
|
|
4
8
|
|
|
5
9
|
function figEditorDefineElement(name, constructor) {
|
|
6
10
|
if (!customElements.get(name)) {
|
|
@@ -4240,6 +4244,29 @@ class FigFillPicker extends HTMLElement {
|
|
|
4240
4244
|
|
|
4241
4245
|
// ============ GRADIENT TAB ============
|
|
4242
4246
|
#initGradientTab() {
|
|
4247
|
+
{
|
|
4248
|
+
const container = this.#dialog.querySelector('[data-tab="gradient"]');
|
|
4249
|
+
const editor = document.createElement("fig-gradient-editor");
|
|
4250
|
+
editor.value = gradientToValueShape(this.#gradient);
|
|
4251
|
+
editor.setAttribute("color-space", this.#gamut);
|
|
4252
|
+
editor.toggleAttribute("disabled", this.#isDisabled());
|
|
4253
|
+
editor.pickerAnchor = this.#dialog;
|
|
4254
|
+
const syncFromEditor = (event) => {
|
|
4255
|
+
event.stopPropagation();
|
|
4256
|
+
if (!event.detail?.gradient) return;
|
|
4257
|
+
this.#gradient = lockFillPickerGradientInterpolation(
|
|
4258
|
+
event.detail.gradient,
|
|
4259
|
+
);
|
|
4260
|
+
this.#updateSwatch();
|
|
4261
|
+
if (event.type === "change") this.#emitChange();
|
|
4262
|
+
else this.#emitInput();
|
|
4263
|
+
};
|
|
4264
|
+
editor.addEventListener("input", syncFromEditor);
|
|
4265
|
+
editor.addEventListener("change", syncFromEditor);
|
|
4266
|
+
container.replaceChildren(editor);
|
|
4267
|
+
return;
|
|
4268
|
+
}
|
|
4269
|
+
|
|
4243
4270
|
const container = this.#dialog.querySelector('[data-tab="gradient"]');
|
|
4244
4271
|
const gradientType = figEditorCreateElement(
|
|
4245
4272
|
"fig-select",
|
|
@@ -4817,6 +4844,14 @@ class FigFillPicker extends HTMLElement {
|
|
|
4817
4844
|
const container = this.#dialog.querySelector('[data-tab="gradient"]');
|
|
4818
4845
|
if (!container) return;
|
|
4819
4846
|
this.#gradient = lockFillPickerGradientInterpolation(this.#gradient);
|
|
4847
|
+
const editor = container.querySelector("fig-gradient-editor");
|
|
4848
|
+
if (editor) {
|
|
4849
|
+
editor.value = this.#gradient;
|
|
4850
|
+
editor.setAttribute("color-space", this.#gamut);
|
|
4851
|
+
editor.toggleAttribute("disabled", this.#isDisabled());
|
|
4852
|
+
editor.pickerAnchor = this.#dialog;
|
|
4853
|
+
return;
|
|
4854
|
+
}
|
|
4820
4855
|
|
|
4821
4856
|
const interpolationValue = gradientInterpolationSelectValue(this.#gradient);
|
|
4822
4857
|
const interpolationSelect = container.querySelector(
|
|
@@ -4895,6 +4930,16 @@ class FigFillPicker extends HTMLElement {
|
|
|
4895
4930
|
#updateGradientPreview() {
|
|
4896
4931
|
if (!this.#dialog) return;
|
|
4897
4932
|
|
|
4933
|
+
const editor = this.#dialog.querySelector(
|
|
4934
|
+
'[data-tab="gradient"] > fig-gradient-editor',
|
|
4935
|
+
);
|
|
4936
|
+
if (editor) {
|
|
4937
|
+
editor.value = this.#gradient;
|
|
4938
|
+
editor.setAttribute("color-space", this.#gamut);
|
|
4939
|
+
this.#updateSwatch();
|
|
4940
|
+
return;
|
|
4941
|
+
}
|
|
4942
|
+
|
|
4898
4943
|
const barInput = this.#dialog.querySelector(
|
|
4899
4944
|
".fig-fill-picker-gradient-bar-input",
|
|
4900
4945
|
);
|
|
@@ -5093,13 +5138,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
5093
5138
|
}
|
|
5094
5139
|
|
|
5095
5140
|
#getGradientCSS() {
|
|
5096
|
-
|
|
5097
|
-
if (this.#testGradientSupport(preferred)) return preferred;
|
|
5098
|
-
|
|
5099
|
-
const oklabFallback = this.#buildGradientCSS("oklab", true);
|
|
5100
|
-
if (this.#testGradientSupport(oklabFallback)) return oklabFallback;
|
|
5101
|
-
|
|
5102
|
-
return this.#buildGradientCSS("oklab", false);
|
|
5141
|
+
return figGradientCSS(this.#gradient, { colorSpace: this.#gamut });
|
|
5103
5142
|
}
|
|
5104
5143
|
|
|
5105
5144
|
// ============ IMAGE TAB ============
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
|
|
2
|
+
fig-gradient-editor {
|
|
3
|
+
display: block;
|
|
4
|
+
width: 100%;
|
|
5
|
+
min-width: 0;
|
|
6
|
+
|
|
7
|
+
.fig-fill-picker-gradient-preview {
|
|
8
|
+
aspect-ratio: auto;
|
|
9
|
+
width: calc(100% - var(--spacer-3) * 2);
|
|
10
|
+
margin: var(--spacer-3) var(--spacer-3) 0;
|
|
11
|
+
background: transparent;
|
|
12
|
+
overflow: visible;
|
|
13
|
+
|
|
14
|
+
&::after {
|
|
15
|
+
display: none;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fig-header.fig-fill-picker-gradient-header {
|
|
20
|
+
.fig-fill-picker-gradient-type {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex: 0 1 auto;
|
|
23
|
+
min-width: 0;
|
|
24
|
+
width: auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.fig-fill-picker-gradient-actions {
|
|
28
|
+
flex: 0 0 auto;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.fig-fill-picker-gradient-stops {
|
|
33
|
+
.fig-fill-picker-gradient-stops-header > span {
|
|
34
|
+
flex: 1;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.fig-fill-picker-gradient-stops-list {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
|
|
42
|
+
fig-reorder {
|
|
43
|
+
display: contents;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.fig-fill-picker-gradient-stop-row {
|
|
48
|
+
&.dragging {
|
|
49
|
+
background-color: var(--figma-color-bg-selected);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.fig-fill-picker-gradient-stop-inputs {
|
|
53
|
+
width: 100%;
|
|
54
|
+
min-width: 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.fig-fill-picker-stop-position {
|
|
58
|
+
flex: 0 0 3rem;
|
|
59
|
+
min-width: 0;
|
|
60
|
+
width: 3rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.fig-fill-picker-stop-color {
|
|
64
|
+
flex: 1;
|
|
65
|
+
min-width: 0;
|
|
66
|
+
|
|
67
|
+
fig-input-text {
|
|
68
|
+
min-width: 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.fig-fill-picker-stop-remove {
|
|
73
|
+
flex-shrink: 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|