@rogieking/figui3 3.14.1 → 3.15.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 +151 -112
- package/fig.js +308 -3
- package/package.json +1 -1
package/components.css
CHANGED
|
@@ -1175,18 +1175,24 @@ input[type="color"] {
|
|
|
1175
1175
|
}
|
|
1176
1176
|
|
|
1177
1177
|
fig-chit {
|
|
1178
|
-
contain: layout paint;
|
|
1179
1178
|
--size: 1.5rem;
|
|
1179
|
+
--padding: 5px;
|
|
1180
|
+
--width: var(--size);
|
|
1181
|
+
--height: var(--size);
|
|
1182
|
+
--border-radius: var(--radius-medium);
|
|
1180
1183
|
--chit-background: #d9d9d9;
|
|
1181
1184
|
--chit-bg-size: cover;
|
|
1182
1185
|
--chit-bg-position: center;
|
|
1186
|
+
--selected: 0;
|
|
1183
1187
|
--alpha: 1;
|
|
1184
1188
|
|
|
1185
1189
|
display: inline-grid;
|
|
1186
1190
|
width: var(--size);
|
|
1187
1191
|
height: var(--size);
|
|
1188
|
-
border-radius: var(--radius
|
|
1189
|
-
|
|
1192
|
+
border-radius: var(--border-radius);
|
|
1193
|
+
background-color: var(--figma-color-bg-secondary);
|
|
1194
|
+
box-shadow: inset 0 0 0 calc(var(--selected) * 1px)
|
|
1195
|
+
var(--figma-color-border-selected);
|
|
1190
1196
|
|
|
1191
1197
|
&::before,
|
|
1192
1198
|
&::after,
|
|
@@ -1195,130 +1201,94 @@ fig-chit {
|
|
|
1195
1201
|
}
|
|
1196
1202
|
|
|
1197
1203
|
/* Selection ring */
|
|
1198
|
-
&[selected]:not([selected="false"])
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
height: var(--size);
|
|
1202
|
-
z-index: 1;
|
|
1203
|
-
border-radius: var(--radius-medium);
|
|
1204
|
-
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
1204
|
+
&[selected]:not([selected="false"]) {
|
|
1205
|
+
--selected: 1;
|
|
1206
|
+
background-color: transparent;
|
|
1205
1207
|
}
|
|
1206
1208
|
|
|
1207
1209
|
&[size="medium"],
|
|
1208
1210
|
&[size="large"] {
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
height: var(--size);
|
|
1213
|
-
border-radius: var(--radius-medium);
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
input[type="color"]::-webkit-color-swatch-wrapper {
|
|
1217
|
-
border-radius: var(--radius-medium);
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
input[type="color"]::-webkit-color-swatch {
|
|
1221
|
-
border-radius: var(--radius-medium);
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
input[type="color"]::-moz-color-swatch {
|
|
1225
|
-
border-radius: var(--radius-medium);
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
&[selected]:not([selected="false"])::before {
|
|
1229
|
-
box-shadow:
|
|
1230
|
-
inset 0 0 0 1px var(--figma-color-border-selected),
|
|
1231
|
-
inset 0 0 0 3px var(--figma-color-bg);
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
&[data-type="gradient"]::after,
|
|
1235
|
-
&[data-type="image"]::after,
|
|
1236
|
-
&[data-type="gradient"]::before,
|
|
1237
|
-
&[data-type="image"]::before {
|
|
1238
|
-
width: var(--size);
|
|
1239
|
-
height: var(--size);
|
|
1240
|
-
border-radius: var(--radius-medium);
|
|
1211
|
+
--padding: 0px;
|
|
1212
|
+
&[selected]:not([selected="false"]) {
|
|
1213
|
+
--padding: 3px;
|
|
1241
1214
|
}
|
|
1242
1215
|
}
|
|
1243
1216
|
|
|
1244
1217
|
&[size="medium"] {
|
|
1245
1218
|
--size: 1.5rem;
|
|
1219
|
+
--padding: 0px;
|
|
1246
1220
|
}
|
|
1247
1221
|
|
|
1248
1222
|
&[size="large"] {
|
|
1249
1223
|
--size: 2rem;
|
|
1224
|
+
--padding: 0px;
|
|
1250
1225
|
}
|
|
1251
1226
|
|
|
1252
1227
|
&[disabled] {
|
|
1253
1228
|
pointer-events: none;
|
|
1254
1229
|
}
|
|
1255
1230
|
|
|
1231
|
+
&::before,
|
|
1232
|
+
&::after {
|
|
1233
|
+
content: "";
|
|
1234
|
+
width: var(--width);
|
|
1235
|
+
height: var(--height);
|
|
1236
|
+
border-radius: calc(var(--border-radius) - (var(--padding) / 2));
|
|
1237
|
+
width: calc(var(--width) - var(--padding) * 2);
|
|
1238
|
+
height: calc(var(--height) - var(--padding) * 2);
|
|
1239
|
+
grid-area: 1/1;
|
|
1240
|
+
place-self: center;
|
|
1241
|
+
pointer-events: none;
|
|
1242
|
+
}
|
|
1243
|
+
&::after {
|
|
1244
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-bordertranslucent);
|
|
1245
|
+
z-index: 1;
|
|
1246
|
+
}
|
|
1256
1247
|
&::before {
|
|
1257
1248
|
content: "";
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1249
|
+
background: var(--chit-background);
|
|
1250
|
+
background-size: var(--chit-bg-size);
|
|
1251
|
+
background-position: var(--chit-bg-position);
|
|
1252
|
+
background-repeat: no-repeat;
|
|
1253
|
+
border-radius: calc(var(--border-radius) - (var(--padding) / 2));
|
|
1254
|
+
mask-image: linear-gradient(
|
|
1255
|
+
to right,
|
|
1256
|
+
black 0%,
|
|
1257
|
+
black 50%,
|
|
1258
|
+
rgba(0, 0, 0, var(--alpha)) 50%
|
|
1259
|
+
);
|
|
1261
1260
|
grid-area: 1/1;
|
|
1262
1261
|
place-self: center;
|
|
1263
1262
|
}
|
|
1263
|
+
&[size="medium"]::before,
|
|
1264
1264
|
&[size="large"]::before {
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1265
|
+
border-radius: calc(var(--border-radius) - var(--padding));
|
|
1266
|
+
}
|
|
1267
|
+
input[type="color"] {
|
|
1268
|
+
background: none;
|
|
1269
|
+
width: var(--width);
|
|
1270
|
+
height: var(--height);
|
|
1271
|
+
background: none;
|
|
1272
|
+
grid-area: 1/1;
|
|
1273
|
+
place-self: center;
|
|
1274
|
+
box-sizing: border-box;
|
|
1275
|
+
opacity: 0;
|
|
1268
1276
|
}
|
|
1269
1277
|
|
|
1270
1278
|
/* Gradient/Image types - inset thumbnail with hidden input */
|
|
1271
1279
|
&[data-type="gradient"],
|
|
1272
1280
|
&[data-type="image"] {
|
|
1273
1281
|
background-color: var(--figma-color-bg-secondary);
|
|
1274
|
-
|
|
1275
|
-
&::after {
|
|
1276
|
-
content: "";
|
|
1277
|
-
width: 0.875rem;
|
|
1278
|
-
height: 0.875rem;
|
|
1279
|
-
|
|
1280
|
-
background: var(--chit-background);
|
|
1281
|
-
background-size: var(--chit-bg-size);
|
|
1282
|
-
background-position: var(--chit-bg-position);
|
|
1283
|
-
background-repeat: no-repeat;
|
|
1284
|
-
border-radius: 0.125rem;
|
|
1285
|
-
box-shadow: inset 0 0 0 1px var(--figma-color-bordertranslucent);
|
|
1286
|
-
mask-image: linear-gradient(
|
|
1287
|
-
to right,
|
|
1288
|
-
black 0%,
|
|
1289
|
-
black 50%,
|
|
1290
|
-
rgba(0, 0, 0, var(--alpha)) 50%
|
|
1291
|
-
);
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
&::after,
|
|
1295
|
-
input {
|
|
1296
|
-
grid-area: 1/1;
|
|
1297
|
-
place-self: center;
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
1282
|
input[type="color"] {
|
|
1301
|
-
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
input[type="color"]::-webkit-color-swatch-wrapper {
|
|
1305
|
-
background: none;
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
input[type="color"]::-moz-color-swatch {
|
|
1309
|
-
opacity: 0;
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
input[type="color"]::-webkit-color-swatch {
|
|
1313
|
-
opacity: 0;
|
|
1283
|
+
display: none;
|
|
1314
1284
|
}
|
|
1315
1285
|
}
|
|
1316
1286
|
|
|
1317
1287
|
/* Checkerboard for empty/missing images */
|
|
1318
|
-
&[data-type="image"]:not([background])::
|
|
1319
|
-
&[data-type="image"][background=""]::
|
|
1320
|
-
&[data-type="image"][background="url()"]::
|
|
1321
|
-
&[checkerboard]:not([checkerboard="false"])::
|
|
1288
|
+
&[data-type="image"]:not([background])::after,
|
|
1289
|
+
&[data-type="image"][background=""]::after,
|
|
1290
|
+
&[data-type="image"][background="url()"]::after,
|
|
1291
|
+
&[checkerboard]:not([checkerboard="false"])::after {
|
|
1322
1292
|
background: var(--checkerboard);
|
|
1323
1293
|
}
|
|
1324
1294
|
}
|
|
@@ -1338,8 +1308,11 @@ fig-image {
|
|
|
1338
1308
|
> * {
|
|
1339
1309
|
grid-area: 1/1;
|
|
1340
1310
|
}
|
|
1341
|
-
fig-chit {
|
|
1311
|
+
fig-chit[size="large"] {
|
|
1342
1312
|
--size: 100% !important;
|
|
1313
|
+
--width: 100% !important;
|
|
1314
|
+
--height: 100% !important;
|
|
1315
|
+
--padding: 0px;
|
|
1343
1316
|
--chit-bg-size: var(--fit);
|
|
1344
1317
|
&[disabled] {
|
|
1345
1318
|
opacity: 1;
|
|
@@ -2900,7 +2873,8 @@ fig-checkbox,
|
|
|
2900
2873
|
fig-radio,
|
|
2901
2874
|
fig-tab,
|
|
2902
2875
|
fig-tabs,
|
|
2903
|
-
fig-segmented-control
|
|
2876
|
+
fig-segmented-control,
|
|
2877
|
+
fig-input-palette {
|
|
2904
2878
|
display: inline-flex;
|
|
2905
2879
|
gap: var(--spacer-2);
|
|
2906
2880
|
user-select: none;
|
|
@@ -3136,6 +3110,7 @@ fig-input-fill {
|
|
|
3136
3110
|
background-color: transparent !important;
|
|
3137
3111
|
box-shadow: none !important;
|
|
3138
3112
|
border: 0 !important;
|
|
3113
|
+
--selected: 0;
|
|
3139
3114
|
}
|
|
3140
3115
|
}
|
|
3141
3116
|
fig-chit ~ fig-input-text > input,
|
|
@@ -3177,21 +3152,12 @@ fig-input-gradient {
|
|
|
3177
3152
|
outline: 1px solid var(--figma-color-border-selected) !important;
|
|
3178
3153
|
outline-offset: -1px !important;
|
|
3179
3154
|
}
|
|
3180
|
-
fig-chit {
|
|
3155
|
+
& > fig-chit {
|
|
3156
|
+
--padding: 0;
|
|
3157
|
+
--width: 100%;
|
|
3181
3158
|
flex: 1 1 auto;
|
|
3182
3159
|
width: 100% !important;
|
|
3183
3160
|
min-width: 0 !important;
|
|
3184
|
-
&::before,
|
|
3185
|
-
&::after {
|
|
3186
|
-
width: 100% !important;
|
|
3187
|
-
place-self: stretch;
|
|
3188
|
-
}
|
|
3189
|
-
&[data-type="gradient"]::after {
|
|
3190
|
-
width: calc(100% - 0.625rem);
|
|
3191
|
-
height: 0.875rem;
|
|
3192
|
-
justify-self: center;
|
|
3193
|
-
align-self: center;
|
|
3194
|
-
}
|
|
3195
3161
|
}
|
|
3196
3162
|
|
|
3197
3163
|
.fig-input-gradient-track {
|
|
@@ -3212,6 +3178,83 @@ fig-input-gradient {
|
|
|
3212
3178
|
}
|
|
3213
3179
|
}
|
|
3214
3180
|
|
|
3181
|
+
fig-input-palette {
|
|
3182
|
+
display: inline-grid !important;
|
|
3183
|
+
grid-template-columns: 1fr 24px;
|
|
3184
|
+
grid-template-areas: "inputs button";
|
|
3185
|
+
gap: var(--spacer-1);
|
|
3186
|
+
width: 100%;
|
|
3187
|
+
|
|
3188
|
+
.palette-colors {
|
|
3189
|
+
display: flex;
|
|
3190
|
+
flex-wrap: nowrap;
|
|
3191
|
+
gap: 0;
|
|
3192
|
+
border-radius: var(--radius-medium);
|
|
3193
|
+
overflow: hidden;
|
|
3194
|
+
grid-area: inputs;
|
|
3195
|
+
min-width: 0;
|
|
3196
|
+
width: 100%;
|
|
3197
|
+
}
|
|
3198
|
+
|
|
3199
|
+
.palette-add-btn {
|
|
3200
|
+
grid-area: button;
|
|
3201
|
+
}
|
|
3202
|
+
|
|
3203
|
+
&:not([expanded]),
|
|
3204
|
+
&[expanded="false"] {
|
|
3205
|
+
.palette-colors {
|
|
3206
|
+
display: flex;
|
|
3207
|
+
background-color: var(--figma-color-bg-secondary);
|
|
3208
|
+
|
|
3209
|
+
> fig-input-color {
|
|
3210
|
+
display: contents;
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
fig-chit {
|
|
3214
|
+
--padding: 0px;
|
|
3215
|
+
--border-radius: 0px;
|
|
3216
|
+
--width: 100%;
|
|
3217
|
+
flex: 1;
|
|
3218
|
+
min-width: 0;
|
|
3219
|
+
width: 100% !important;
|
|
3220
|
+
height: var(--size);
|
|
3221
|
+
border-radius: 0 !important;
|
|
3222
|
+
input,
|
|
3223
|
+
&::before,
|
|
3224
|
+
&::after {
|
|
3225
|
+
padding: 0 !important;
|
|
3226
|
+
border-radius: 0 !important;
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
|
|
3232
|
+
&[expanded]:not([expanded="false"]) {
|
|
3233
|
+
.palette-colors {
|
|
3234
|
+
flex-direction: column;
|
|
3235
|
+
overflow: visible;
|
|
3236
|
+
border-radius: 0;
|
|
3237
|
+
gap: var(--spacer-2);
|
|
3238
|
+
background-color: transparent;
|
|
3239
|
+
|
|
3240
|
+
> fig-input-color {
|
|
3241
|
+
min-width: 0;
|
|
3242
|
+
}
|
|
3243
|
+
|
|
3244
|
+
fig-chit {
|
|
3245
|
+
--border-radius: var(--radius-medium);
|
|
3246
|
+
width: auto !important;
|
|
3247
|
+
height: var(--size);
|
|
3248
|
+
border-radius: var(--radius-medium) !important;
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3254
|
+
fig-field[direction="horizontal"]:has(> fig-input-palette) {
|
|
3255
|
+
padding-right: var(--spacer-2);
|
|
3256
|
+
}
|
|
3257
|
+
|
|
3215
3258
|
fig-slider {
|
|
3216
3259
|
display: flex;
|
|
3217
3260
|
|
|
@@ -4849,10 +4892,6 @@ fig-color-tip {
|
|
|
4849
4892
|
}
|
|
4850
4893
|
}
|
|
4851
4894
|
|
|
4852
|
-
&[selected]:not([selected="false"]) {
|
|
4853
|
-
outline: var(--tip-selection-width) solid var(--figma-color-border-selected);
|
|
4854
|
-
}
|
|
4855
|
-
|
|
4856
4895
|
&[selected]:not([selected="false"]):before {
|
|
4857
4896
|
content: "";
|
|
4858
4897
|
background: var(--figma-color-border-selected);
|
|
@@ -4860,7 +4899,7 @@ fig-color-tip {
|
|
|
4860
4899
|
width: 6px;
|
|
4861
4900
|
height: 3px;
|
|
4862
4901
|
position: absolute;
|
|
4863
|
-
top:
|
|
4902
|
+
top: 100%;
|
|
4864
4903
|
left: var(--beak-offset, 50%);
|
|
4865
4904
|
z-index: 1;
|
|
4866
4905
|
pointer-events: none;
|
|
@@ -4875,9 +4914,9 @@ fig-color-tip {
|
|
|
4875
4914
|
width: 6px;
|
|
4876
4915
|
height: 3px;
|
|
4877
4916
|
position: absolute;
|
|
4878
|
-
top: 100
|
|
4917
|
+
top: calc(100% - 1px);
|
|
4879
4918
|
left: var(--beak-offset, 50%);
|
|
4880
|
-
z-index:
|
|
4919
|
+
z-index: 3;
|
|
4881
4920
|
transform: translate(-50%);
|
|
4882
4921
|
}
|
|
4883
4922
|
|
package/fig.js
CHANGED
|
@@ -4521,7 +4521,8 @@ class FigInputColor extends HTMLElement {
|
|
|
4521
4521
|
const fpAttrs = this.#buildFillPickerAttrs();
|
|
4522
4522
|
|
|
4523
4523
|
let html = ``;
|
|
4524
|
-
|
|
4524
|
+
const showText = this.getAttribute("text") === "true";
|
|
4525
|
+
if (showText) {
|
|
4525
4526
|
let label = `<fig-input-text
|
|
4526
4527
|
type="text"
|
|
4527
4528
|
placeholder="000000"
|
|
@@ -4758,7 +4759,7 @@ class FigInputColor extends HTMLElement {
|
|
|
4758
4759
|
}
|
|
4759
4760
|
|
|
4760
4761
|
static get observedAttributes() {
|
|
4761
|
-
return ["value", "style", "mode", "picker", "experimental", "alpha"];
|
|
4762
|
+
return ["value", "style", "mode", "picker", "experimental", "alpha", "text"];
|
|
4762
4763
|
}
|
|
4763
4764
|
|
|
4764
4765
|
get mode() {
|
|
@@ -4809,6 +4810,7 @@ class FigInputColor extends HTMLElement {
|
|
|
4809
4810
|
// Picker type change requires re-render
|
|
4810
4811
|
break;
|
|
4811
4812
|
case "alpha":
|
|
4813
|
+
case "text":
|
|
4812
4814
|
if (this.isConnected) this.#buildUI();
|
|
4813
4815
|
break;
|
|
4814
4816
|
}
|
|
@@ -5683,6 +5685,287 @@ class FigInputFill extends HTMLElement {
|
|
|
5683
5685
|
}
|
|
5684
5686
|
customElements.define("fig-input-fill", FigInputFill);
|
|
5685
5687
|
|
|
5688
|
+
/* Input Palette */
|
|
5689
|
+
/**
|
|
5690
|
+
* A palette of solid colors, each rendered as a fig-input-color swatch.
|
|
5691
|
+
* Manages an internal array of colors with add support.
|
|
5692
|
+
* @attr {string} value - JSON array of hex strings or {color,alpha} objects, or comma-separated hex
|
|
5693
|
+
* @attr {boolean} disabled - Whether the palette is disabled
|
|
5694
|
+
* @attr {number} min - Minimum number of colors (default: 2)
|
|
5695
|
+
* @attr {number} max - Maximum number of colors (default: 8); add button hidden at max
|
|
5696
|
+
* @fires input - During color editing (detail: full color array)
|
|
5697
|
+
* @fires change - On committed color edits or add (detail: full color array)
|
|
5698
|
+
*/
|
|
5699
|
+
class FigInputPalette extends HTMLElement {
|
|
5700
|
+
#colors = [];
|
|
5701
|
+
#pickers = [];
|
|
5702
|
+
#renderRAF = null;
|
|
5703
|
+
|
|
5704
|
+
static get observedAttributes() {
|
|
5705
|
+
return ["value", "disabled", "min", "max", "expanded"];
|
|
5706
|
+
}
|
|
5707
|
+
|
|
5708
|
+
get #expanded() {
|
|
5709
|
+
return this.hasAttribute("expanded") && this.getAttribute("expanded") !== "false";
|
|
5710
|
+
}
|
|
5711
|
+
|
|
5712
|
+
get #min() {
|
|
5713
|
+
const v = parseInt(this.getAttribute("min"));
|
|
5714
|
+
return isNaN(v) ? 2 : v;
|
|
5715
|
+
}
|
|
5716
|
+
|
|
5717
|
+
get #max() {
|
|
5718
|
+
const v = parseInt(this.getAttribute("max"));
|
|
5719
|
+
return isNaN(v) ? 8 : v;
|
|
5720
|
+
}
|
|
5721
|
+
|
|
5722
|
+
connectedCallback() {
|
|
5723
|
+
if (this.#renderRAF) cancelAnimationFrame(this.#renderRAF);
|
|
5724
|
+
this.#renderRAF = requestAnimationFrame(() => {
|
|
5725
|
+
this.#renderRAF = null;
|
|
5726
|
+
this.#parseValue();
|
|
5727
|
+
this.#render();
|
|
5728
|
+
});
|
|
5729
|
+
}
|
|
5730
|
+
|
|
5731
|
+
disconnectedCallback() {
|
|
5732
|
+
if (this.#renderRAF) {
|
|
5733
|
+
cancelAnimationFrame(this.#renderRAF);
|
|
5734
|
+
this.#renderRAF = null;
|
|
5735
|
+
}
|
|
5736
|
+
this.#pickers = [];
|
|
5737
|
+
}
|
|
5738
|
+
|
|
5739
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
5740
|
+
if (oldValue === newValue) return;
|
|
5741
|
+
|
|
5742
|
+
switch (name) {
|
|
5743
|
+
case "value":
|
|
5744
|
+
this.#parseValue();
|
|
5745
|
+
this.#syncPickers();
|
|
5746
|
+
break;
|
|
5747
|
+
case "disabled":
|
|
5748
|
+
this.#syncDisabled();
|
|
5749
|
+
break;
|
|
5750
|
+
case "min":
|
|
5751
|
+
case "max":
|
|
5752
|
+
case "expanded":
|
|
5753
|
+
this.#render();
|
|
5754
|
+
break;
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5757
|
+
|
|
5758
|
+
#parseValue() {
|
|
5759
|
+
const raw = this.getAttribute("value");
|
|
5760
|
+
if (!raw) {
|
|
5761
|
+
this.#colors = [];
|
|
5762
|
+
return;
|
|
5763
|
+
}
|
|
5764
|
+
|
|
5765
|
+
const trimmed = raw.trim();
|
|
5766
|
+
|
|
5767
|
+
// Try JSON first
|
|
5768
|
+
try {
|
|
5769
|
+
const parsed = JSON.parse(trimmed);
|
|
5770
|
+
if (Array.isArray(parsed)) {
|
|
5771
|
+
this.#colors = parsed.map((entry) => {
|
|
5772
|
+
if (typeof entry === "string") {
|
|
5773
|
+
return { color: entry.slice(0, 7), alpha: entry.length > 7 ? parseInt(entry.slice(7, 9), 16) / 255 : 1 };
|
|
5774
|
+
}
|
|
5775
|
+
if (entry && typeof entry === "object") {
|
|
5776
|
+
return {
|
|
5777
|
+
color: entry.color || "#D9D9D9",
|
|
5778
|
+
alpha: entry.alpha !== undefined ? entry.alpha : (entry.opacity !== undefined ? entry.opacity / 100 : 1),
|
|
5779
|
+
};
|
|
5780
|
+
}
|
|
5781
|
+
return { color: "#D9D9D9", alpha: 1 };
|
|
5782
|
+
});
|
|
5783
|
+
return;
|
|
5784
|
+
}
|
|
5785
|
+
} catch (e) {
|
|
5786
|
+
// Not JSON — try comma-separated hex
|
|
5787
|
+
}
|
|
5788
|
+
|
|
5789
|
+
// Comma-separated hex
|
|
5790
|
+
if (trimmed.includes(",")) {
|
|
5791
|
+
this.#colors = trimmed.split(",").map((s) => {
|
|
5792
|
+
const hex = s.trim();
|
|
5793
|
+
return {
|
|
5794
|
+
color: hex.slice(0, 7),
|
|
5795
|
+
alpha: hex.length > 7 ? parseInt(hex.slice(7, 9), 16) / 255 : 1,
|
|
5796
|
+
};
|
|
5797
|
+
});
|
|
5798
|
+
return;
|
|
5799
|
+
}
|
|
5800
|
+
|
|
5801
|
+
// Single hex
|
|
5802
|
+
if (trimmed.startsWith("#")) {
|
|
5803
|
+
this.#colors = [{
|
|
5804
|
+
color: trimmed.slice(0, 7),
|
|
5805
|
+
alpha: trimmed.length > 7 ? parseInt(trimmed.slice(7, 9), 16) / 255 : 1,
|
|
5806
|
+
}];
|
|
5807
|
+
return;
|
|
5808
|
+
}
|
|
5809
|
+
|
|
5810
|
+
this.#colors = [];
|
|
5811
|
+
}
|
|
5812
|
+
|
|
5813
|
+
get value() {
|
|
5814
|
+
return this.#colors.map((c) => ({ ...c }));
|
|
5815
|
+
}
|
|
5816
|
+
|
|
5817
|
+
set value(val) {
|
|
5818
|
+
if (typeof val === "string") {
|
|
5819
|
+
this.setAttribute("value", val);
|
|
5820
|
+
} else {
|
|
5821
|
+
this.setAttribute("value", JSON.stringify(val));
|
|
5822
|
+
}
|
|
5823
|
+
}
|
|
5824
|
+
|
|
5825
|
+
#render() {
|
|
5826
|
+
const disabled = this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false";
|
|
5827
|
+
|
|
5828
|
+
this.innerHTML = "";
|
|
5829
|
+
this.#pickers = [];
|
|
5830
|
+
|
|
5831
|
+
const wrap = document.createElement("div");
|
|
5832
|
+
wrap.className = "palette-colors";
|
|
5833
|
+
this.#colors.forEach((entry, i) => {
|
|
5834
|
+
wrap.appendChild(this.#createPicker(entry, i, disabled));
|
|
5835
|
+
});
|
|
5836
|
+
this.appendChild(wrap);
|
|
5837
|
+
|
|
5838
|
+
this.#createAddButton(disabled);
|
|
5839
|
+
}
|
|
5840
|
+
|
|
5841
|
+
#createPicker(entry, index, disabled) {
|
|
5842
|
+
const hexAlpha = entry.alpha < 1
|
|
5843
|
+
? entry.color + Math.round(entry.alpha * 255).toString(16).padStart(2, "0")
|
|
5844
|
+
: entry.color;
|
|
5845
|
+
const expanded = this.#expanded;
|
|
5846
|
+
const ic = document.createElement("fig-input-color");
|
|
5847
|
+
ic.setAttribute("value", hexAlpha);
|
|
5848
|
+
ic.setAttribute("text", expanded ? "true" : "false");
|
|
5849
|
+
ic.setAttribute("picker", "figma");
|
|
5850
|
+
ic.setAttribute("alpha", "true");
|
|
5851
|
+
ic.setAttribute("picker-anchor", "self");
|
|
5852
|
+
if (expanded) ic.setAttribute("full", "");
|
|
5853
|
+
if (disabled) ic.setAttribute("disabled", "");
|
|
5854
|
+
|
|
5855
|
+
const updateFromPicker = (e) => {
|
|
5856
|
+
e.stopPropagation();
|
|
5857
|
+
const el = e.currentTarget;
|
|
5858
|
+
this.#colors[index] = {
|
|
5859
|
+
color: el.hexOpaque || this.#colors[index].color,
|
|
5860
|
+
alpha: el.rgba ? el.rgba.a : this.#colors[index].alpha,
|
|
5861
|
+
};
|
|
5862
|
+
};
|
|
5863
|
+
|
|
5864
|
+
ic.addEventListener("input", (e) => {
|
|
5865
|
+
updateFromPicker(e);
|
|
5866
|
+
this.#emitInput();
|
|
5867
|
+
});
|
|
5868
|
+
|
|
5869
|
+
ic.addEventListener("change", (e) => {
|
|
5870
|
+
updateFromPicker(e);
|
|
5871
|
+
this.#emitChange();
|
|
5872
|
+
});
|
|
5873
|
+
|
|
5874
|
+
this.#pickers.push(ic);
|
|
5875
|
+
return ic;
|
|
5876
|
+
}
|
|
5877
|
+
|
|
5878
|
+
#createAddButton(disabled) {
|
|
5879
|
+
const atMax = this.#colors.length >= this.#max;
|
|
5880
|
+
const addBtn = document.createElement("fig-button");
|
|
5881
|
+
addBtn.setAttribute("variant", "ghost");
|
|
5882
|
+
addBtn.setAttribute("icon", "true");
|
|
5883
|
+
addBtn.setAttribute("aria-label", "Add color");
|
|
5884
|
+
addBtn.className = "palette-add-btn";
|
|
5885
|
+
if (disabled || atMax) addBtn.setAttribute("disabled", "");
|
|
5886
|
+
addBtn.innerHTML = `<span class="fig-mask-icon" style="--icon: var(--icon-add)"></span>`;
|
|
5887
|
+
addBtn.addEventListener("click", () => {
|
|
5888
|
+
if (this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false") return;
|
|
5889
|
+
if (this.#colors.length >= this.#max) return;
|
|
5890
|
+
this.#addColor({ color: "#D9D9D9", alpha: 1 });
|
|
5891
|
+
});
|
|
5892
|
+
const tooltip = document.createElement("fig-tooltip");
|
|
5893
|
+
tooltip.setAttribute("text", "Add color");
|
|
5894
|
+
tooltip.appendChild(addBtn);
|
|
5895
|
+
this.appendChild(tooltip);
|
|
5896
|
+
}
|
|
5897
|
+
|
|
5898
|
+
#addColor(entry) {
|
|
5899
|
+
this.#colors.push(entry);
|
|
5900
|
+
const disabled = this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false";
|
|
5901
|
+
const ic = this.#createPicker(entry, this.#colors.length - 1, disabled);
|
|
5902
|
+
const wrap = this.querySelector(".palette-colors");
|
|
5903
|
+
if (wrap) {
|
|
5904
|
+
wrap.appendChild(ic);
|
|
5905
|
+
} else {
|
|
5906
|
+
this.appendChild(ic);
|
|
5907
|
+
}
|
|
5908
|
+
|
|
5909
|
+
if (this.#colors.length >= this.#max) {
|
|
5910
|
+
const addBtn = this.querySelector(".palette-add-btn");
|
|
5911
|
+
if (addBtn) addBtn.setAttribute("disabled", "");
|
|
5912
|
+
}
|
|
5913
|
+
this.#emitChange();
|
|
5914
|
+
}
|
|
5915
|
+
|
|
5916
|
+
#updateChit(index) {
|
|
5917
|
+
const ic = this.#pickers[index];
|
|
5918
|
+
if (!ic) return;
|
|
5919
|
+
const entry = this.#colors[index];
|
|
5920
|
+
const hexAlpha = entry.alpha < 1
|
|
5921
|
+
? entry.color + Math.round(entry.alpha * 255).toString(16).padStart(2, "0")
|
|
5922
|
+
: entry.color;
|
|
5923
|
+
ic.setAttribute("value", hexAlpha);
|
|
5924
|
+
}
|
|
5925
|
+
|
|
5926
|
+
#syncPickers() {
|
|
5927
|
+
if (this.#pickers.length !== this.#colors.length) {
|
|
5928
|
+
this.#render();
|
|
5929
|
+
return;
|
|
5930
|
+
}
|
|
5931
|
+
this.#colors.forEach((_, i) => {
|
|
5932
|
+
this.#updateChit(i);
|
|
5933
|
+
});
|
|
5934
|
+
}
|
|
5935
|
+
|
|
5936
|
+
#syncDisabled() {
|
|
5937
|
+
const disabled = this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false";
|
|
5938
|
+
this.#pickers.forEach((fp) => {
|
|
5939
|
+
if (disabled) fp.setAttribute("disabled", "");
|
|
5940
|
+
else fp.removeAttribute("disabled");
|
|
5941
|
+
});
|
|
5942
|
+
const addBtn = this.querySelector(".palette-add-btn");
|
|
5943
|
+
if (addBtn) {
|
|
5944
|
+
if (disabled) addBtn.setAttribute("disabled", "");
|
|
5945
|
+
else addBtn.removeAttribute("disabled");
|
|
5946
|
+
}
|
|
5947
|
+
}
|
|
5948
|
+
|
|
5949
|
+
#emitInput() {
|
|
5950
|
+
this.dispatchEvent(
|
|
5951
|
+
new CustomEvent("input", {
|
|
5952
|
+
bubbles: true,
|
|
5953
|
+
detail: this.value,
|
|
5954
|
+
}),
|
|
5955
|
+
);
|
|
5956
|
+
}
|
|
5957
|
+
|
|
5958
|
+
#emitChange() {
|
|
5959
|
+
this.dispatchEvent(
|
|
5960
|
+
new CustomEvent("change", {
|
|
5961
|
+
bubbles: true,
|
|
5962
|
+
detail: this.value,
|
|
5963
|
+
}),
|
|
5964
|
+
);
|
|
5965
|
+
}
|
|
5966
|
+
}
|
|
5967
|
+
customElements.define("fig-input-palette", FigInputPalette);
|
|
5968
|
+
|
|
5686
5969
|
/* Input Gradient */
|
|
5687
5970
|
/**
|
|
5688
5971
|
* A gradient-only fill input built on top of fig-fill-picker.
|
|
@@ -10075,6 +10358,7 @@ class FigFillPicker extends HTMLElement {
|
|
|
10075
10358
|
this.#teardownColorAreaEvents();
|
|
10076
10359
|
this.#teardownColorAreaEvents = null;
|
|
10077
10360
|
}
|
|
10361
|
+
if (this.#chit) this.#chit.removeAttribute("selected");
|
|
10078
10362
|
if (this.#dialog) {
|
|
10079
10363
|
this.#dialog.close();
|
|
10080
10364
|
this.#dialog.remove();
|
|
@@ -10252,6 +10536,8 @@ class FigFillPicker extends HTMLElement {
|
|
|
10252
10536
|
const gamutEl = this.#dialog.querySelector(".fig-fill-picker-gamut");
|
|
10253
10537
|
if (gamutEl) gamutEl.value = this.#gamut;
|
|
10254
10538
|
|
|
10539
|
+
if (this.#chit) this.#chit.setAttribute("selected", "true");
|
|
10540
|
+
|
|
10255
10541
|
this.#dialog.open = true;
|
|
10256
10542
|
|
|
10257
10543
|
requestAnimationFrame(() => {
|
|
@@ -10406,9 +10692,17 @@ class FigFillPicker extends HTMLElement {
|
|
|
10406
10692
|
this.#dialog.open = false;
|
|
10407
10693
|
});
|
|
10408
10694
|
|
|
10409
|
-
|
|
10695
|
+
const onDialogClose = () => {
|
|
10696
|
+
if (this.#chit) this.#chit.removeAttribute("selected");
|
|
10410
10697
|
this.#emitChange();
|
|
10698
|
+
};
|
|
10699
|
+
this.#dialog.addEventListener("close", onDialogClose);
|
|
10700
|
+
|
|
10701
|
+
const observer = new MutationObserver(() => {
|
|
10702
|
+
const isOpen = this.#dialog.hasAttribute("open") && this.#dialog.getAttribute("open") !== "false";
|
|
10703
|
+
if (!isOpen) onDialogClose();
|
|
10411
10704
|
});
|
|
10705
|
+
observer.observe(this.#dialog, { attributes: true, attributeFilter: ["open"] });
|
|
10412
10706
|
|
|
10413
10707
|
// Initialize built-in tabs (skip any overridden by custom slots)
|
|
10414
10708
|
const builtinInits = {
|
|
@@ -13059,6 +13353,7 @@ class FigHandle extends HTMLElement {
|
|
|
13059
13353
|
this.#syncDrag();
|
|
13060
13354
|
this.addEventListener("click", this.#handleSelect);
|
|
13061
13355
|
document.addEventListener("pointerdown", this.#handleDeselect);
|
|
13356
|
+
document.addEventListener("keydown", this.#handleKeyDown);
|
|
13062
13357
|
const initial = this.getAttribute("value");
|
|
13063
13358
|
if (initial) this.#applyValue(initial);
|
|
13064
13359
|
if (this.#hasControlMode && !this.#isGhost) this.#showColorTip();
|
|
@@ -13069,6 +13364,7 @@ class FigHandle extends HTMLElement {
|
|
|
13069
13364
|
this.#hideColorTip();
|
|
13070
13365
|
this.removeEventListener("click", this.#handleSelect);
|
|
13071
13366
|
document.removeEventListener("pointerdown", this.#handleDeselect);
|
|
13367
|
+
document.removeEventListener("keydown", this.#handleKeyDown);
|
|
13072
13368
|
}
|
|
13073
13369
|
|
|
13074
13370
|
select() {
|
|
@@ -13098,6 +13394,15 @@ class FigHandle extends HTMLElement {
|
|
|
13098
13394
|
this.deselect();
|
|
13099
13395
|
};
|
|
13100
13396
|
|
|
13397
|
+
#handleKeyDown = (e) => {
|
|
13398
|
+
if (e.key !== "Enter") return;
|
|
13399
|
+
if (!this.hasAttribute("selected")) return;
|
|
13400
|
+
if (this.getAttribute("type") !== "color") return;
|
|
13401
|
+
if (this.#colorTip) return;
|
|
13402
|
+
e.preventDefault();
|
|
13403
|
+
this.#showColorTip();
|
|
13404
|
+
};
|
|
13405
|
+
|
|
13101
13406
|
attributeChangedCallback(name, _old, value) {
|
|
13102
13407
|
if (name === "color") {
|
|
13103
13408
|
if (!value || value === "false" || value === "true") {
|
package/package.json
CHANGED