@rogieking/figui3 3.2.0 → 3.3.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 +65 -35
- package/fig.js +77 -65
- package/package.json +1 -1
package/components.css
CHANGED
|
@@ -367,6 +367,10 @@ textarea,
|
|
|
367
367
|
input[type="text"],
|
|
368
368
|
input[type="number"],
|
|
369
369
|
input[type="password"],
|
|
370
|
+
input[type="url"],
|
|
371
|
+
input[type="email"],
|
|
372
|
+
input[type="search"],
|
|
373
|
+
input[type="tel"],
|
|
370
374
|
.input {
|
|
371
375
|
background-color: var(--figma-color-bg-secondary);
|
|
372
376
|
border: 0;
|
|
@@ -395,28 +399,47 @@ input[type="password"],
|
|
|
395
399
|
}
|
|
396
400
|
}
|
|
397
401
|
|
|
398
|
-
fig-input-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
402
|
+
fig-input-number .fig-steppers {
|
|
403
|
+
display: flex;
|
|
404
|
+
flex-direction: column;
|
|
405
|
+
flex-shrink: 0;
|
|
406
|
+
border-radius: 0 var(--radius-medium) var(--radius-medium) 0;
|
|
407
|
+
overflow: hidden;
|
|
408
|
+
|
|
409
|
+
& button {
|
|
410
|
+
display: block;
|
|
411
|
+
appearance: none;
|
|
412
|
+
border: 0;
|
|
413
|
+
padding: 0;
|
|
414
|
+
margin: 0;
|
|
415
|
+
width: 1.5rem;
|
|
416
|
+
flex: 1;
|
|
417
|
+
background-color: var(--figma-color-text-secondary);
|
|
418
|
+
cursor: pointer;
|
|
419
|
+
mask-size: 1rem;
|
|
420
|
+
mask-repeat: no-repeat;
|
|
421
|
+
mask-position: center -3.5px;
|
|
422
|
+
|
|
423
|
+
&:hover {
|
|
424
|
+
background-color: var(--figma-color-text);
|
|
407
425
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
input[type="number"]::-webkit-inner-spin-button {
|
|
411
|
-
display: block;
|
|
412
|
-
opacity: 1;
|
|
413
|
-
height: 1.5rem;
|
|
414
|
-
width: 1.5rem;
|
|
415
|
-
margin-right: calc(var(--spacer-2) * -1);
|
|
416
|
-
background-color: var(--figma-color-text-secondary);
|
|
417
|
-
mask-image: var(--icon-steppers);
|
|
426
|
+
&:active {
|
|
427
|
+
background-color: var(--figma-color-text-tertiary);
|
|
418
428
|
}
|
|
419
429
|
}
|
|
430
|
+
|
|
431
|
+
fig-input-number[disabled]:not([disabled="false"]) & button {
|
|
432
|
+
pointer-events: none;
|
|
433
|
+
background-color: var(--figma-color-text-disabled);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
& .fig-stepper-up {
|
|
437
|
+
mask-image: var(--icon-chevron);
|
|
438
|
+
rotate: 180deg;
|
|
439
|
+
}
|
|
440
|
+
& .fig-stepper-down {
|
|
441
|
+
mask-image: var(--icon-chevron);
|
|
442
|
+
}
|
|
420
443
|
}
|
|
421
444
|
|
|
422
445
|
/* Textarea */
|
|
@@ -2681,6 +2704,7 @@ dialog[is="fig-toast"] {
|
|
|
2681
2704
|
justify-content: center;
|
|
2682
2705
|
min-width: 0;
|
|
2683
2706
|
color: var(--figma-color-text);
|
|
2707
|
+
background-color: var(--figma-color-bg);
|
|
2684
2708
|
|
|
2685
2709
|
&[open] {
|
|
2686
2710
|
display: flex;
|
|
@@ -2703,32 +2727,34 @@ dialog[is="fig-toast"] {
|
|
|
2703
2727
|
|
|
2704
2728
|
/* Theme: Dark (default) - hardcoded to ensure consistency regardless of global theme */
|
|
2705
2729
|
&[theme="dark"] {
|
|
2706
|
-
background-color: #2c2c2c;
|
|
2707
|
-
color: rgba(255, 255, 255, 0.9);
|
|
2708
2730
|
color-scheme: dark;
|
|
2709
2731
|
}
|
|
2710
2732
|
|
|
2711
2733
|
/* Theme: Light - hardcoded to ensure consistency regardless of global theme */
|
|
2712
2734
|
&[theme="light"] {
|
|
2713
|
-
background-color: #ffffff;
|
|
2714
|
-
color: rgba(0, 0, 0, 0.9);
|
|
2715
|
-
box-shadow: var(--figma-elevation-500-modal-window);
|
|
2716
2735
|
color-scheme: light;
|
|
2717
2736
|
}
|
|
2718
2737
|
|
|
2719
2738
|
/* Theme: Danger - hardcoded to ensure consistency regardless of global theme */
|
|
2720
2739
|
&[theme="danger"] {
|
|
2721
|
-
background-color:
|
|
2722
|
-
color: #ffffff;
|
|
2740
|
+
background-color: var(--figma-color-bg-danger);
|
|
2723
2741
|
color-scheme: dark;
|
|
2724
2742
|
}
|
|
2725
2743
|
|
|
2726
2744
|
/* Theme: Brand - hardcoded to ensure consistency regardless of global theme */
|
|
2727
2745
|
&[theme="brand"] {
|
|
2728
|
-
background-color:
|
|
2729
|
-
color:
|
|
2746
|
+
background-color: var(--figma-color-bg-brand);
|
|
2747
|
+
color-scheme: dark;
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
&[theme="success"] {
|
|
2751
|
+
background-color: var(--figma-color-bg-success);
|
|
2730
2752
|
color-scheme: dark;
|
|
2731
2753
|
}
|
|
2754
|
+
|
|
2755
|
+
&[theme="auto"] {
|
|
2756
|
+
/* color-scheme is resolved at runtime by FigToast JS */
|
|
2757
|
+
}
|
|
2732
2758
|
}
|
|
2733
2759
|
|
|
2734
2760
|
/* Tooltip */
|
|
@@ -2958,9 +2984,13 @@ fig-input-number {
|
|
|
2958
2984
|
flex: 1;
|
|
2959
2985
|
color: var(--figma-color-text);
|
|
2960
2986
|
|
|
2987
|
+
&[full]:not([full="false"]) {
|
|
2988
|
+
display: flex;
|
|
2989
|
+
width: 100%;
|
|
2990
|
+
}
|
|
2961
2991
|
&[multiline] {
|
|
2962
2992
|
display: flex;
|
|
2963
|
-
width: 100%;
|
|
2993
|
+
width: 100%;
|
|
2964
2994
|
}
|
|
2965
2995
|
&[autoresize] input,
|
|
2966
2996
|
&[autoresize] textarea {
|
|
@@ -3064,8 +3094,7 @@ fig-input-fill {
|
|
|
3064
3094
|
}
|
|
3065
3095
|
}
|
|
3066
3096
|
|
|
3067
|
-
fig-field[direction="horizontal"]
|
|
3068
|
-
fig-field[direction="row"] & {
|
|
3097
|
+
fig-field[direction="horizontal"] & {
|
|
3069
3098
|
flex: 1;
|
|
3070
3099
|
min-width: 0;
|
|
3071
3100
|
}
|
|
@@ -3082,8 +3111,7 @@ fig-slider {
|
|
|
3082
3111
|
flex-basis: 5rem;
|
|
3083
3112
|
}
|
|
3084
3113
|
|
|
3085
|
-
fig-field[direction="horizontal"]
|
|
3086
|
-
fig-field[direction="row"] & {
|
|
3114
|
+
fig-field[direction="horizontal"] & {
|
|
3087
3115
|
flex: 1;
|
|
3088
3116
|
min-width: 0;
|
|
3089
3117
|
}
|
|
@@ -3099,7 +3127,6 @@ fig-field,
|
|
|
3099
3127
|
gap: 0;
|
|
3100
3128
|
align-items: start;
|
|
3101
3129
|
|
|
3102
|
-
&[direction="row"],
|
|
3103
3130
|
&[direction="horizontal"] {
|
|
3104
3131
|
flex-direction: row;
|
|
3105
3132
|
align-items: center;
|
|
@@ -3121,10 +3148,13 @@ fig-field,
|
|
|
3121
3148
|
width: 100%;
|
|
3122
3149
|
}
|
|
3123
3150
|
|
|
3124
|
-
&[direction="row"] > label,
|
|
3125
3151
|
&[direction="horizontal"] > label {
|
|
3126
3152
|
width: auto;
|
|
3127
3153
|
min-width: var(--field-label-width);
|
|
3154
|
+
max-width: var(--field-label-width);
|
|
3155
|
+
overflow: hidden;
|
|
3156
|
+
text-overflow: ellipsis;
|
|
3157
|
+
white-space: nowrap;
|
|
3128
3158
|
}
|
|
3129
3159
|
|
|
3130
3160
|
&[direction="horizontal"] {
|
package/fig.js
CHANGED
|
@@ -2253,15 +2253,15 @@ class FigTabs extends HTMLElement {
|
|
|
2253
2253
|
this.setAttribute("role", "tablist");
|
|
2254
2254
|
this.addEventListener("click", this.handleClick.bind(this));
|
|
2255
2255
|
this.addEventListener("keydown", this.#handleKeyDown.bind(this));
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
}
|
|
2256
|
+
requestAnimationFrame(() => {
|
|
2257
|
+
const value = this.getAttribute("value");
|
|
2258
|
+
if (value) {
|
|
2259
|
+
this.#selectByValue(value);
|
|
2260
|
+
}
|
|
2261
|
+
if (this.hasAttribute("disabled")) {
|
|
2262
|
+
this.#applyDisabled(true);
|
|
2263
|
+
}
|
|
2264
|
+
});
|
|
2265
2265
|
}
|
|
2266
2266
|
|
|
2267
2267
|
#applyDisabled(disabled) {
|
|
@@ -2333,6 +2333,7 @@ class FigTabs extends HTMLElement {
|
|
|
2333
2333
|
for (const tab of tabs) {
|
|
2334
2334
|
if (tab.getAttribute("value") === value) {
|
|
2335
2335
|
this.selectedTab = tab;
|
|
2336
|
+
tab.setAttribute("selected", "true");
|
|
2336
2337
|
} else {
|
|
2337
2338
|
tab.removeAttribute("selected");
|
|
2338
2339
|
}
|
|
@@ -2353,7 +2354,6 @@ class FigTabs extends HTMLElement {
|
|
|
2353
2354
|
}
|
|
2354
2355
|
|
|
2355
2356
|
handleClick(event) {
|
|
2356
|
-
// Ignore clicks when disabled
|
|
2357
2357
|
if (this.hasAttribute("disabled")) return;
|
|
2358
2358
|
const target = event.target;
|
|
2359
2359
|
if (target.nodeName.toLowerCase() === "fig-tab") {
|
|
@@ -2361,6 +2361,7 @@ class FigTabs extends HTMLElement {
|
|
|
2361
2361
|
for (const tab of tabs) {
|
|
2362
2362
|
if (tab === target) {
|
|
2363
2363
|
this.selectedTab = tab;
|
|
2364
|
+
tab.setAttribute("selected", "true");
|
|
2364
2365
|
this.setAttribute("value", tab.getAttribute("value") || "");
|
|
2365
2366
|
} else {
|
|
2366
2367
|
tab.removeAttribute("selected");
|
|
@@ -3459,20 +3460,46 @@ class FigInputNumber extends HTMLElement {
|
|
|
3459
3460
|
#unitPosition;
|
|
3460
3461
|
#precision;
|
|
3461
3462
|
#isInteracting = false;
|
|
3463
|
+
#stepperEl = null;
|
|
3464
|
+
|
|
3465
|
+
#syncSteppers(hasSteppers) {
|
|
3466
|
+
if (hasSteppers && !this.#stepperEl) {
|
|
3467
|
+
this.#stepperEl = document.createElement("span");
|
|
3468
|
+
this.#stepperEl.className = "fig-steppers";
|
|
3469
|
+
this.#stepperEl.innerHTML =
|
|
3470
|
+
`<button class="fig-stepper-up" tabindex="-1" aria-label="Increase"></button>` +
|
|
3471
|
+
`<button class="fig-stepper-down" tabindex="-1" aria-label="Decrease"></button>`;
|
|
3472
|
+
this.#stepperEl.addEventListener("pointerdown", (e) => {
|
|
3473
|
+
e.preventDefault();
|
|
3474
|
+
e.stopPropagation();
|
|
3475
|
+
const btn = e.target.closest("button");
|
|
3476
|
+
if (!btn || this.disabled) return;
|
|
3477
|
+
const dir = btn.classList.contains("fig-stepper-up") ? 1 : -1;
|
|
3478
|
+
this.#stepValue(dir);
|
|
3479
|
+
this.input.focus();
|
|
3480
|
+
});
|
|
3481
|
+
this.append(this.#stepperEl);
|
|
3482
|
+
} else if (!hasSteppers && this.#stepperEl) {
|
|
3483
|
+
this.#stepperEl.remove();
|
|
3484
|
+
this.#stepperEl = null;
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3462
3487
|
|
|
3463
|
-
#
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
this.
|
|
3474
|
-
|
|
3475
|
-
|
|
3488
|
+
#stepValue(direction) {
|
|
3489
|
+
const step = this.step || 1;
|
|
3490
|
+
let numericValue = this.#getNumericValue(this.input.value);
|
|
3491
|
+
let value =
|
|
3492
|
+
(numericValue !== "" ? Number(numericValue) / (this.transform || 1) : 0) +
|
|
3493
|
+
step * direction;
|
|
3494
|
+
value = this.#sanitizeInput(value, false);
|
|
3495
|
+
this.value = value;
|
|
3496
|
+
this.input.value = this.#formatWithUnit(this.value);
|
|
3497
|
+
this.dispatchEvent(
|
|
3498
|
+
new CustomEvent("input", { detail: this.value, bubbles: true }),
|
|
3499
|
+
);
|
|
3500
|
+
this.dispatchEvent(
|
|
3501
|
+
new CustomEvent("change", { detail: this.value, bubbles: true }),
|
|
3502
|
+
);
|
|
3476
3503
|
}
|
|
3477
3504
|
|
|
3478
3505
|
constructor() {
|
|
@@ -3528,19 +3555,12 @@ class FigInputNumber extends HTMLElement {
|
|
|
3528
3555
|
this.hasAttribute("steppers") &&
|
|
3529
3556
|
this.getAttribute("steppers") !== "false";
|
|
3530
3557
|
|
|
3531
|
-
// Use type="number" when steppers are enabled (for native spin buttons)
|
|
3532
|
-
const inputType = hasSteppers ? "number" : "text";
|
|
3533
|
-
const inputMode = hasSteppers ? "" : 'inputmode="decimal"';
|
|
3534
|
-
const inputValue = hasSteppers
|
|
3535
|
-
? this.#transformNumber(this.value)
|
|
3536
|
-
: this.#formatWithUnit(this.value);
|
|
3537
|
-
|
|
3538
3558
|
let html = `<input
|
|
3539
|
-
type="
|
|
3540
|
-
|
|
3559
|
+
type="text"
|
|
3560
|
+
inputmode="decimal"
|
|
3541
3561
|
${this.name ? `name="${this.name}"` : ""}
|
|
3542
3562
|
placeholder="${this.placeholder}"
|
|
3543
|
-
value="${
|
|
3563
|
+
value="${this.#formatWithUnit(this.value)}" />`;
|
|
3544
3564
|
|
|
3545
3565
|
//child nodes hack
|
|
3546
3566
|
requestAnimationFrame(() => {
|
|
@@ -3569,7 +3589,8 @@ class FigInputNumber extends HTMLElement {
|
|
|
3569
3589
|
if (this.getAttribute("step")) {
|
|
3570
3590
|
this.step = Number(this.getAttribute("step"));
|
|
3571
3591
|
}
|
|
3572
|
-
|
|
3592
|
+
|
|
3593
|
+
this.#syncSteppers(hasSteppers);
|
|
3573
3594
|
|
|
3574
3595
|
// Set disabled state if present
|
|
3575
3596
|
if (this.hasAttribute("disabled")) {
|
|
@@ -3845,24 +3866,15 @@ class FigInputNumber extends HTMLElement {
|
|
|
3845
3866
|
break;
|
|
3846
3867
|
case "units":
|
|
3847
3868
|
this.#units = newValue || "";
|
|
3848
|
-
this.input.value =
|
|
3849
|
-
this.input.type === "number"
|
|
3850
|
-
? this.#transformNumber(this.value)
|
|
3851
|
-
: this.#formatWithUnit(this.value);
|
|
3869
|
+
this.input.value = this.#formatWithUnit(this.value);
|
|
3852
3870
|
break;
|
|
3853
3871
|
case "unit-position":
|
|
3854
3872
|
this.#unitPosition = newValue || "suffix";
|
|
3855
|
-
this.input.value =
|
|
3856
|
-
this.input.type === "number"
|
|
3857
|
-
? this.#transformNumber(this.value)
|
|
3858
|
-
: this.#formatWithUnit(this.value);
|
|
3873
|
+
this.input.value = this.#formatWithUnit(this.value);
|
|
3859
3874
|
break;
|
|
3860
3875
|
case "transform":
|
|
3861
3876
|
this.transform = Number(newValue) || 1;
|
|
3862
|
-
this.input.value =
|
|
3863
|
-
this.input.type === "number"
|
|
3864
|
-
? this.#transformNumber(this.value)
|
|
3865
|
-
: this.#formatWithUnit(this.value);
|
|
3877
|
+
this.input.value = this.#formatWithUnit(this.value);
|
|
3866
3878
|
break;
|
|
3867
3879
|
case "value":
|
|
3868
3880
|
if (this.#isInteracting) break;
|
|
@@ -3872,41 +3884,25 @@ class FigInputNumber extends HTMLElement {
|
|
|
3872
3884
|
value = this.#sanitizeInput(value, false);
|
|
3873
3885
|
}
|
|
3874
3886
|
this.value = value;
|
|
3875
|
-
this.input.value =
|
|
3876
|
-
this.input.type === "number"
|
|
3877
|
-
? this.#transformNumber(this.value)
|
|
3878
|
-
: this.#formatWithUnit(this.value);
|
|
3887
|
+
this.input.value = this.#formatWithUnit(this.value);
|
|
3879
3888
|
break;
|
|
3880
3889
|
case "min":
|
|
3881
3890
|
case "max":
|
|
3882
3891
|
case "step":
|
|
3883
3892
|
if (newValue === null || newValue === "") {
|
|
3884
3893
|
this[name] = undefined;
|
|
3885
|
-
this.#syncNativeNumberAttributes();
|
|
3886
3894
|
break;
|
|
3887
3895
|
}
|
|
3888
3896
|
this[name] = Number(newValue);
|
|
3889
|
-
this.#syncNativeNumberAttributes();
|
|
3890
3897
|
break;
|
|
3891
3898
|
case "steppers": {
|
|
3892
3899
|
const hasSteppers = newValue !== null && newValue !== "false";
|
|
3893
|
-
this
|
|
3894
|
-
if (hasSteppers) {
|
|
3895
|
-
this.input.removeAttribute("inputmode");
|
|
3896
|
-
this.#syncNativeNumberAttributes();
|
|
3897
|
-
this.input.value = this.#transformNumber(this.value);
|
|
3898
|
-
} else {
|
|
3899
|
-
this.input.setAttribute("inputmode", "decimal");
|
|
3900
|
-
this.input.value = this.#formatWithUnit(this.value);
|
|
3901
|
-
}
|
|
3900
|
+
this.#syncSteppers(hasSteppers);
|
|
3902
3901
|
break;
|
|
3903
3902
|
}
|
|
3904
3903
|
case "precision":
|
|
3905
3904
|
this.#precision = newValue !== null ? Number(newValue) : 2;
|
|
3906
|
-
this.input.value =
|
|
3907
|
-
this.input.type === "number"
|
|
3908
|
-
? this.#transformNumber(this.value)
|
|
3909
|
-
: this.#formatWithUnit(this.value);
|
|
3905
|
+
this.input.value = this.#formatWithUnit(this.value);
|
|
3910
3906
|
break;
|
|
3911
3907
|
case "name":
|
|
3912
3908
|
this[name] = this.input[name] = newValue;
|
|
@@ -5425,10 +5421,18 @@ class FigToast extends HTMLDialogElement {
|
|
|
5425
5421
|
}
|
|
5426
5422
|
}
|
|
5427
5423
|
|
|
5424
|
+
#resolveAutoTheme() {
|
|
5425
|
+
if (this.getAttribute("theme") !== "auto") return;
|
|
5426
|
+
const cs = getComputedStyle(document.documentElement).colorScheme || "";
|
|
5427
|
+
const isDark = cs.includes("dark");
|
|
5428
|
+
this.style.colorScheme = isDark ? "light" : "dark";
|
|
5429
|
+
}
|
|
5430
|
+
|
|
5428
5431
|
/**
|
|
5429
5432
|
* Show the toast notification (non-modal)
|
|
5430
5433
|
*/
|
|
5431
5434
|
showToast() {
|
|
5435
|
+
this.#resolveAutoTheme();
|
|
5432
5436
|
this.show(); // Non-modal show
|
|
5433
5437
|
this.applyPosition();
|
|
5434
5438
|
this.startAutoClose();
|
|
@@ -5460,6 +5464,14 @@ class FigToast extends HTMLDialogElement {
|
|
|
5460
5464
|
this.hideToast();
|
|
5461
5465
|
}
|
|
5462
5466
|
}
|
|
5467
|
+
|
|
5468
|
+
if (name === "theme") {
|
|
5469
|
+
if (newValue === "auto") {
|
|
5470
|
+
this.#resolveAutoTheme();
|
|
5471
|
+
} else {
|
|
5472
|
+
this.style.removeProperty("color-scheme");
|
|
5473
|
+
}
|
|
5474
|
+
}
|
|
5463
5475
|
}
|
|
5464
5476
|
}
|
|
5465
5477
|
figDefineCustomizedBuiltIn("fig-toast", FigToast, { extends: "dialog" });
|
package/package.json
CHANGED