@rogieking/figui3 11.6.0 → 11.6.2
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/components.md +10 -5
- package/.cursor/skills/fig-editor/reference.md +10 -4
- package/.cursor/skills/figui3/reference.md +8 -0
- package/CHANGELOG.md +32 -0
- package/README.md +32 -8
- package/components.css +3 -1
- package/dist/components.css +1 -1
- package/dist/fig-color.js +1 -0
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +3 -3
- package/dist/fig-property.css +1 -1
- package/dist/fig.css +1 -1
- package/dist/fig.js +6 -6
- package/fig-color.js +406 -0
- package/fig-editor.css +1 -16
- package/fig-editor.js +39 -594
- package/fig-gradient-editor.css +6 -1
- package/fig-gradient-editor.js +566 -237
- package/fig-palette-editor.css +20 -0
- package/fig-palette-editor.js +745 -0
- package/fig-popup-gradient.js +9 -1
- package/fig-popup-palette.js +13 -2
- package/fig-property.css +4 -0
- package/fig.js +164 -177
- package/package.json +7 -2
package/fig-popup-gradient.js
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
import "./fig.js";
|
|
3
3
|
import "./fig-gradient-editor.js";
|
|
4
4
|
|
|
5
|
-
const GRADIENT_ATTRIBUTES = [
|
|
5
|
+
const GRADIENT_ATTRIBUTES = [
|
|
6
|
+
"value",
|
|
7
|
+
"color-space",
|
|
8
|
+
"disabled",
|
|
9
|
+
"overflow",
|
|
10
|
+
"show-rows",
|
|
11
|
+
];
|
|
6
12
|
|
|
7
13
|
customElements.whenDefined("fig-popup").then(() => {
|
|
8
14
|
if (customElements.get("fig-popup-gradient")) return;
|
|
@@ -16,6 +22,8 @@ customElements.whenDefined("fig-popup").then(() => {
|
|
|
16
22
|
* @attr {string} value - JSON gradient config or full gradient fill value
|
|
17
23
|
* @attr {string} color-space - `srgb` or `display-p3`
|
|
18
24
|
* @attr {boolean} disabled - Disables gradient editing
|
|
25
|
+
* @attr {"fade"|"visible"} overflow - Stop-list overflow mode
|
|
26
|
+
* @attr {number} show-rows - Visible stop rows before overflow
|
|
19
27
|
* @fires input - During gradient edits
|
|
20
28
|
* @fires change - On committed gradient edits
|
|
21
29
|
*/
|
package/fig-popup-palette.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
|
|
2
2
|
import "./fig.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import "./fig-palette-editor.js";
|
|
4
|
+
|
|
5
|
+
const PALETTE_ATTRIBUTES = [
|
|
6
|
+
"value",
|
|
7
|
+
"min",
|
|
8
|
+
"max",
|
|
9
|
+
"fixed",
|
|
10
|
+
"disabled",
|
|
11
|
+
"overflow",
|
|
12
|
+
"show-rows",
|
|
13
|
+
];
|
|
5
14
|
|
|
6
15
|
function normalizePaletteValue(value) {
|
|
7
16
|
let entries = value;
|
|
@@ -56,6 +65,8 @@ customElements.whenDefined("fig-popup").then(() => {
|
|
|
56
65
|
* @attr {number} max - Maximum number of colors
|
|
57
66
|
* @attr {boolean} fixed - Locks the palette length
|
|
58
67
|
* @attr {boolean} disabled - Disables palette editing
|
|
68
|
+
* @attr {"fade"|"visible"} overflow - Vertical overflow mode
|
|
69
|
+
* @attr {number} show-rows - Visible rows before overflow
|
|
59
70
|
* @fires input - During editing with the normalized color array in detail
|
|
60
71
|
* @fires change - On committed edits with the normalized color array in detail
|
|
61
72
|
*/
|
package/fig-property.css
CHANGED
|
@@ -29,6 +29,10 @@ fig-property {
|
|
|
29
29
|
padding: var(--fig-property-top-padding) 0
|
|
30
30
|
var(--fig-property-bottom-padding);
|
|
31
31
|
|
|
32
|
+
&[selected]:not([selected="false"]) {
|
|
33
|
+
background-color: var(--figma-color-bg-selected);
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
&[show-trailing]:not([show-trailing="hover"]):has(> fig-button[slot="trailing"][variant="ghost"]),
|
|
33
37
|
&[show-trailing]:not([show-trailing="hover"]):has(> [slot="trailing"] fig-button[variant="ghost"]) {
|
|
34
38
|
--fig-property-right-padding: var(--spacer-2);
|
package/fig.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import "./fig-layer.js";
|
|
2
|
+
import {
|
|
3
|
+
figHexToRGB,
|
|
4
|
+
figHslToRGB,
|
|
5
|
+
figInterpolateHue,
|
|
6
|
+
figLinearToSRGB,
|
|
7
|
+
figOklabToOklch,
|
|
8
|
+
figOklabToRGB,
|
|
9
|
+
figOklchToOklab,
|
|
10
|
+
figRGBToHsl as figRgbToHsl,
|
|
11
|
+
figRGBToLinear,
|
|
12
|
+
figRGBToOklab,
|
|
13
|
+
} from "./fig-color.js";
|
|
2
14
|
|
|
3
15
|
/**
|
|
4
16
|
* Generates a unique ID string using timestamp and random values
|
|
@@ -2907,7 +2919,11 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2907
2919
|
_wasDragged = false;
|
|
2908
2920
|
_previousFocus = null;
|
|
2909
2921
|
_boundDocumentKeydown;
|
|
2922
|
+
_boundDocumentPointerUp;
|
|
2910
2923
|
_boundNativeClose;
|
|
2924
|
+
_boundNativeCancel;
|
|
2925
|
+
_suppressNativeCancel = false;
|
|
2926
|
+
_nativeCancelResetTimer = null;
|
|
2911
2927
|
|
|
2912
2928
|
constructor() {
|
|
2913
2929
|
super();
|
|
@@ -2929,7 +2945,10 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2929
2945
|
this._boundPointerMove = this.handlePointerMove.bind(this);
|
|
2930
2946
|
this._boundPointerUp = this.handlePointerUp.bind(this);
|
|
2931
2947
|
this._boundDocumentKeydown = this.handleDocumentKeydown.bind(this);
|
|
2948
|
+
this._boundDocumentPointerUp =
|
|
2949
|
+
this.handleDocumentPointerUp.bind(this);
|
|
2932
2950
|
this._boundNativeClose = this.handleNativeClose.bind(this);
|
|
2951
|
+
this._boundNativeCancel = this.handleNativeCancel.bind(this);
|
|
2933
2952
|
this._boundAutoClose = () => {
|
|
2934
2953
|
this.open = false;
|
|
2935
2954
|
};
|
|
@@ -2960,6 +2979,10 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2960
2979
|
if (typeof this._dragThreshold !== "number") this._dragThreshold = 3;
|
|
2961
2980
|
if (typeof this._wasDragged === "undefined") this._wasDragged = false;
|
|
2962
2981
|
if (typeof this._previousFocus === "undefined") this._previousFocus = null;
|
|
2982
|
+
if (typeof this._suppressNativeCancel === "undefined")
|
|
2983
|
+
this._suppressNativeCancel = false;
|
|
2984
|
+
if (typeof this._nativeCancelResetTimer === "undefined")
|
|
2985
|
+
this._nativeCancelResetTimer = null;
|
|
2963
2986
|
|
|
2964
2987
|
if (typeof this._boundReposition !== "function") {
|
|
2965
2988
|
this._boundReposition = () => this.queueReposition();
|
|
@@ -2995,9 +3018,16 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2995
3018
|
if (typeof this._boundDocumentKeydown !== "function") {
|
|
2996
3019
|
this._boundDocumentKeydown = this.handleDocumentKeydown.bind(this);
|
|
2997
3020
|
}
|
|
3021
|
+
if (typeof this._boundDocumentPointerUp !== "function") {
|
|
3022
|
+
this._boundDocumentPointerUp =
|
|
3023
|
+
this.handleDocumentPointerUp.bind(this);
|
|
3024
|
+
}
|
|
2998
3025
|
if (typeof this._boundNativeClose !== "function") {
|
|
2999
3026
|
this._boundNativeClose = this.handleNativeClose.bind(this);
|
|
3000
3027
|
}
|
|
3028
|
+
if (typeof this._boundNativeCancel !== "function") {
|
|
3029
|
+
this._boundNativeCancel = this.handleNativeCancel.bind(this);
|
|
3030
|
+
}
|
|
3001
3031
|
if (typeof this._boundAutoClose !== "function") {
|
|
3002
3032
|
this._boundAutoClose = () => {
|
|
3003
3033
|
this.open = false;
|
|
@@ -3092,6 +3122,8 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3092
3122
|
|
|
3093
3123
|
this.removeEventListener("close", this._boundNativeClose);
|
|
3094
3124
|
this.addEventListener("close", this._boundNativeClose);
|
|
3125
|
+
this.removeEventListener("cancel", this._boundNativeCancel);
|
|
3126
|
+
this.addEventListener("cancel", this._boundNativeCancel);
|
|
3095
3127
|
|
|
3096
3128
|
requestAnimationFrame(() => {
|
|
3097
3129
|
this.setupDragListeners();
|
|
@@ -3114,7 +3146,22 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3114
3146
|
true,
|
|
3115
3147
|
);
|
|
3116
3148
|
document.removeEventListener("keydown", this._boundDocumentKeydown, true);
|
|
3149
|
+
document.removeEventListener(
|
|
3150
|
+
"pointerup",
|
|
3151
|
+
this._boundDocumentPointerUp,
|
|
3152
|
+
true,
|
|
3153
|
+
);
|
|
3154
|
+
document.removeEventListener(
|
|
3155
|
+
"pointercancel",
|
|
3156
|
+
this._boundDocumentPointerUp,
|
|
3157
|
+
true,
|
|
3158
|
+
);
|
|
3117
3159
|
this.removeEventListener("close", this._boundNativeClose);
|
|
3160
|
+
this.removeEventListener("cancel", this._boundNativeCancel);
|
|
3161
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3162
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3163
|
+
this._nativeCancelResetTimer = null;
|
|
3164
|
+
}
|
|
3118
3165
|
if (this._rafId !== null) {
|
|
3119
3166
|
cancelAnimationFrame(this._rafId);
|
|
3120
3167
|
this._rafId = null;
|
|
@@ -3210,6 +3257,16 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3210
3257
|
true,
|
|
3211
3258
|
);
|
|
3212
3259
|
document.addEventListener("keydown", this._boundDocumentKeydown, true);
|
|
3260
|
+
document.addEventListener(
|
|
3261
|
+
"pointerup",
|
|
3262
|
+
this._boundDocumentPointerUp,
|
|
3263
|
+
true,
|
|
3264
|
+
);
|
|
3265
|
+
document.addEventListener(
|
|
3266
|
+
"pointercancel",
|
|
3267
|
+
this._boundDocumentPointerUp,
|
|
3268
|
+
true,
|
|
3269
|
+
);
|
|
3213
3270
|
this._wasDragged = false;
|
|
3214
3271
|
this.queueReposition();
|
|
3215
3272
|
this._isPopupActive = true;
|
|
@@ -3241,6 +3298,21 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3241
3298
|
true,
|
|
3242
3299
|
);
|
|
3243
3300
|
document.removeEventListener("keydown", this._boundDocumentKeydown, true);
|
|
3301
|
+
document.removeEventListener(
|
|
3302
|
+
"pointerup",
|
|
3303
|
+
this._boundDocumentPointerUp,
|
|
3304
|
+
true,
|
|
3305
|
+
);
|
|
3306
|
+
document.removeEventListener(
|
|
3307
|
+
"pointercancel",
|
|
3308
|
+
this._boundDocumentPointerUp,
|
|
3309
|
+
true,
|
|
3310
|
+
);
|
|
3311
|
+
this._suppressNativeCancel = false;
|
|
3312
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3313
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3314
|
+
this._nativeCancelResetTimer = null;
|
|
3315
|
+
}
|
|
3244
3316
|
|
|
3245
3317
|
if (
|
|
3246
3318
|
this.hasAttribute("popover") &&
|
|
@@ -3317,6 +3389,15 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3317
3389
|
if (this.hasAttribute("open")) this.removeAttribute("open");
|
|
3318
3390
|
}
|
|
3319
3391
|
|
|
3392
|
+
handleNativeCancel(event) {
|
|
3393
|
+
if (
|
|
3394
|
+
this._suppressNativeCancel &&
|
|
3395
|
+
this.getAttribute("closedby") === "any"
|
|
3396
|
+
) {
|
|
3397
|
+
event.preventDefault();
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3320
3401
|
setupObservers() {
|
|
3321
3402
|
this.teardownObservers();
|
|
3322
3403
|
|
|
@@ -3462,26 +3543,55 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3462
3543
|
// counts as inside — Node.contains() is false for slotted nodes.
|
|
3463
3544
|
const path =
|
|
3464
3545
|
typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
3465
|
-
if (path.includes(this))
|
|
3466
|
-
|
|
3546
|
+
if (path.includes(this) || this.contains(target)) {
|
|
3547
|
+
this.markOwnedPointerInteraction();
|
|
3548
|
+
return;
|
|
3549
|
+
}
|
|
3467
3550
|
|
|
3468
3551
|
const anchor = this.resolveAnchor();
|
|
3469
|
-
if (anchor && (path.includes(anchor) || anchor.contains?.(target)))
|
|
3552
|
+
if (anchor && (path.includes(anchor) || anchor.contains?.(target))) {
|
|
3553
|
+
this.markOwnedPointerInteraction();
|
|
3554
|
+
return;
|
|
3555
|
+
}
|
|
3470
3556
|
|
|
3471
|
-
if (this.isInsideDescendantPopup(target))
|
|
3557
|
+
if (this.isInsideDescendantPopup(target, path)) {
|
|
3558
|
+
this.markOwnedPointerInteraction();
|
|
3559
|
+
return;
|
|
3560
|
+
}
|
|
3472
3561
|
|
|
3562
|
+
this._suppressNativeCancel = false;
|
|
3473
3563
|
this.open = false;
|
|
3474
3564
|
}
|
|
3475
3565
|
|
|
3566
|
+
markOwnedPointerInteraction() {
|
|
3567
|
+
this._suppressNativeCancel = true;
|
|
3568
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3569
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3570
|
+
this._nativeCancelResetTimer = null;
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3574
|
+
handleDocumentPointerUp() {
|
|
3575
|
+
if (!this._suppressNativeCancel) return;
|
|
3576
|
+
if (this._nativeCancelResetTimer !== null) {
|
|
3577
|
+
clearTimeout(this._nativeCancelResetTimer);
|
|
3578
|
+
}
|
|
3579
|
+
// Native dialog light-dismiss runs after pointer dispatch. Keep the guard
|
|
3580
|
+
// through that algorithm, then allow later requestClose() calls normally.
|
|
3581
|
+
this._nativeCancelResetTimer = setTimeout(() => {
|
|
3582
|
+
this._suppressNativeCancel = false;
|
|
3583
|
+
this._nativeCancelResetTimer = null;
|
|
3584
|
+
}, 0);
|
|
3585
|
+
}
|
|
3586
|
+
|
|
3476
3587
|
handleDocumentKeydown(event) {
|
|
3477
3588
|
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
3478
3589
|
if (!this.open) return;
|
|
3479
3590
|
if (this.getAttribute("role") === "menu") return;
|
|
3480
3591
|
const closedby = this.getAttribute("closedby");
|
|
3481
3592
|
if (closedby === "none") return;
|
|
3482
|
-
const openPopups = Array.from(
|
|
3483
|
-
|
|
3484
|
-
).filter((popup) => popup.open);
|
|
3593
|
+
const openPopups = Array.from(document.querySelectorAll("dialog[open]"))
|
|
3594
|
+
.filter((popup) => popup instanceof FigPopup && popup.open);
|
|
3485
3595
|
const topPopup = openPopups
|
|
3486
3596
|
.map((popup) => ({
|
|
3487
3597
|
popup,
|
|
@@ -3494,8 +3604,40 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3494
3604
|
this.open = false;
|
|
3495
3605
|
}
|
|
3496
3606
|
|
|
3497
|
-
|
|
3498
|
-
|
|
3607
|
+
getContainingPopup(node) {
|
|
3608
|
+
let current = node;
|
|
3609
|
+
const visited = new Set();
|
|
3610
|
+
while (current && !visited.has(current)) {
|
|
3611
|
+
visited.add(current);
|
|
3612
|
+
if (current instanceof FigPopup) return current;
|
|
3613
|
+
current =
|
|
3614
|
+
current.parentNode ??
|
|
3615
|
+
(current.getRootNode?.() instanceof ShadowRoot
|
|
3616
|
+
? current.getRootNode().host
|
|
3617
|
+
: null);
|
|
3618
|
+
}
|
|
3619
|
+
return null;
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
composedContains(node) {
|
|
3623
|
+
let current = node;
|
|
3624
|
+
const visited = new Set();
|
|
3625
|
+
while (current && !visited.has(current)) {
|
|
3626
|
+
if (current === this) return true;
|
|
3627
|
+
visited.add(current);
|
|
3628
|
+
current =
|
|
3629
|
+
current.parentNode ??
|
|
3630
|
+
(current.getRootNode?.() instanceof ShadowRoot
|
|
3631
|
+
? current.getRootNode().host
|
|
3632
|
+
: null);
|
|
3633
|
+
}
|
|
3634
|
+
return false;
|
|
3635
|
+
}
|
|
3636
|
+
|
|
3637
|
+
isInsideDescendantPopup(target, path = []) {
|
|
3638
|
+
const targetDialog =
|
|
3639
|
+
path.find((node) => node instanceof FigPopup) ??
|
|
3640
|
+
this.getContainingPopup(target);
|
|
3499
3641
|
if (!targetDialog || targetDialog === this) return false;
|
|
3500
3642
|
|
|
3501
3643
|
let current = targetDialog;
|
|
@@ -3504,8 +3646,8 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3504
3646
|
visited.add(current);
|
|
3505
3647
|
const popupAnchor = current.anchor;
|
|
3506
3648
|
if (!(popupAnchor instanceof Element)) break;
|
|
3507
|
-
if (this.
|
|
3508
|
-
current =
|
|
3649
|
+
if (this.composedContains(popupAnchor)) return true;
|
|
3650
|
+
current = this.getContainingPopup(popupAnchor);
|
|
3509
3651
|
}
|
|
3510
3652
|
return false;
|
|
3511
3653
|
}
|
|
@@ -9679,96 +9821,6 @@ function figLooksLikeVideoUrl(raw) {
|
|
|
9679
9821
|
}
|
|
9680
9822
|
}
|
|
9681
9823
|
|
|
9682
|
-
function figHexToRGB(hex) {
|
|
9683
|
-
const h = hex.replace(/^#/, "");
|
|
9684
|
-
return {
|
|
9685
|
-
r: parseInt(h.substring(0, 2), 16),
|
|
9686
|
-
g: parseInt(h.substring(2, 4), 16),
|
|
9687
|
-
b: parseInt(h.substring(4, 6), 16),
|
|
9688
|
-
};
|
|
9689
|
-
}
|
|
9690
|
-
|
|
9691
|
-
function figRGBToLinear(c) {
|
|
9692
|
-
const s = c / 255;
|
|
9693
|
-
return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
9694
|
-
}
|
|
9695
|
-
|
|
9696
|
-
function figLinearToSRGB(c) {
|
|
9697
|
-
const v = c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
9698
|
-
return Math.round(Math.max(0, Math.min(1, v)) * 255);
|
|
9699
|
-
}
|
|
9700
|
-
|
|
9701
|
-
function figRGBToOklab(r, g, b) {
|
|
9702
|
-
const lr = figRGBToLinear(r);
|
|
9703
|
-
const lg = figRGBToLinear(g);
|
|
9704
|
-
const lb = figRGBToLinear(b);
|
|
9705
|
-
const l_ = Math.cbrt(
|
|
9706
|
-
0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb,
|
|
9707
|
-
);
|
|
9708
|
-
const m_ = Math.cbrt(
|
|
9709
|
-
0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb,
|
|
9710
|
-
);
|
|
9711
|
-
const s_ = Math.cbrt(
|
|
9712
|
-
0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb,
|
|
9713
|
-
);
|
|
9714
|
-
return {
|
|
9715
|
-
l: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
|
|
9716
|
-
a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
|
|
9717
|
-
b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,
|
|
9718
|
-
};
|
|
9719
|
-
}
|
|
9720
|
-
|
|
9721
|
-
function figOklabToRGB(L, a, b) {
|
|
9722
|
-
const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
|
|
9723
|
-
const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
|
|
9724
|
-
const s_ = L - 0.0894841775 * a - 1.291485548 * b;
|
|
9725
|
-
const l = l_ * l_ * l_;
|
|
9726
|
-
const m = m_ * m_ * m_;
|
|
9727
|
-
const s = s_ * s_ * s_;
|
|
9728
|
-
return {
|
|
9729
|
-
r: figLinearToSRGB(+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
|
|
9730
|
-
g: figLinearToSRGB(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
|
|
9731
|
-
b: figLinearToSRGB(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),
|
|
9732
|
-
};
|
|
9733
|
-
}
|
|
9734
|
-
|
|
9735
|
-
function figOklabToOklch(L, a, b) {
|
|
9736
|
-
return {
|
|
9737
|
-
l: L,
|
|
9738
|
-
c: Math.sqrt(a * a + b * b),
|
|
9739
|
-
h: (Math.atan2(b, a) * 180) / Math.PI,
|
|
9740
|
-
};
|
|
9741
|
-
}
|
|
9742
|
-
|
|
9743
|
-
function figOklchToOklab(l, c, h) {
|
|
9744
|
-
const hRad = (h * Math.PI) / 180;
|
|
9745
|
-
return { l, a: c * Math.cos(hRad), b: c * Math.sin(hRad) };
|
|
9746
|
-
}
|
|
9747
|
-
|
|
9748
|
-
function figInterpolateHue(h1, h2, t, mode) {
|
|
9749
|
-
let a = ((h1 % 360) + 360) % 360;
|
|
9750
|
-
let b = ((h2 % 360) + 360) % 360;
|
|
9751
|
-
let diff = b - a;
|
|
9752
|
-
switch (mode) {
|
|
9753
|
-
case "longer":
|
|
9754
|
-
if (diff > 0 && diff < 180) diff -= 360;
|
|
9755
|
-
else if (diff < 0 && diff > -180) diff += 360;
|
|
9756
|
-
else if (diff === 0) diff = 0;
|
|
9757
|
-
break;
|
|
9758
|
-
case "increasing":
|
|
9759
|
-
if (diff < 0) diff += 360;
|
|
9760
|
-
break;
|
|
9761
|
-
case "decreasing":
|
|
9762
|
-
if (diff > 0) diff -= 360;
|
|
9763
|
-
break;
|
|
9764
|
-
default:
|
|
9765
|
-
if (diff > 180) diff -= 360;
|
|
9766
|
-
else if (diff < -180) diff += 360;
|
|
9767
|
-
break;
|
|
9768
|
-
}
|
|
9769
|
-
return (((a + diff * t) % 360) + 360) % 360;
|
|
9770
|
-
}
|
|
9771
|
-
|
|
9772
9824
|
function figSampleGradientAt(
|
|
9773
9825
|
stops,
|
|
9774
9826
|
position,
|
|
@@ -9834,10 +9886,10 @@ function figSampleGradientAt(
|
|
|
9834
9886
|
);
|
|
9835
9887
|
const S = hsl1.s + (hsl2.s - hsl1.s) * t;
|
|
9836
9888
|
const L = hsl1.l + (hsl2.l - hsl1.l) * t;
|
|
9837
|
-
const rgb =
|
|
9838
|
-
r = rgb
|
|
9839
|
-
g = rgb
|
|
9840
|
-
b = rgb
|
|
9889
|
+
const rgb = figHslToRGB(H, S, L);
|
|
9890
|
+
r = rgb.r;
|
|
9891
|
+
g = rgb.g;
|
|
9892
|
+
b = rgb.b;
|
|
9841
9893
|
} else if (space === "srgb") {
|
|
9842
9894
|
r = Math.round(c1.r + (c2.r - c1.r) * t);
|
|
9843
9895
|
g = Math.round(c1.g + (c2.g - c1.g) * t);
|
|
@@ -9857,77 +9909,6 @@ function figSampleGradientAt(
|
|
|
9857
9909
|
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`.toUpperCase();
|
|
9858
9910
|
}
|
|
9859
9911
|
|
|
9860
|
-
function figRgbToHsl(r, g, b) {
|
|
9861
|
-
const R = r / 255;
|
|
9862
|
-
const G = g / 255;
|
|
9863
|
-
const B = b / 255;
|
|
9864
|
-
const max = Math.max(R, G, B);
|
|
9865
|
-
const min = Math.min(R, G, B);
|
|
9866
|
-
const l = (max + min) / 2;
|
|
9867
|
-
if (max === min) {
|
|
9868
|
-
return { h: 0, s: 0, l: l * 100 };
|
|
9869
|
-
}
|
|
9870
|
-
const d = max - min;
|
|
9871
|
-
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
9872
|
-
let h;
|
|
9873
|
-
switch (max) {
|
|
9874
|
-
case R:
|
|
9875
|
-
h = ((G - B) / d + (G < B ? 6 : 0)) / 6;
|
|
9876
|
-
break;
|
|
9877
|
-
case G:
|
|
9878
|
-
h = ((B - R) / d + 2) / 6;
|
|
9879
|
-
break;
|
|
9880
|
-
default:
|
|
9881
|
-
h = ((R - G) / d + 4) / 6;
|
|
9882
|
-
break;
|
|
9883
|
-
}
|
|
9884
|
-
return { h: h * 360, s: s * 100, l: l * 100 };
|
|
9885
|
-
}
|
|
9886
|
-
|
|
9887
|
-
function hslToP3(h, s, l) {
|
|
9888
|
-
const sRGB = hslToSRGB(h, s, l);
|
|
9889
|
-
return sRGB.map((c) => +(c / 255).toFixed(4));
|
|
9890
|
-
}
|
|
9891
|
-
|
|
9892
|
-
function hslToSRGB(h, s, l) {
|
|
9893
|
-
s /= 100;
|
|
9894
|
-
l /= 100;
|
|
9895
|
-
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
9896
|
-
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
9897
|
-
const m = l - c / 2;
|
|
9898
|
-
let r, g, b;
|
|
9899
|
-
if (h < 60) {
|
|
9900
|
-
r = c;
|
|
9901
|
-
g = x;
|
|
9902
|
-
b = 0;
|
|
9903
|
-
} else if (h < 120) {
|
|
9904
|
-
r = x;
|
|
9905
|
-
g = c;
|
|
9906
|
-
b = 0;
|
|
9907
|
-
} else if (h < 180) {
|
|
9908
|
-
r = 0;
|
|
9909
|
-
g = c;
|
|
9910
|
-
b = x;
|
|
9911
|
-
} else if (h < 240) {
|
|
9912
|
-
r = 0;
|
|
9913
|
-
g = x;
|
|
9914
|
-
b = c;
|
|
9915
|
-
} else if (h < 300) {
|
|
9916
|
-
r = x;
|
|
9917
|
-
g = 0;
|
|
9918
|
-
b = c;
|
|
9919
|
-
} else {
|
|
9920
|
-
r = c;
|
|
9921
|
-
g = 0;
|
|
9922
|
-
b = x;
|
|
9923
|
-
}
|
|
9924
|
-
return [
|
|
9925
|
-
Math.round((r + m) * 255),
|
|
9926
|
-
Math.round((g + m) * 255),
|
|
9927
|
-
Math.round((b + m) * 255),
|
|
9928
|
-
];
|
|
9929
|
-
}
|
|
9930
|
-
|
|
9931
9912
|
/**
|
|
9932
9913
|
* A fill input that supports solid colors, gradients, images, videos, and webcam.
|
|
9933
9914
|
* @attr {string} value - JSON string with fill data
|
|
@@ -12307,7 +12288,13 @@ class FigInputGradient extends HTMLElement {
|
|
|
12307
12288
|
|
|
12308
12289
|
this.#track.addEventListener("pointerdown", (e) => {
|
|
12309
12290
|
if (figBooleanAttribute(this, "disabled")) return;
|
|
12310
|
-
|
|
12291
|
+
const handle = e.target.closest(
|
|
12292
|
+
"fig-handle:not(.fig-input-gradient-ghost)",
|
|
12293
|
+
);
|
|
12294
|
+
if (handle) {
|
|
12295
|
+
this.#activateStopHandle(handle);
|
|
12296
|
+
return;
|
|
12297
|
+
}
|
|
12311
12298
|
if (e.button !== 0) return;
|
|
12312
12299
|
e.preventDefault();
|
|
12313
12300
|
e.stopPropagation();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rogieking/figui3",
|
|
3
|
-
"version": "11.6.
|
|
3
|
+
"version": "11.6.2",
|
|
4
4
|
"description": "A lightweight web components library for building Figma plugin and widget UIs with native look and feel",
|
|
5
5
|
"author": "Rogie King",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
".": "./dist/fig.js",
|
|
12
12
|
"./fig.js": "./dist/fig.js",
|
|
13
|
+
"./fig-color.js": "./dist/fig-color.js",
|
|
13
14
|
"./fig-layer.js": "./dist/fig-layer.js",
|
|
14
15
|
"./fig-property.js": "./dist/fig-property.js",
|
|
15
16
|
"./fig-editor.js": "./dist/fig-editor.js",
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
"./base.css": "./dist/base.css",
|
|
23
24
|
"./components.css": "./dist/components.css",
|
|
24
25
|
"./src/fig.js": "./fig.js",
|
|
26
|
+
"./src/fig-color.js": "./fig-color.js",
|
|
25
27
|
"./src/fig-layer.js": "./fig-layer.js",
|
|
26
28
|
"./src/fig-property.js": "./fig-property.js",
|
|
27
29
|
"./src/fig-editor.js": "./fig-editor.js",
|
|
@@ -36,9 +38,11 @@
|
|
|
36
38
|
},
|
|
37
39
|
"files": [
|
|
38
40
|
"fig.js",
|
|
41
|
+
"fig-color.js",
|
|
39
42
|
"fig-layer.js",
|
|
40
43
|
"fig-property.js",
|
|
41
44
|
"fig-gradient-editor.js",
|
|
45
|
+
"fig-palette-editor.js",
|
|
42
46
|
"fig-popup-easing.js",
|
|
43
47
|
"fig-popup-gradient.js",
|
|
44
48
|
"fig-popup-palette.js",
|
|
@@ -48,6 +52,7 @@
|
|
|
48
52
|
"fig-layer.css",
|
|
49
53
|
"fig-property.css",
|
|
50
54
|
"fig-gradient-editor.css",
|
|
55
|
+
"fig-palette-editor.css",
|
|
51
56
|
"fig-popup-easing.css",
|
|
52
57
|
"fig-popup-gradient.css",
|
|
53
58
|
"fig-popup-palette.css",
|
|
@@ -71,7 +76,7 @@
|
|
|
71
76
|
],
|
|
72
77
|
"scripts": {
|
|
73
78
|
"dev": "bun --hot server.ts",
|
|
74
|
-
"build": "bun build fig.js --minify --outdir dist && bun build fig-layer.js --minify --outdir dist && bun build fig-property.js --minify --outdir dist --external ./fig.js && bun build fig-editor.js --minify --outdir dist --external ./fig.js --external ./fig-property.js --external ./fig-lab.js && bun build fig-lab.js --minify --outdir dist --external ./fig.js --external ./fig-editor.js && npm run build:css",
|
|
79
|
+
"build": "bun build fig-color.js --minify --outdir dist && bun build fig.js --minify --outdir dist --external ./fig-color.js && bun build fig-layer.js --minify --outdir dist && bun build fig-property.js --minify --outdir dist --external ./fig.js && bun build fig-editor.js --minify --outdir dist --external ./fig.js --external ./fig-color.js --external ./fig-property.js --external ./fig-lab.js && bun build fig-lab.js --minify --outdir dist --external ./fig.js --external ./fig-editor.js && npm run build:css",
|
|
75
80
|
"build:css": "node scripts/build-css.mjs",
|
|
76
81
|
"dev:playground": "node playground/dev.mjs",
|
|
77
82
|
"build:playground": "cd playground && npm run build",
|