@rogieking/figui3 6.8.6 → 6.8.7
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 +42 -22
- package/dist/components.css +1 -1
- package/dist/fig.css +1 -1
- package/dist/fig.js +18 -28
- package/fig.js +279 -101
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -35,6 +35,65 @@ function figNextFrame(host, callback) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function figNormalizeTextOnlyInputSlots(host) {
|
|
39
|
+
host
|
|
40
|
+
.querySelectorAll(':scope > [slot="prepend"], :scope > [slot="append"]')
|
|
41
|
+
.forEach((node) => {
|
|
42
|
+
if (node.children.length > 0) {
|
|
43
|
+
figClearInputSlotTooltip(node);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const text = node.textContent.trim();
|
|
47
|
+
if (!text) {
|
|
48
|
+
figClearInputSlotTooltip(node);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const previousFullText = node.dataset.figInputSlotFullText || "";
|
|
52
|
+
const previousShortText = previousFullText
|
|
53
|
+
? Array.from(previousFullText)[0]?.toUpperCase()
|
|
54
|
+
: "";
|
|
55
|
+
const fullText = text === previousShortText ? previousFullText : text;
|
|
56
|
+
const first = Array.from(text)[0];
|
|
57
|
+
const normalized = first.toUpperCase();
|
|
58
|
+
if (node.textContent !== normalized) node.textContent = normalized;
|
|
59
|
+
if (fullText && fullText !== normalized) {
|
|
60
|
+
node.dataset.figInputSlotFullText = fullText;
|
|
61
|
+
node.setAttribute("aria-label", fullText);
|
|
62
|
+
figBindInputSlotTooltip(node);
|
|
63
|
+
} else {
|
|
64
|
+
figClearInputSlotTooltip(node);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function figBindInputSlotTooltip(node) {
|
|
70
|
+
if (node.dataset.figInputSlotTooltipBound === "true") return;
|
|
71
|
+
node.dataset.figInputSlotTooltipBound = "true";
|
|
72
|
+
node.addEventListener("pointerenter", figShowInputSlotTooltip);
|
|
73
|
+
node.addEventListener("pointerleave", figHideInputSlotTooltip);
|
|
74
|
+
node.addEventListener("focus", figShowInputSlotTooltip);
|
|
75
|
+
node.addEventListener("blur", figHideInputSlotTooltip);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function figClearInputSlotTooltip(node) {
|
|
79
|
+
figHideInputSlotTooltip({ currentTarget: node });
|
|
80
|
+
delete node.dataset.figInputSlotFullText;
|
|
81
|
+
node.removeAttribute("aria-label");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function figShowInputSlotTooltip(event) {
|
|
85
|
+
const node = event.currentTarget;
|
|
86
|
+
const text = node?.dataset?.figInputSlotFullText;
|
|
87
|
+
if (!node || !text) return;
|
|
88
|
+
FigTooltip.show(node, text);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function figHideInputSlotTooltip(event) {
|
|
92
|
+
const node = event.currentTarget;
|
|
93
|
+
if (!node) return;
|
|
94
|
+
FigTooltip.hide(node);
|
|
95
|
+
}
|
|
96
|
+
|
|
38
97
|
function createFigOverflowButtons({
|
|
39
98
|
owner,
|
|
40
99
|
onStart,
|
|
@@ -751,6 +810,7 @@ class FigTooltip extends HTMLElement {
|
|
|
751
810
|
static #warmupWindow = 1000;
|
|
752
811
|
static #hoverOpen = null;
|
|
753
812
|
static #documentExitListenersReady = false;
|
|
813
|
+
static #programmaticAnchors = new Set();
|
|
754
814
|
|
|
755
815
|
#boundHideOnChromeOpen;
|
|
756
816
|
#boundHidePopupOutsideClick;
|
|
@@ -958,6 +1018,7 @@ class FigTooltip extends HTMLElement {
|
|
|
958
1018
|
|
|
959
1019
|
destroy() {
|
|
960
1020
|
if (this.popup) {
|
|
1021
|
+
this.#removeDescribedBy(this.popup.id);
|
|
961
1022
|
this.popup.hidePopup?.();
|
|
962
1023
|
this.popup.remove();
|
|
963
1024
|
this.popup = null;
|
|
@@ -970,6 +1031,18 @@ class FigTooltip extends HTMLElement {
|
|
|
970
1031
|
);
|
|
971
1032
|
}
|
|
972
1033
|
}
|
|
1034
|
+
#removeDescribedBy(id) {
|
|
1035
|
+
const trigger = this.firstElementChild;
|
|
1036
|
+
if (!trigger || !id) return;
|
|
1037
|
+
const value = trigger.getAttribute("aria-describedby");
|
|
1038
|
+
if (!value) return;
|
|
1039
|
+
const next = value
|
|
1040
|
+
.split(/\s+/)
|
|
1041
|
+
.filter((token) => token && token !== id)
|
|
1042
|
+
.join(" ");
|
|
1043
|
+
if (next) trigger.setAttribute("aria-describedby", next);
|
|
1044
|
+
else trigger.removeAttribute("aria-describedby");
|
|
1045
|
+
}
|
|
973
1046
|
isTouchDevice() {
|
|
974
1047
|
return (
|
|
975
1048
|
"ontouchstart" in window ||
|
|
@@ -1206,6 +1279,9 @@ class FigTooltip extends HTMLElement {
|
|
|
1206
1279
|
const handlePointerLeftDocument = () => {
|
|
1207
1280
|
FigTooltip.#dismissHoverTooltipsOnDocumentExit();
|
|
1208
1281
|
};
|
|
1282
|
+
const handleViewportChange = () => {
|
|
1283
|
+
FigTooltip.#dismissTooltipsOnViewportChange();
|
|
1284
|
+
};
|
|
1209
1285
|
|
|
1210
1286
|
document.documentElement.addEventListener(
|
|
1211
1287
|
"mouseleave",
|
|
@@ -1215,6 +1291,17 @@ class FigTooltip extends HTMLElement {
|
|
|
1215
1291
|
if (event.relatedTarget) return;
|
|
1216
1292
|
handlePointerLeftDocument();
|
|
1217
1293
|
});
|
|
1294
|
+
document.addEventListener("scroll", handleViewportChange, {
|
|
1295
|
+
capture: true,
|
|
1296
|
+
passive: true,
|
|
1297
|
+
});
|
|
1298
|
+
window.addEventListener("scroll", handleViewportChange, { passive: true });
|
|
1299
|
+
window.visualViewport?.addEventListener("scroll", handleViewportChange, {
|
|
1300
|
+
passive: true,
|
|
1301
|
+
});
|
|
1302
|
+
window.visualViewport?.addEventListener("resize", handleViewportChange, {
|
|
1303
|
+
passive: true,
|
|
1304
|
+
});
|
|
1218
1305
|
|
|
1219
1306
|
// Same-origin embed: leaving the iframe element (e.g. into a parent dialog).
|
|
1220
1307
|
try {
|
|
@@ -1235,15 +1322,26 @@ class FigTooltip extends HTMLElement {
|
|
|
1235
1322
|
for (const node of document.querySelectorAll("fig-tooltip")) {
|
|
1236
1323
|
if (!(node instanceof FigTooltip)) continue;
|
|
1237
1324
|
if (node.action !== "hover") continue;
|
|
1238
|
-
if (node
|
|
1239
|
-
continue;
|
|
1325
|
+
if (node.#showPersisted) continue;
|
|
1240
1326
|
if (node.isOpen || node.timeout) node.hidePopup();
|
|
1241
1327
|
}
|
|
1242
1328
|
}
|
|
1243
1329
|
|
|
1244
1330
|
static #programmatic = new WeakMap();
|
|
1245
1331
|
|
|
1332
|
+
static #dismissTooltipsOnViewportChange() {
|
|
1333
|
+
for (const node of document.querySelectorAll("fig-tooltip")) {
|
|
1334
|
+
if (!(node instanceof FigTooltip)) continue;
|
|
1335
|
+
if (node.#showPersisted) continue;
|
|
1336
|
+
if (node.isOpen || node.timeout) node.hidePopup();
|
|
1337
|
+
}
|
|
1338
|
+
for (const anchor of Array.from(FigTooltip.#programmaticAnchors)) {
|
|
1339
|
+
FigTooltip.hide(anchor);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1246
1343
|
static show(anchor, text, options = {}) {
|
|
1344
|
+
FigTooltip.#ensureDocumentExitListeners();
|
|
1247
1345
|
FigTooltip.hide(anchor);
|
|
1248
1346
|
const delay = options.delay ?? 500;
|
|
1249
1347
|
const warm =
|
|
@@ -1252,6 +1350,7 @@ class FigTooltip extends HTMLElement {
|
|
|
1252
1350
|
|
|
1253
1351
|
const state = { timeout: null, popup: null };
|
|
1254
1352
|
FigTooltip.#programmatic.set(anchor, state);
|
|
1353
|
+
FigTooltip.#programmaticAnchors.add(anchor);
|
|
1255
1354
|
|
|
1256
1355
|
state.timeout = setTimeout(() => {
|
|
1257
1356
|
const supportsPopover =
|
|
@@ -1292,8 +1391,12 @@ class FigTooltip extends HTMLElement {
|
|
|
1292
1391
|
const state = FigTooltip.#programmatic.get(anchor);
|
|
1293
1392
|
if (!state) return;
|
|
1294
1393
|
clearTimeout(state.timeout);
|
|
1295
|
-
if (state.popup)
|
|
1394
|
+
if (state.popup) {
|
|
1395
|
+
state.popup.remove();
|
|
1396
|
+
FigTooltip.#lastHiddenAt = Date.now();
|
|
1397
|
+
}
|
|
1296
1398
|
FigTooltip.#programmatic.delete(anchor);
|
|
1399
|
+
FigTooltip.#programmaticAnchors.delete(anchor);
|
|
1297
1400
|
}
|
|
1298
1401
|
}
|
|
1299
1402
|
|
|
@@ -5424,6 +5527,9 @@ class FigInputText extends HTMLElement {
|
|
|
5424
5527
|
#boundInputChange;
|
|
5425
5528
|
#boundNativeInput;
|
|
5426
5529
|
#boundFocusControl;
|
|
5530
|
+
#boundAdornmentClick;
|
|
5531
|
+
#mutationObserver = null;
|
|
5532
|
+
#syncRaf = 0;
|
|
5427
5533
|
#a11yAttributes = [
|
|
5428
5534
|
"aria-label",
|
|
5429
5535
|
"aria-labelledby",
|
|
@@ -5447,6 +5553,7 @@ class FigInputText extends HTMLElement {
|
|
|
5447
5553
|
this.#syncSearchClearVisibility();
|
|
5448
5554
|
};
|
|
5449
5555
|
this.#boundFocusControl = this.focus.bind(this);
|
|
5556
|
+
this.#boundAdornmentClick = this.#handleAdornmentClick.bind(this);
|
|
5450
5557
|
}
|
|
5451
5558
|
|
|
5452
5559
|
connectedCallback() {
|
|
@@ -5482,6 +5589,8 @@ class FigInputText extends HTMLElement {
|
|
|
5482
5589
|
this.#syncSearchClear();
|
|
5483
5590
|
this.#syncSearchClearVisibility();
|
|
5484
5591
|
this.#syncPasswordToggle();
|
|
5592
|
+
figNormalizeTextOnlyInputSlots(this);
|
|
5593
|
+
this.#startObserver();
|
|
5485
5594
|
|
|
5486
5595
|
if (this.type === "number") {
|
|
5487
5596
|
if (this.getAttribute("min")) {
|
|
@@ -5495,6 +5604,8 @@ class FigInputText extends HTMLElement {
|
|
|
5495
5604
|
}
|
|
5496
5605
|
this.addEventListener("pointerdown", this.#boundMouseDown);
|
|
5497
5606
|
}
|
|
5607
|
+
this.removeEventListener("click", this.#boundAdornmentClick);
|
|
5608
|
+
this.addEventListener("click", this.#boundAdornmentClick);
|
|
5498
5609
|
this.input.removeEventListener("change", this.#boundInputChange);
|
|
5499
5610
|
this.input.addEventListener("change", this.#boundInputChange);
|
|
5500
5611
|
this.input.removeEventListener("input", this.#boundNativeInput);
|
|
@@ -5506,10 +5617,17 @@ class FigInputText extends HTMLElement {
|
|
|
5506
5617
|
this.input.removeEventListener("change", this.#boundInputChange);
|
|
5507
5618
|
this.input.removeEventListener("input", this.#boundNativeInput);
|
|
5508
5619
|
}
|
|
5620
|
+
this.removeEventListener("click", this.#boundAdornmentClick);
|
|
5509
5621
|
this.removeEventListener("pointerdown", this.#boundMouseDown);
|
|
5510
5622
|
window.removeEventListener("pointermove", this.#boundMouseMove);
|
|
5511
5623
|
window.removeEventListener("pointerup", this.#boundMouseUp);
|
|
5512
5624
|
window.removeEventListener("blur", this.#boundWindowBlur);
|
|
5625
|
+
this.#mutationObserver?.disconnect();
|
|
5626
|
+
this.#mutationObserver = null;
|
|
5627
|
+
if (this.#syncRaf) {
|
|
5628
|
+
cancelAnimationFrame(this.#syncRaf);
|
|
5629
|
+
this.#syncRaf = 0;
|
|
5630
|
+
}
|
|
5513
5631
|
}
|
|
5514
5632
|
|
|
5515
5633
|
focus() {
|
|
@@ -5523,37 +5641,61 @@ class FigInputText extends HTMLElement {
|
|
|
5523
5641
|
? existing.tagName === "TEXTAREA"
|
|
5524
5642
|
: existing.tagName === "INPUT";
|
|
5525
5643
|
if (matches) return existing;
|
|
5644
|
+
existing.remove();
|
|
5526
5645
|
}
|
|
5527
5646
|
|
|
5528
|
-
let
|
|
5529
|
-
type="${this.type}"
|
|
5530
|
-
${this.name ? `name="${this.name}"` : ""}
|
|
5531
|
-
placeholder="${this.placeholder}"
|
|
5532
|
-
value="${
|
|
5533
|
-
this.type === "number" ? this.#transformNumber(this.value) : this.value
|
|
5534
|
-
}" />`;
|
|
5647
|
+
let control;
|
|
5535
5648
|
if (wantsTextarea) {
|
|
5536
|
-
|
|
5537
|
-
|
|
5649
|
+
control = document.createElement("textarea");
|
|
5650
|
+
control.value = this.value;
|
|
5651
|
+
} else {
|
|
5652
|
+
control = document.createElement("input");
|
|
5653
|
+
control.type = this.type;
|
|
5654
|
+
control.value =
|
|
5655
|
+
this.type === "number" ? this.#transformNumber(this.value) : this.value;
|
|
5538
5656
|
}
|
|
5657
|
+
control.setAttribute("data-generated", "input-control");
|
|
5658
|
+
if (this.name) control.name = this.name;
|
|
5659
|
+
control.placeholder = this.placeholder;
|
|
5660
|
+
this.insertBefore(control, this.querySelector('[slot="append"]'));
|
|
5539
5661
|
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5662
|
+
return control;
|
|
5663
|
+
}
|
|
5664
|
+
#handleAdornmentClick(event) {
|
|
5665
|
+
const adornment = event.target?.closest?.("[slot]");
|
|
5666
|
+
if (!adornment || adornment.parentElement !== this) return;
|
|
5667
|
+
this.focus();
|
|
5668
|
+
}
|
|
5669
|
+
#startObserver() {
|
|
5670
|
+
this.#mutationObserver?.disconnect();
|
|
5671
|
+
this.#mutationObserver = new MutationObserver(() => this.#scheduleLightDomSync());
|
|
5672
|
+
this.#mutationObserver.observe(this, {
|
|
5673
|
+
childList: true,
|
|
5674
|
+
characterData: true,
|
|
5675
|
+
subtree: true,
|
|
5676
|
+
});
|
|
5677
|
+
}
|
|
5678
|
+
#scheduleLightDomSync() {
|
|
5679
|
+
if (this.#syncRaf) return;
|
|
5680
|
+
this.#syncRaf = requestAnimationFrame(() => {
|
|
5681
|
+
this.#syncRaf = 0;
|
|
5682
|
+
if (!this.isConnected) return;
|
|
5683
|
+
this.#syncLightDom();
|
|
5684
|
+
});
|
|
5685
|
+
}
|
|
5686
|
+
#syncLightDom() {
|
|
5687
|
+
if (!this.input || !this.contains(this.input)) {
|
|
5688
|
+
this.input = this.#ensureInputControl();
|
|
5689
|
+
this.input.readOnly = this.readonly;
|
|
5690
|
+
this.input.addEventListener("change", this.#boundInputChange);
|
|
5691
|
+
this.input.addEventListener("input", this.#boundNativeInput);
|
|
5554
5692
|
}
|
|
5555
|
-
|
|
5556
|
-
|
|
5693
|
+
this.#syncInputA11yAttributes();
|
|
5694
|
+
this.#syncSearchPrefix();
|
|
5695
|
+
this.#syncSearchClear();
|
|
5696
|
+
this.#syncSearchClearVisibility();
|
|
5697
|
+
this.#syncPasswordToggle();
|
|
5698
|
+
figNormalizeTextOnlyInputSlots(this);
|
|
5557
5699
|
}
|
|
5558
5700
|
#syncInputA11yAttributes() {
|
|
5559
5701
|
if (!this.input) return;
|
|
@@ -5574,8 +5716,11 @@ class FigInputText extends HTMLElement {
|
|
|
5574
5716
|
generated?.remove();
|
|
5575
5717
|
return;
|
|
5576
5718
|
}
|
|
5577
|
-
const prepend = this.querySelector('[slot="prepend"]');
|
|
5578
|
-
if (prepend
|
|
5719
|
+
const prepend = this.querySelector('[slot="prepend"]:not([data-generated])');
|
|
5720
|
+
if (prepend) {
|
|
5721
|
+
generated?.remove();
|
|
5722
|
+
return;
|
|
5723
|
+
}
|
|
5579
5724
|
if (generated) {
|
|
5580
5725
|
const icon = generated.querySelector("fig-icon");
|
|
5581
5726
|
if (icon && icon.getAttribute("name") !== "search") {
|
|
@@ -5599,8 +5744,11 @@ class FigInputText extends HTMLElement {
|
|
|
5599
5744
|
generated?.remove();
|
|
5600
5745
|
return;
|
|
5601
5746
|
}
|
|
5602
|
-
const append = this.querySelector('[slot="append"]');
|
|
5603
|
-
if (append
|
|
5747
|
+
const append = this.querySelector('[slot="append"]:not([data-generated])');
|
|
5748
|
+
if (append) {
|
|
5749
|
+
generated?.remove();
|
|
5750
|
+
return;
|
|
5751
|
+
}
|
|
5604
5752
|
if (generated) {
|
|
5605
5753
|
const icon = generated.querySelector("fig-icon");
|
|
5606
5754
|
if (icon && icon.getAttribute("name") !== "close") {
|
|
@@ -5659,8 +5807,11 @@ class FigInputText extends HTMLElement {
|
|
|
5659
5807
|
this.#passwordVisible = false;
|
|
5660
5808
|
return;
|
|
5661
5809
|
}
|
|
5662
|
-
const append = this.querySelector('[slot="append"]');
|
|
5663
|
-
if (append
|
|
5810
|
+
const append = this.querySelector('[slot="append"]:not([data-generated])');
|
|
5811
|
+
if (append) {
|
|
5812
|
+
generated?.remove();
|
|
5813
|
+
return;
|
|
5814
|
+
}
|
|
5664
5815
|
if (generated) {
|
|
5665
5816
|
this.#updatePasswordToggle(generated);
|
|
5666
5817
|
return;
|
|
@@ -5930,6 +6081,7 @@ class FigInputNumber extends HTMLElement {
|
|
|
5930
6081
|
#boundBlur;
|
|
5931
6082
|
#boundKeyDown;
|
|
5932
6083
|
#boundFocusControl;
|
|
6084
|
+
#boundAdornmentClick;
|
|
5933
6085
|
#units;
|
|
5934
6086
|
#rawUnits;
|
|
5935
6087
|
#unitsDisallow;
|
|
@@ -5937,6 +6089,8 @@ class FigInputNumber extends HTMLElement {
|
|
|
5937
6089
|
#precision;
|
|
5938
6090
|
#isInteracting = false;
|
|
5939
6091
|
#stepperEl = null;
|
|
6092
|
+
#mutationObserver = null;
|
|
6093
|
+
#syncRaf = 0;
|
|
5940
6094
|
#a11yAttributes = [
|
|
5941
6095
|
"aria-label",
|
|
5942
6096
|
"aria-labelledby",
|
|
@@ -6056,6 +6210,7 @@ class FigInputNumber extends HTMLElement {
|
|
|
6056
6210
|
this.#handleKeyDown(e);
|
|
6057
6211
|
};
|
|
6058
6212
|
this.#boundFocusControl = this.focus.bind(this);
|
|
6213
|
+
this.#boundAdornmentClick = this.#handleAdornmentClick.bind(this);
|
|
6059
6214
|
}
|
|
6060
6215
|
|
|
6061
6216
|
connectedCallback() {
|
|
@@ -6114,8 +6269,12 @@ class FigInputNumber extends HTMLElement {
|
|
|
6114
6269
|
}
|
|
6115
6270
|
this.#syncStepperState();
|
|
6116
6271
|
this.#syncSpinbuttonAria();
|
|
6272
|
+
figNormalizeTextOnlyInputSlots(this);
|
|
6117
6273
|
|
|
6118
6274
|
this.addEventListener("pointerdown", this.#boundMouseDown);
|
|
6275
|
+
this.removeEventListener("click", this.#boundAdornmentClick);
|
|
6276
|
+
this.addEventListener("click", this.#boundAdornmentClick);
|
|
6277
|
+
this.#startObserver();
|
|
6119
6278
|
this.input.removeEventListener("change", this.#boundInputChange);
|
|
6120
6279
|
this.input.addEventListener("change", this.#boundInputChange);
|
|
6121
6280
|
this.input.removeEventListener("input", this.#boundInput);
|
|
@@ -6136,10 +6295,17 @@ class FigInputNumber extends HTMLElement {
|
|
|
6136
6295
|
this.input.removeEventListener("blur", this.#boundBlur);
|
|
6137
6296
|
this.input.removeEventListener("keydown", this.#boundKeyDown);
|
|
6138
6297
|
}
|
|
6298
|
+
this.removeEventListener("click", this.#boundAdornmentClick);
|
|
6139
6299
|
this.removeEventListener("pointerdown", this.#boundMouseDown);
|
|
6140
6300
|
window.removeEventListener("pointermove", this.#boundMouseMove);
|
|
6141
6301
|
window.removeEventListener("pointerup", this.#boundMouseUp);
|
|
6142
6302
|
window.removeEventListener("blur", this.#boundWindowBlur);
|
|
6303
|
+
this.#mutationObserver?.disconnect();
|
|
6304
|
+
this.#mutationObserver = null;
|
|
6305
|
+
if (this.#syncRaf) {
|
|
6306
|
+
cancelAnimationFrame(this.#syncRaf);
|
|
6307
|
+
this.#syncRaf = 0;
|
|
6308
|
+
}
|
|
6143
6309
|
}
|
|
6144
6310
|
|
|
6145
6311
|
focus() {
|
|
@@ -6150,30 +6316,62 @@ class FigInputNumber extends HTMLElement {
|
|
|
6150
6316
|
const existing = this.querySelector("input");
|
|
6151
6317
|
if (existing) return existing;
|
|
6152
6318
|
|
|
6153
|
-
const
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6319
|
+
const input = document.createElement("input");
|
|
6320
|
+
input.type = "text";
|
|
6321
|
+
input.inputMode = "decimal";
|
|
6322
|
+
input.setAttribute("data-generated", "input-control");
|
|
6323
|
+
if (this.name) input.name = this.name;
|
|
6324
|
+
input.placeholder = this.placeholder;
|
|
6325
|
+
input.value = this.#formatWithUnit(this.value);
|
|
6326
|
+
this.insertBefore(input, this.querySelector('[slot="append"]'));
|
|
6159
6327
|
|
|
6160
|
-
|
|
6161
|
-
|
|
6328
|
+
return input;
|
|
6329
|
+
}
|
|
6162
6330
|
|
|
6163
|
-
|
|
6331
|
+
#handleAdornmentClick(event) {
|
|
6332
|
+
const adornment = event.target?.closest?.("[slot]");
|
|
6333
|
+
if (!adornment || adornment.parentElement !== this) return;
|
|
6334
|
+
this.focus();
|
|
6335
|
+
}
|
|
6164
6336
|
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6337
|
+
#startObserver() {
|
|
6338
|
+
this.#mutationObserver?.disconnect();
|
|
6339
|
+
this.#mutationObserver = new MutationObserver(() => this.#scheduleLightDomSync());
|
|
6340
|
+
this.#mutationObserver.observe(this, {
|
|
6341
|
+
childList: true,
|
|
6342
|
+
characterData: true,
|
|
6343
|
+
subtree: true,
|
|
6344
|
+
});
|
|
6345
|
+
}
|
|
6346
|
+
|
|
6347
|
+
#scheduleLightDomSync() {
|
|
6348
|
+
if (this.#syncRaf) return;
|
|
6349
|
+
this.#syncRaf = requestAnimationFrame(() => {
|
|
6350
|
+
this.#syncRaf = 0;
|
|
6351
|
+
if (!this.isConnected) return;
|
|
6352
|
+
this.#syncLightDom();
|
|
6353
|
+
});
|
|
6354
|
+
}
|
|
6355
|
+
|
|
6356
|
+
#syncLightDom() {
|
|
6357
|
+
if (!this.input || !this.contains(this.input)) {
|
|
6358
|
+
this.input = this.#ensureInputControl();
|
|
6359
|
+
this.input.addEventListener("change", this.#boundInputChange);
|
|
6360
|
+
this.input.addEventListener("input", this.#boundInput);
|
|
6361
|
+
this.input.addEventListener("focus", this.#boundFocus);
|
|
6362
|
+
this.input.addEventListener("blur", this.#boundBlur);
|
|
6363
|
+
this.input.addEventListener("keydown", this.#boundKeyDown);
|
|
6169
6364
|
}
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6365
|
+
const hasSteppers =
|
|
6366
|
+
this.hasAttribute("steppers") &&
|
|
6367
|
+
this.getAttribute("steppers") !== "false";
|
|
6368
|
+
if (this.#stepperEl && !this.contains(this.#stepperEl)) {
|
|
6369
|
+
this.#stepperEl = null;
|
|
6174
6370
|
}
|
|
6175
|
-
|
|
6176
|
-
|
|
6371
|
+
this.#syncSteppers(hasSteppers);
|
|
6372
|
+
this.#syncInputA11yAttributes();
|
|
6373
|
+
this.#syncSpinbuttonAria();
|
|
6374
|
+
figNormalizeTextOnlyInputSlots(this);
|
|
6177
6375
|
}
|
|
6178
6376
|
|
|
6179
6377
|
#syncInputA11yAttributes() {
|
|
@@ -15106,6 +15304,7 @@ class FigChooser extends HTMLElement {
|
|
|
15106
15304
|
}
|
|
15107
15305
|
if (name === "columns") {
|
|
15108
15306
|
this.#syncGridColumns();
|
|
15307
|
+
this.#resettleSelectedChoice();
|
|
15109
15308
|
}
|
|
15110
15309
|
if (name === "drag") {
|
|
15111
15310
|
if (this.#dragEnabled) {
|
|
@@ -15116,10 +15315,16 @@ class FigChooser extends HTMLElement {
|
|
|
15116
15315
|
}
|
|
15117
15316
|
if (name === "overflow") {
|
|
15118
15317
|
this.#applyOverflowMode();
|
|
15318
|
+
requestAnimationFrame(() => this.#syncOverflow());
|
|
15119
15319
|
}
|
|
15120
15320
|
if (name === "layout") {
|
|
15121
15321
|
this.#applyOverflowMode();
|
|
15122
|
-
|
|
15322
|
+
if (newValue === "horizontal") {
|
|
15323
|
+
this.scrollTop = 0;
|
|
15324
|
+
} else {
|
|
15325
|
+
this.scrollLeft = 0;
|
|
15326
|
+
}
|
|
15327
|
+
this.#resettleSelectedChoice();
|
|
15123
15328
|
}
|
|
15124
15329
|
}
|
|
15125
15330
|
|
|
@@ -15265,6 +15470,7 @@ class FigChooser extends HTMLElement {
|
|
|
15265
15470
|
this.#resizeObserver?.disconnect();
|
|
15266
15471
|
this.#resizeObserver = new ResizeObserver(() => {
|
|
15267
15472
|
this.#syncOverflow();
|
|
15473
|
+
this.#resettleSelectedChoice();
|
|
15268
15474
|
});
|
|
15269
15475
|
this.#resizeObserver.observe(this);
|
|
15270
15476
|
}
|
|
@@ -15452,6 +15658,11 @@ class FigChooser extends HTMLElement {
|
|
|
15452
15658
|
figScrollOverflowPage(this, isHorizontal ? "x" : "y", direction);
|
|
15453
15659
|
}
|
|
15454
15660
|
|
|
15661
|
+
#resettleSelectedChoice() {
|
|
15662
|
+
if (!this.#selectedChoice) return;
|
|
15663
|
+
this.#scrollToChoice(this.#selectedChoice, "auto");
|
|
15664
|
+
}
|
|
15665
|
+
|
|
15455
15666
|
#scrollToChoice(el, behavior = "smooth") {
|
|
15456
15667
|
if (!el) return;
|
|
15457
15668
|
requestAnimationFrame(() => {
|
|
@@ -15464,58 +15675,25 @@ class FigChooser extends HTMLElement {
|
|
|
15464
15675
|
const hostRect = this.getBoundingClientRect();
|
|
15465
15676
|
const options = { behavior };
|
|
15466
15677
|
let shouldScroll = false;
|
|
15467
|
-
const threshold = 2;
|
|
15468
15678
|
|
|
15469
15679
|
if (overflowY) {
|
|
15470
|
-
const
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
|
|
15477
|
-
!fullyVisible &&
|
|
15478
|
-
(!topVisible ||
|
|
15479
|
-
(!bottomVisible && !atScrollStart) ||
|
|
15480
|
-
choiceRect.top >= hostRect.bottom - 1);
|
|
15481
|
-
if (needsScroll) {
|
|
15482
|
-
const choiceTop = choiceRect.top - hostRect.top + this.scrollTop;
|
|
15483
|
-
const maxScroll = this.scrollHeight - this.clientHeight;
|
|
15484
|
-
options.top = Math.max(
|
|
15485
|
-
0,
|
|
15486
|
-
Math.min(
|
|
15487
|
-
choiceTop + choiceRect.height / 2 - this.clientHeight / 2,
|
|
15488
|
-
maxScroll,
|
|
15489
|
-
),
|
|
15490
|
-
);
|
|
15491
|
-
shouldScroll = true;
|
|
15492
|
-
}
|
|
15680
|
+
const choiceTop = choiceRect.top - hostRect.top + this.scrollTop;
|
|
15681
|
+
const maxScroll = this.scrollHeight - this.clientHeight;
|
|
15682
|
+
options.top = Math.max(
|
|
15683
|
+
0,
|
|
15684
|
+
Math.min(choiceTop + choiceRect.height / 2 - this.clientHeight / 2, maxScroll),
|
|
15685
|
+
);
|
|
15686
|
+
shouldScroll = true;
|
|
15493
15687
|
}
|
|
15494
15688
|
|
|
15495
15689
|
if (overflowX) {
|
|
15496
|
-
const
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
|
|
15501
|
-
|
|
15502
|
-
|
|
15503
|
-
!fullyVisible &&
|
|
15504
|
-
(!startVisible ||
|
|
15505
|
-
(!endVisible && !atScrollStart) ||
|
|
15506
|
-
choiceRect.left >= hostRect.right - 1);
|
|
15507
|
-
if (needsScroll) {
|
|
15508
|
-
const choiceLeft = choiceRect.left - hostRect.left + this.scrollLeft;
|
|
15509
|
-
const maxScroll = this.scrollWidth - this.clientWidth;
|
|
15510
|
-
options.left = Math.max(
|
|
15511
|
-
0,
|
|
15512
|
-
Math.min(
|
|
15513
|
-
choiceLeft + choiceRect.width / 2 - this.clientWidth / 2,
|
|
15514
|
-
maxScroll,
|
|
15515
|
-
),
|
|
15516
|
-
);
|
|
15517
|
-
shouldScroll = true;
|
|
15518
|
-
}
|
|
15690
|
+
const choiceLeft = choiceRect.left - hostRect.left + this.scrollLeft;
|
|
15691
|
+
const maxScroll = this.scrollWidth - this.clientWidth;
|
|
15692
|
+
options.left = Math.max(
|
|
15693
|
+
0,
|
|
15694
|
+
Math.min(choiceLeft + choiceRect.width / 2 - this.clientWidth / 2, maxScroll),
|
|
15695
|
+
);
|
|
15696
|
+
shouldScroll = true;
|
|
15519
15697
|
}
|
|
15520
15698
|
|
|
15521
15699
|
if (shouldScroll) {
|
package/package.json
CHANGED