@rogieking/figui3 6.24.5 → 6.26.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/figui3/SKILL.md +3 -1
- package/README.md +18 -7
- package/components.css +55 -25
- package/dist/components.css +1 -1
- package/dist/fig-lab.js +10 -10
- package/dist/fig.css +1 -1
- package/dist/fig.js +25 -25
- package/fig-lab.js +94 -59
- package/fig.js +206 -25
- package/package.json +1 -1
package/fig-lab.js
CHANGED
|
@@ -18,6 +18,20 @@ function figLabBooleanAttribute(element, name) {
|
|
|
18
18
|
return element.hasAttribute(name) && element.getAttribute(name) !== "false";
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function figLabColorEventAliases(color, alpha, opacity) {
|
|
22
|
+
const numericAlpha = Number(alpha);
|
|
23
|
+
const numericOpacity = Number(opacity);
|
|
24
|
+
const normalizedAlpha = Number.isFinite(numericAlpha)
|
|
25
|
+
? Math.max(0, Math.min(1, numericAlpha))
|
|
26
|
+
: Number.isFinite(numericOpacity)
|
|
27
|
+
? Math.max(0, Math.min(100, numericOpacity)) / 100
|
|
28
|
+
: 1;
|
|
29
|
+
const normalizedOpacity = Number.isFinite(numericOpacity)
|
|
30
|
+
? Math.max(0, Math.min(100, numericOpacity))
|
|
31
|
+
: Math.round(normalizedAlpha * 100);
|
|
32
|
+
return { color, alpha: normalizedAlpha, opacity: normalizedOpacity };
|
|
33
|
+
}
|
|
34
|
+
|
|
21
35
|
/* Unique IDs for lab components such as propskit-group. */
|
|
22
36
|
let figLabUniqueIdCounter = 0;
|
|
23
37
|
function figLabUniqueId(prefix = "fig-lab") {
|
|
@@ -1226,7 +1240,6 @@ class PropskitGroup extends HTMLElement {
|
|
|
1226
1240
|
].join(",");
|
|
1227
1241
|
|
|
1228
1242
|
#header = null;
|
|
1229
|
-
#disclosure = null;
|
|
1230
1243
|
#chevron = null;
|
|
1231
1244
|
#resetTooltip = null;
|
|
1232
1245
|
#defaults = new WeakMap();
|
|
@@ -1249,7 +1262,8 @@ class PropskitGroup extends HTMLElement {
|
|
|
1249
1262
|
cancelAnimationFrame(this.#dirtyFrame);
|
|
1250
1263
|
this.#dirtyFrame = 0;
|
|
1251
1264
|
}
|
|
1252
|
-
this.#
|
|
1265
|
+
this.#header?.removeEventListener("click", this.#handleToggle);
|
|
1266
|
+
this.#header?.removeEventListener("keydown", this.#handleHeaderKeyDown);
|
|
1253
1267
|
const resetBtn = this.#resetTooltip?.querySelector("fig-button");
|
|
1254
1268
|
resetBtn?.removeEventListener("click", this.#handleReset);
|
|
1255
1269
|
}
|
|
@@ -1257,7 +1271,7 @@ class PropskitGroup extends HTMLElement {
|
|
|
1257
1271
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
1258
1272
|
if (oldValue === newValue) return;
|
|
1259
1273
|
if (name === "open") {
|
|
1260
|
-
this.#
|
|
1274
|
+
this.#header?.setAttribute("aria-expanded", String(this.open));
|
|
1261
1275
|
return;
|
|
1262
1276
|
}
|
|
1263
1277
|
if (name === "show-reset") {
|
|
@@ -1280,7 +1294,7 @@ class PropskitGroup extends HTMLElement {
|
|
|
1280
1294
|
} else {
|
|
1281
1295
|
this.setAttribute("open", "false");
|
|
1282
1296
|
}
|
|
1283
|
-
this.#
|
|
1297
|
+
this.#header?.setAttribute("aria-expanded", String(!!value));
|
|
1284
1298
|
if (was !== !!value) {
|
|
1285
1299
|
this.dispatchEvent(
|
|
1286
1300
|
new CustomEvent("openchange", {
|
|
@@ -1360,6 +1374,14 @@ class PropskitGroup extends HTMLElement {
|
|
|
1360
1374
|
this.open = !this.open;
|
|
1361
1375
|
};
|
|
1362
1376
|
|
|
1377
|
+
#handleHeaderKeyDown = (e) => {
|
|
1378
|
+
if (this.#isResetTarget(e.target)) return;
|
|
1379
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
1380
|
+
e.preventDefault();
|
|
1381
|
+
e.stopPropagation();
|
|
1382
|
+
this.open = !this.open;
|
|
1383
|
+
};
|
|
1384
|
+
|
|
1363
1385
|
#handleReset = (e) => {
|
|
1364
1386
|
e.preventDefault();
|
|
1365
1387
|
e.stopPropagation();
|
|
@@ -1552,24 +1574,30 @@ class PropskitGroup extends HTMLElement {
|
|
|
1552
1574
|
this.prepend(this.#header);
|
|
1553
1575
|
}
|
|
1554
1576
|
|
|
1555
|
-
let
|
|
1556
|
-
|
|
1577
|
+
let h3 = this.#header.querySelector(":scope > h3");
|
|
1578
|
+
const legacyDisclosure = this.#header.querySelector(
|
|
1579
|
+
":scope > fig-button.propskit-group-disclosure",
|
|
1557
1580
|
);
|
|
1558
|
-
if (!
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
const existingHeading = this.#header.querySelector(":scope > h3");
|
|
1563
|
-
if (existingHeading) disclosure.appendChild(existingHeading);
|
|
1564
|
-
this.#header.prepend(disclosure);
|
|
1581
|
+
if (!h3 && legacyDisclosure) {
|
|
1582
|
+
h3 = legacyDisclosure.querySelector(":scope > h3");
|
|
1583
|
+
if (h3) this.#header.insertBefore(h3, legacyDisclosure);
|
|
1584
|
+
legacyDisclosure.remove();
|
|
1565
1585
|
}
|
|
1566
|
-
this.#disclosure = disclosure;
|
|
1567
|
-
|
|
1568
|
-
let h3 = disclosure.querySelector("h3");
|
|
1569
1586
|
if (!h3) {
|
|
1570
1587
|
h3 = document.createElement("h3");
|
|
1571
|
-
|
|
1588
|
+
this.#header.prepend(h3);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
const disclosure = h3.querySelector(
|
|
1592
|
+
":scope > button.propskit-group-disclosure",
|
|
1593
|
+
);
|
|
1594
|
+
if (disclosure) {
|
|
1595
|
+
while (disclosure.firstChild) {
|
|
1596
|
+
h3.insertBefore(disclosure.firstChild, disclosure);
|
|
1597
|
+
}
|
|
1598
|
+
disclosure.remove();
|
|
1572
1599
|
}
|
|
1600
|
+
|
|
1573
1601
|
if (!h3.id) h3.id = figLabUniqueId("propskit-group");
|
|
1574
1602
|
if (this.#header.dataset.generated) {
|
|
1575
1603
|
// Preserve chevron while updating the title text node.
|
|
@@ -1594,17 +1622,17 @@ class PropskitGroup extends HTMLElement {
|
|
|
1594
1622
|
}
|
|
1595
1623
|
this.#chevron = h3.querySelector(".propskit-group-chevron");
|
|
1596
1624
|
this.#syncResetButton();
|
|
1597
|
-
this.#header.
|
|
1598
|
-
this.#header.
|
|
1599
|
-
this.#header.
|
|
1600
|
-
this.#
|
|
1601
|
-
this.#
|
|
1602
|
-
this.#
|
|
1603
|
-
this.#
|
|
1625
|
+
this.#header.setAttribute("role", "button");
|
|
1626
|
+
this.#header.setAttribute("tabindex", "0");
|
|
1627
|
+
this.#header.setAttribute("aria-expanded", String(this.open));
|
|
1628
|
+
this.#header.removeEventListener("click", this.#handleToggle);
|
|
1629
|
+
this.#header.addEventListener("click", this.#handleToggle);
|
|
1630
|
+
this.#header.removeEventListener("keydown", this.#handleHeaderKeyDown);
|
|
1631
|
+
this.#header.addEventListener("keydown", this.#handleHeaderKeyDown);
|
|
1604
1632
|
|
|
1605
1633
|
if (!this.hasAttribute("open")) {
|
|
1606
1634
|
this.setAttribute("open", "false");
|
|
1607
|
-
this.#
|
|
1635
|
+
this.#header.setAttribute("aria-expanded", "false");
|
|
1608
1636
|
}
|
|
1609
1637
|
}
|
|
1610
1638
|
}
|
|
@@ -3229,18 +3257,29 @@ class FigCanvasControl extends HTMLElement {
|
|
|
3229
3257
|
this.#syncPointPointCursors();
|
|
3230
3258
|
}
|
|
3231
3259
|
|
|
3232
|
-
#emitInput() {
|
|
3260
|
+
#emitInput(detail = this.value) {
|
|
3233
3261
|
this.dispatchEvent(
|
|
3234
|
-
new CustomEvent("input", { bubbles: true, detail
|
|
3262
|
+
new CustomEvent("input", { bubbles: true, detail }),
|
|
3235
3263
|
);
|
|
3236
3264
|
}
|
|
3237
3265
|
|
|
3238
|
-
#emitChange() {
|
|
3266
|
+
#emitChange(detail = this.value) {
|
|
3239
3267
|
this.dispatchEvent(
|
|
3240
|
-
new CustomEvent("change", { bubbles: true, detail
|
|
3268
|
+
new CustomEvent("change", { bubbles: true, detail }),
|
|
3241
3269
|
);
|
|
3242
3270
|
}
|
|
3243
3271
|
|
|
3272
|
+
#colorEventDetail(detail) {
|
|
3273
|
+
return {
|
|
3274
|
+
...this.value,
|
|
3275
|
+
...figLabColorEventAliases(
|
|
3276
|
+
detail.color,
|
|
3277
|
+
detail.alpha,
|
|
3278
|
+
detail.opacity,
|
|
3279
|
+
),
|
|
3280
|
+
};
|
|
3281
|
+
}
|
|
3282
|
+
|
|
3244
3283
|
#syncValueAttribute() {
|
|
3245
3284
|
this.setAttribute("value", JSON.stringify(this.value));
|
|
3246
3285
|
}
|
|
@@ -3251,8 +3290,11 @@ class FigCanvasControl extends HTMLElement {
|
|
|
3251
3290
|
this.#pointHandle.addEventListener("input", (e) => {
|
|
3252
3291
|
e.stopPropagation();
|
|
3253
3292
|
if (e.detail?.color) {
|
|
3254
|
-
this.setAttribute(
|
|
3255
|
-
|
|
3293
|
+
this.setAttribute(
|
|
3294
|
+
"color",
|
|
3295
|
+
this.#pointHandle.getAttribute("color") || e.detail.color,
|
|
3296
|
+
);
|
|
3297
|
+
this.#emitInput(this.#colorEventDetail(e.detail));
|
|
3256
3298
|
return;
|
|
3257
3299
|
}
|
|
3258
3300
|
this.#isDragging = true;
|
|
@@ -3271,8 +3313,11 @@ class FigCanvasControl extends HTMLElement {
|
|
|
3271
3313
|
this.#pointHandle.addEventListener("change", (e) => {
|
|
3272
3314
|
e.stopPropagation();
|
|
3273
3315
|
if (e.detail?.color) {
|
|
3274
|
-
this.setAttribute(
|
|
3275
|
-
|
|
3316
|
+
this.setAttribute(
|
|
3317
|
+
"color",
|
|
3318
|
+
this.#pointHandle.getAttribute("color") || e.detail.color,
|
|
3319
|
+
);
|
|
3320
|
+
this.#emitChange(this.#colorEventDetail(e.detail));
|
|
3276
3321
|
return;
|
|
3277
3322
|
}
|
|
3278
3323
|
const px = e.detail?.px ?? this.#x / 100;
|
|
@@ -5272,32 +5317,22 @@ class FigReorder extends HTMLElement {
|
|
|
5272
5317
|
|
|
5273
5318
|
static #DRAG_THRESHOLD = 6;
|
|
5274
5319
|
|
|
5275
|
-
static #
|
|
5276
|
-
"
|
|
5277
|
-
"
|
|
5278
|
-
"
|
|
5279
|
-
"
|
|
5280
|
-
"
|
|
5281
|
-
"label",
|
|
5282
|
-
"summary",
|
|
5283
|
-
"fig-button",
|
|
5284
|
-
"fig-dropdown",
|
|
5320
|
+
static #NESTED_DRAG_SELECTORS = [
|
|
5321
|
+
'[draggable]:not([draggable="false"])',
|
|
5322
|
+
'img:not([draggable="false"])',
|
|
5323
|
+
'a[href]:not([draggable="false"])',
|
|
5324
|
+
'input[type="range"]',
|
|
5325
|
+
"fig-handle",
|
|
5285
5326
|
"fig-slider",
|
|
5286
5327
|
"fig-input-number",
|
|
5287
|
-
"fig-input-
|
|
5288
|
-
"
|
|
5328
|
+
"fig-input-gradient",
|
|
5329
|
+
"fig-easing-curve",
|
|
5330
|
+
"fig-input-angle",
|
|
5331
|
+
"fig-input-joystick",
|
|
5332
|
+
"fig-canvas-control",
|
|
5289
5333
|
"propskit-number",
|
|
5290
|
-
"propskit-select",
|
|
5291
5334
|
"propskit-slider",
|
|
5292
|
-
"propskit-
|
|
5293
|
-
"propskit-text",
|
|
5294
|
-
"fig-checkbox",
|
|
5295
|
-
"fig-switch",
|
|
5296
|
-
"fig-combo-input",
|
|
5297
|
-
"fig-segmented-control",
|
|
5298
|
-
"fig-input-color",
|
|
5299
|
-
"fig-input-fill",
|
|
5300
|
-
'[contenteditable="true"]',
|
|
5335
|
+
"propskit-oscillator",
|
|
5301
5336
|
];
|
|
5302
5337
|
|
|
5303
5338
|
#childObserver = null;
|
|
@@ -5458,7 +5493,7 @@ class FigReorder extends HTMLElement {
|
|
|
5458
5493
|
if (event.button !== 0) return;
|
|
5459
5494
|
if (
|
|
5460
5495
|
!this.#handleSelector &&
|
|
5461
|
-
this.#
|
|
5496
|
+
this.#isNestedDragTarget(event.target, child)
|
|
5462
5497
|
) {
|
|
5463
5498
|
return;
|
|
5464
5499
|
}
|
|
@@ -5567,11 +5602,11 @@ class FigReorder extends HTMLElement {
|
|
|
5567
5602
|
});
|
|
5568
5603
|
}
|
|
5569
5604
|
|
|
5570
|
-
#
|
|
5605
|
+
#isNestedDragTarget(target, child) {
|
|
5571
5606
|
let node = target;
|
|
5572
5607
|
while (node && node !== child) {
|
|
5573
5608
|
if (node instanceof Element) {
|
|
5574
|
-
for (const selector of FigReorder.#
|
|
5609
|
+
for (const selector of FigReorder.#NESTED_DRAG_SELECTORS) {
|
|
5575
5610
|
if (node.matches(selector)) return true;
|
|
5576
5611
|
}
|
|
5577
5612
|
}
|
|
@@ -5588,7 +5623,6 @@ class FigReorder extends HTMLElement {
|
|
|
5588
5623
|
|
|
5589
5624
|
#startPendingDrag(event, item, target) {
|
|
5590
5625
|
this.#cancelDrag();
|
|
5591
|
-
FigReorder.#setDocumentDragging(true);
|
|
5592
5626
|
|
|
5593
5627
|
const state = {
|
|
5594
5628
|
item,
|
|
@@ -5618,6 +5652,7 @@ class FigReorder extends HTMLElement {
|
|
|
5618
5652
|
event.preventDefault();
|
|
5619
5653
|
event.stopPropagation();
|
|
5620
5654
|
item.classList.add("dragging");
|
|
5655
|
+
FigReorder.#setDocumentDragging(true);
|
|
5621
5656
|
try {
|
|
5622
5657
|
target.setPointerCapture(state.pointerId);
|
|
5623
5658
|
} catch {}
|
package/fig.js
CHANGED
|
@@ -39,6 +39,20 @@ function figBooleanAttribute(element, name) {
|
|
|
39
39
|
return element.hasAttribute(name) && element.getAttribute(name) !== "false";
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function figColorEventAliases(color, alpha, opacity) {
|
|
43
|
+
const numericAlpha = Number(alpha);
|
|
44
|
+
const numericOpacity = Number(opacity);
|
|
45
|
+
const normalizedAlpha = Number.isFinite(numericAlpha)
|
|
46
|
+
? Math.max(0, Math.min(1, numericAlpha))
|
|
47
|
+
: Number.isFinite(numericOpacity)
|
|
48
|
+
? Math.max(0, Math.min(100, numericOpacity)) / 100
|
|
49
|
+
: 1;
|
|
50
|
+
const normalizedOpacity = Number.isFinite(numericOpacity)
|
|
51
|
+
? Math.max(0, Math.min(100, numericOpacity))
|
|
52
|
+
: Math.round(normalizedAlpha * 100);
|
|
53
|
+
return { color, alpha: normalizedAlpha, opacity: normalizedOpacity };
|
|
54
|
+
}
|
|
55
|
+
|
|
42
56
|
function figNormalizeTextOnlyInputSlots(host) {
|
|
43
57
|
host
|
|
44
58
|
.querySelectorAll(':scope > [slot="prepend"], :scope > [slot="append"]')
|
|
@@ -9115,7 +9129,7 @@ class FigInputColor extends HTMLElement {
|
|
|
9115
9129
|
new CustomEvent("input", {
|
|
9116
9130
|
bubbles: true,
|
|
9117
9131
|
cancelable: true,
|
|
9118
|
-
detail:
|
|
9132
|
+
detail: this.#eventDetail(),
|
|
9119
9133
|
}),
|
|
9120
9134
|
);
|
|
9121
9135
|
}
|
|
@@ -9124,11 +9138,24 @@ class FigInputColor extends HTMLElement {
|
|
|
9124
9138
|
new CustomEvent("change", {
|
|
9125
9139
|
bubbles: true,
|
|
9126
9140
|
cancelable: true,
|
|
9127
|
-
detail:
|
|
9141
|
+
detail: this.#eventDetail(),
|
|
9128
9142
|
}),
|
|
9129
9143
|
);
|
|
9130
9144
|
}
|
|
9131
9145
|
|
|
9146
|
+
#eventDetail() {
|
|
9147
|
+
return {
|
|
9148
|
+
value: this.value,
|
|
9149
|
+
hex: this.hex,
|
|
9150
|
+
rgba: this.rgba,
|
|
9151
|
+
...figColorEventAliases(
|
|
9152
|
+
this.hexOpaque,
|
|
9153
|
+
this.rgba?.a,
|
|
9154
|
+
Math.round((this.rgba?.a ?? 1) * 100),
|
|
9155
|
+
),
|
|
9156
|
+
};
|
|
9157
|
+
}
|
|
9158
|
+
|
|
9132
9159
|
static get observedAttributes() {
|
|
9133
9160
|
return [
|
|
9134
9161
|
"value",
|
|
@@ -11605,6 +11632,10 @@ class FigInputGradient extends HTMLElement {
|
|
|
11605
11632
|
this.#gradient.stops[idx].color = e.detail.color;
|
|
11606
11633
|
if (e.detail.opacity !== undefined) {
|
|
11607
11634
|
this.#gradient.stops[idx].opacity = e.detail.opacity;
|
|
11635
|
+
} else if (e.detail.alpha !== undefined) {
|
|
11636
|
+
this.#gradient.stops[idx].opacity = Math.round(
|
|
11637
|
+
e.detail.alpha * 100,
|
|
11638
|
+
);
|
|
11608
11639
|
}
|
|
11609
11640
|
handle.setAttribute(
|
|
11610
11641
|
"color",
|
|
@@ -13367,7 +13398,8 @@ figDefineElement("fig-video", FigVideo);
|
|
|
13367
13398
|
/**
|
|
13368
13399
|
* <fig-card> — Media card with optional link, selection chrome, and truncated label.
|
|
13369
13400
|
*
|
|
13370
|
-
* Composes a generated `fig-image`
|
|
13401
|
+
* Composes a generated `fig-image` when `src` is set. Without `src`, authored
|
|
13402
|
+
* children remain direct children and generated label content is appended.
|
|
13371
13403
|
* Selection is attribute-only (`selected`); apps own toggle/group logic.
|
|
13372
13404
|
* When `href` is set (and not disabled), content wraps in a real `<a>`.
|
|
13373
13405
|
*
|
|
@@ -13405,18 +13437,39 @@ class FigCard extends HTMLElement {
|
|
|
13405
13437
|
}
|
|
13406
13438
|
|
|
13407
13439
|
#linkEl = null;
|
|
13408
|
-
#mediaWrap = null;
|
|
13409
13440
|
#textWrap = null;
|
|
13410
13441
|
#imageEl = null;
|
|
13411
13442
|
#labelEl = null;
|
|
13412
13443
|
#sublabelEl = null;
|
|
13413
13444
|
#usesAuthoredMedia = false;
|
|
13445
|
+
#mediaObserver = new MutationObserver((mutations) => {
|
|
13446
|
+
const authoredMediaChanged = mutations.some((mutation) =>
|
|
13447
|
+
[...mutation.addedNodes, ...mutation.removedNodes].some(
|
|
13448
|
+
(node) =>
|
|
13449
|
+
node instanceof Element &&
|
|
13450
|
+
(node.matches(
|
|
13451
|
+
"fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated])",
|
|
13452
|
+
) ||
|
|
13453
|
+
node.querySelector(
|
|
13454
|
+
"fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated])",
|
|
13455
|
+
)),
|
|
13456
|
+
),
|
|
13457
|
+
);
|
|
13458
|
+
if (!authoredMediaChanged || !this.isConnected) return;
|
|
13459
|
+
this.#ensureStructure();
|
|
13460
|
+
this.#sync();
|
|
13461
|
+
});
|
|
13414
13462
|
|
|
13415
13463
|
connectedCallback() {
|
|
13464
|
+
this.#mediaObserver.observe(this, { childList: true, subtree: true });
|
|
13416
13465
|
this.#ensureStructure();
|
|
13417
13466
|
this.#sync();
|
|
13418
13467
|
}
|
|
13419
13468
|
|
|
13469
|
+
disconnectedCallback() {
|
|
13470
|
+
this.#mediaObserver.disconnect();
|
|
13471
|
+
}
|
|
13472
|
+
|
|
13420
13473
|
attributeChangedCallback() {
|
|
13421
13474
|
if (!this.isConnected) return;
|
|
13422
13475
|
this.#ensureStructure();
|
|
@@ -13441,13 +13494,27 @@ class FigCard extends HTMLElement {
|
|
|
13441
13494
|
return raw === "2" ? "2" : "1";
|
|
13442
13495
|
}
|
|
13443
13496
|
|
|
13497
|
+
#usesGeneratedMedia() {
|
|
13498
|
+
return Boolean(this.getAttribute("src"));
|
|
13499
|
+
}
|
|
13500
|
+
|
|
13444
13501
|
#findAuthoredMedia() {
|
|
13445
13502
|
return this.querySelector(
|
|
13446
|
-
":scope > fig-image:not([data-generated]), :scope > fig-media:not([data-generated]), :scope > fig-preview:not([data-generated]), :scope > .fig-card-link > .fig-card-media > fig-image:not([data-generated]), :scope > .fig-card-link > .fig-card-media > fig-media:not([data-generated]), :scope > .fig-card-link > .fig-card-media > fig-preview:not([data-generated])",
|
|
13503
|
+
":scope > fig-image:not([data-generated]), :scope > fig-media:not([data-generated]), :scope > fig-preview:not([data-generated]), :scope > .fig-card-link > fig-image:not([data-generated]), :scope > .fig-card-link > fig-media:not([data-generated]), :scope > .fig-card-link > fig-preview:not([data-generated]), :scope > .fig-card-link > .fig-card-media > fig-image:not([data-generated]), :scope > .fig-card-link > .fig-card-media > fig-media:not([data-generated]), :scope > .fig-card-link > .fig-card-media > fig-preview:not([data-generated])",
|
|
13447
13504
|
);
|
|
13448
13505
|
}
|
|
13449
13506
|
|
|
13450
13507
|
#ensureStructure() {
|
|
13508
|
+
if (!this.#usesGeneratedMedia()) {
|
|
13509
|
+
this.#ensureManualStructure();
|
|
13510
|
+
return;
|
|
13511
|
+
}
|
|
13512
|
+
|
|
13513
|
+
this.querySelectorAll(":scope > .fig-card-text[data-generated]").forEach(
|
|
13514
|
+
(element) => element.remove(),
|
|
13515
|
+
);
|
|
13516
|
+
if (this.#textWrap?.parentElement === this) this.#textWrap = null;
|
|
13517
|
+
|
|
13451
13518
|
const authored = this.#findAuthoredMedia();
|
|
13452
13519
|
this.#usesAuthoredMedia = Boolean(authored);
|
|
13453
13520
|
|
|
@@ -13468,29 +13535,30 @@ class FigCard extends HTMLElement {
|
|
|
13468
13535
|
this.#linkEl = next;
|
|
13469
13536
|
}
|
|
13470
13537
|
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
this.#linkEl.
|
|
13538
|
+
const legacyMediaWrap = this.#linkEl.querySelector(
|
|
13539
|
+
":scope > .fig-card-media",
|
|
13540
|
+
);
|
|
13541
|
+
if (legacyMediaWrap) {
|
|
13542
|
+
while (legacyMediaWrap.firstChild) {
|
|
13543
|
+
this.#linkEl.insertBefore(legacyMediaWrap.firstChild, legacyMediaWrap);
|
|
13477
13544
|
}
|
|
13545
|
+
legacyMediaWrap.remove();
|
|
13478
13546
|
}
|
|
13479
13547
|
|
|
13480
|
-
if (authored && authored.parentElement !== this.#
|
|
13481
|
-
this.#
|
|
13482
|
-
.querySelectorAll("[data-generated]")
|
|
13548
|
+
if (authored && authored.parentElement !== this.#linkEl) {
|
|
13549
|
+
this.#linkEl
|
|
13550
|
+
.querySelectorAll(":scope > [data-generated]:not(.fig-card-text)")
|
|
13483
13551
|
.forEach((el) => el.remove());
|
|
13484
|
-
this.#
|
|
13552
|
+
this.#linkEl.prepend(authored);
|
|
13485
13553
|
this.#imageEl = null;
|
|
13486
13554
|
}
|
|
13487
13555
|
|
|
13488
13556
|
if (!this.#usesAuthoredMedia) {
|
|
13489
13557
|
this.#imageEl =
|
|
13490
|
-
this.#
|
|
13558
|
+
this.#linkEl.querySelector(":scope > fig-image[data-generated]") ||
|
|
13491
13559
|
null;
|
|
13492
13560
|
if (!this.#imageEl) {
|
|
13493
|
-
this.#
|
|
13561
|
+
this.#linkEl
|
|
13494
13562
|
.querySelectorAll(
|
|
13495
13563
|
":scope > fig-image, :scope > fig-media, :scope > fig-preview",
|
|
13496
13564
|
)
|
|
@@ -13501,12 +13569,26 @@ class FigCard extends HTMLElement {
|
|
|
13501
13569
|
this.#imageEl.setAttribute("data-generated", "");
|
|
13502
13570
|
this.#imageEl.setAttribute("full", "");
|
|
13503
13571
|
this.#imageEl.setAttribute("size", "auto");
|
|
13504
|
-
this.#
|
|
13572
|
+
this.#linkEl.prepend(this.#imageEl);
|
|
13505
13573
|
}
|
|
13506
13574
|
}
|
|
13507
13575
|
|
|
13508
13576
|
if (!this.#textWrap || !this.#textWrap.isConnected) {
|
|
13509
13577
|
this.#textWrap = this.#linkEl.querySelector(":scope > .fig-card-text");
|
|
13578
|
+
if (this.#textWrap?.tagName.toLowerCase() !== "div") {
|
|
13579
|
+
const text = document.createElement("div");
|
|
13580
|
+
text.className = "fig-card-text";
|
|
13581
|
+
text.setAttribute("data-generated", "");
|
|
13582
|
+
if (this.#textWrap) {
|
|
13583
|
+
while (this.#textWrap.firstChild) {
|
|
13584
|
+
text.appendChild(this.#textWrap.firstChild);
|
|
13585
|
+
}
|
|
13586
|
+
this.#textWrap.replaceWith(text);
|
|
13587
|
+
} else {
|
|
13588
|
+
this.#linkEl.appendChild(text);
|
|
13589
|
+
}
|
|
13590
|
+
this.#textWrap = text;
|
|
13591
|
+
}
|
|
13510
13592
|
if (!this.#textWrap) {
|
|
13511
13593
|
this.#textWrap = document.createElement("div");
|
|
13512
13594
|
this.#textWrap.className = "fig-card-text";
|
|
@@ -13542,7 +13624,7 @@ class FigCard extends HTMLElement {
|
|
|
13542
13624
|
":scope > .fig-card-sublabel[data-generated]",
|
|
13543
13625
|
) || null;
|
|
13544
13626
|
if (!this.#sublabelEl) {
|
|
13545
|
-
this.#sublabelEl = document.createElement("
|
|
13627
|
+
this.#sublabelEl = document.createElement("label");
|
|
13546
13628
|
this.#sublabelEl.className = "fig-card-sublabel";
|
|
13547
13629
|
this.#sublabelEl.setAttribute("data-generated", "");
|
|
13548
13630
|
}
|
|
@@ -13551,7 +13633,49 @@ class FigCard extends HTMLElement {
|
|
|
13551
13633
|
}
|
|
13552
13634
|
}
|
|
13553
13635
|
|
|
13636
|
+
#ensureManualStructure() {
|
|
13637
|
+
const staleLink =
|
|
13638
|
+
this.#linkEl || this.querySelector(":scope > .fig-card-link");
|
|
13639
|
+
if (staleLink) {
|
|
13640
|
+
staleLink
|
|
13641
|
+
.querySelectorAll(
|
|
13642
|
+
"fig-image:not([data-generated]), fig-media:not([data-generated]), fig-preview:not([data-generated])",
|
|
13643
|
+
)
|
|
13644
|
+
.forEach((media) => this.insertBefore(media, staleLink));
|
|
13645
|
+
staleLink.remove();
|
|
13646
|
+
}
|
|
13647
|
+
this.querySelectorAll(":scope > [data-generated]").forEach((element) =>
|
|
13648
|
+
element.remove(),
|
|
13649
|
+
);
|
|
13650
|
+
|
|
13651
|
+
this.#linkEl = null;
|
|
13652
|
+
this.#imageEl = null;
|
|
13653
|
+
this.#usesAuthoredMedia = true;
|
|
13654
|
+
|
|
13655
|
+
this.#textWrap = document.createElement("div");
|
|
13656
|
+
this.#textWrap.className = "fig-card-text";
|
|
13657
|
+
this.#textWrap.setAttribute("data-generated", "");
|
|
13658
|
+
this.#labelEl = document.createElement("label");
|
|
13659
|
+
this.#labelEl.className = "fig-card-label";
|
|
13660
|
+
this.#labelEl.setAttribute("data-generated", "");
|
|
13661
|
+
this.#textWrap.appendChild(this.#labelEl);
|
|
13662
|
+
|
|
13663
|
+
const sublabel = this.#sublabelText();
|
|
13664
|
+
this.#sublabelEl = null;
|
|
13665
|
+
if (sublabel) {
|
|
13666
|
+
this.#sublabelEl = document.createElement("label");
|
|
13667
|
+
this.#sublabelEl.className = "fig-card-sublabel";
|
|
13668
|
+
this.#sublabelEl.setAttribute("data-generated", "");
|
|
13669
|
+
this.#textWrap.appendChild(this.#sublabelEl);
|
|
13670
|
+
}
|
|
13671
|
+
this.appendChild(this.#textWrap);
|
|
13672
|
+
}
|
|
13673
|
+
|
|
13554
13674
|
#sync() {
|
|
13675
|
+
if (!this.#usesGeneratedMedia()) {
|
|
13676
|
+
this.#syncManual();
|
|
13677
|
+
return;
|
|
13678
|
+
}
|
|
13555
13679
|
if (!this.#linkEl) return;
|
|
13556
13680
|
|
|
13557
13681
|
const disabled = figBooleanAttribute(this, "disabled");
|
|
@@ -13634,6 +13758,29 @@ class FigCard extends HTMLElement {
|
|
|
13634
13758
|
this.#textWrap.hidden = !label && !sublabel;
|
|
13635
13759
|
}
|
|
13636
13760
|
}
|
|
13761
|
+
|
|
13762
|
+
#syncManual() {
|
|
13763
|
+
const disabled = figBooleanAttribute(this, "disabled");
|
|
13764
|
+
const label = this.#labelText();
|
|
13765
|
+
const sublabel = this.#sublabelText();
|
|
13766
|
+
|
|
13767
|
+
this.style.setProperty(
|
|
13768
|
+
"--fig-card-label-line-clamp",
|
|
13769
|
+
this.#lineClamp(),
|
|
13770
|
+
);
|
|
13771
|
+
this.setAttribute("role", "group");
|
|
13772
|
+
const ariaLabel = [label, sublabel].filter(Boolean).join(", ");
|
|
13773
|
+
if (ariaLabel) this.setAttribute("aria-label", ariaLabel);
|
|
13774
|
+
else this.removeAttribute("aria-label");
|
|
13775
|
+
if (disabled) this.setAttribute("aria-disabled", "true");
|
|
13776
|
+
else this.removeAttribute("aria-disabled");
|
|
13777
|
+
|
|
13778
|
+
if (this.#labelEl) {
|
|
13779
|
+
this.#labelEl.textContent = label;
|
|
13780
|
+
this.#labelEl.hidden = !label;
|
|
13781
|
+
}
|
|
13782
|
+
if (this.#sublabelEl) this.#sublabelEl.textContent = sublabel;
|
|
13783
|
+
}
|
|
13637
13784
|
}
|
|
13638
13785
|
figDefineElement("fig-card", FigCard);
|
|
13639
13786
|
|
|
@@ -17637,6 +17784,14 @@ class FigColorTip extends HTMLElement {
|
|
|
17637
17784
|
eventDetail.opacity = Math.round(detail.alpha * 100);
|
|
17638
17785
|
}
|
|
17639
17786
|
}
|
|
17787
|
+
Object.assign(
|
|
17788
|
+
eventDetail,
|
|
17789
|
+
figColorEventAliases(
|
|
17790
|
+
eventDetail.color,
|
|
17791
|
+
this.#alphaEnabled ? detail?.alpha : 1,
|
|
17792
|
+
eventDetail.opacity,
|
|
17793
|
+
),
|
|
17794
|
+
);
|
|
17640
17795
|
|
|
17641
17796
|
this.dispatchEvent(
|
|
17642
17797
|
new CustomEvent(type, {
|
|
@@ -19183,7 +19338,11 @@ class FigHandle extends HTMLElement {
|
|
|
19183
19338
|
: detail.alpha !== undefined
|
|
19184
19339
|
? Math.round(detail.alpha * 100)
|
|
19185
19340
|
: undefined;
|
|
19186
|
-
return {
|
|
19341
|
+
return {
|
|
19342
|
+
color: detail.color,
|
|
19343
|
+
opacity,
|
|
19344
|
+
...figColorEventAliases(detail.color, detail.alpha, opacity),
|
|
19345
|
+
};
|
|
19187
19346
|
}
|
|
19188
19347
|
|
|
19189
19348
|
#handleDirectColorPickerInput = (e) => {
|
|
@@ -19214,7 +19373,11 @@ class FigHandle extends HTMLElement {
|
|
|
19214
19373
|
|
|
19215
19374
|
#detailFromNativeColor(value) {
|
|
19216
19375
|
const { opacity } = this.#normalizeColorForPicker();
|
|
19217
|
-
|
|
19376
|
+
const detail = opacity < 100 ? { color: value, opacity } : { color: value };
|
|
19377
|
+
return {
|
|
19378
|
+
...detail,
|
|
19379
|
+
...figColorEventAliases(value, undefined, opacity),
|
|
19380
|
+
};
|
|
19218
19381
|
}
|
|
19219
19382
|
|
|
19220
19383
|
#handleNativeColorInput = (e) => {
|
|
@@ -19249,14 +19412,23 @@ class FigHandle extends HTMLElement {
|
|
|
19249
19412
|
#handleColorTipInput = (e) => {
|
|
19250
19413
|
e.stopPropagation();
|
|
19251
19414
|
if (e.detail?.color) {
|
|
19415
|
+
const detail = {
|
|
19416
|
+
color: e.detail.color,
|
|
19417
|
+
opacity: e.detail.opacity,
|
|
19418
|
+
...figColorEventAliases(
|
|
19419
|
+
e.detail.color,
|
|
19420
|
+
e.detail.alpha,
|
|
19421
|
+
e.detail.opacity,
|
|
19422
|
+
),
|
|
19423
|
+
};
|
|
19252
19424
|
this.setAttribute(
|
|
19253
19425
|
"color",
|
|
19254
|
-
this.#colorWithOpacity(
|
|
19426
|
+
this.#colorWithOpacity(detail.color, detail.opacity),
|
|
19255
19427
|
);
|
|
19256
19428
|
this.dispatchEvent(
|
|
19257
19429
|
new CustomEvent("input", {
|
|
19258
19430
|
bubbles: true,
|
|
19259
|
-
detail
|
|
19431
|
+
detail,
|
|
19260
19432
|
}),
|
|
19261
19433
|
);
|
|
19262
19434
|
}
|
|
@@ -19265,14 +19437,23 @@ class FigHandle extends HTMLElement {
|
|
|
19265
19437
|
#handleColorTipChange = (e) => {
|
|
19266
19438
|
e.stopPropagation();
|
|
19267
19439
|
if (e.detail?.color) {
|
|
19440
|
+
const detail = {
|
|
19441
|
+
color: e.detail.color,
|
|
19442
|
+
opacity: e.detail.opacity,
|
|
19443
|
+
...figColorEventAliases(
|
|
19444
|
+
e.detail.color,
|
|
19445
|
+
e.detail.alpha,
|
|
19446
|
+
e.detail.opacity,
|
|
19447
|
+
),
|
|
19448
|
+
};
|
|
19268
19449
|
this.setAttribute(
|
|
19269
19450
|
"color",
|
|
19270
|
-
this.#colorWithOpacity(
|
|
19451
|
+
this.#colorWithOpacity(detail.color, detail.opacity),
|
|
19271
19452
|
);
|
|
19272
19453
|
this.dispatchEvent(
|
|
19273
19454
|
new CustomEvent("change", {
|
|
19274
19455
|
bubbles: true,
|
|
19275
|
-
detail
|
|
19456
|
+
detail,
|
|
19276
19457
|
}),
|
|
19277
19458
|
);
|
|
19278
19459
|
}
|
package/package.json
CHANGED