@rogieking/figui3 6.20.2 → 6.21.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/README.md +50 -1
- package/components.css +63 -2
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +240 -98
- package/dist/fig-lab.css +1 -1
- package/dist/fig-lab.js +16 -16
- package/dist/fig.css +1 -1
- package/dist/fig.js +60 -43
- package/dist/propskit.css +1 -0
- package/dist/propskit.js +591 -0
- package/fig-editor.css +157 -17
- package/fig-editor.js +457 -187
- package/fig-lab.css +51 -42
- package/fig-lab.js +125 -9
- package/fig.js +519 -16
- package/package.json +33 -4
- package/propskit-core.js +556 -0
- package/propskit.d.ts +98 -0
- package/propskit.js +15 -0
package/fig-lab.css
CHANGED
|
@@ -137,27 +137,33 @@ fig-content:has(> propskit-group[name]:last-child) {
|
|
|
137
137
|
padding-bottom: 0;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
/*
|
|
141
|
-
propskit-select applies left inset on label + trigger
|
|
140
|
+
/* Default/large size: more left field padding; nudge trailing controls in from
|
|
141
|
+
the right. propskit-select applies left inset on label + trigger instead. */
|
|
142
142
|
:is(
|
|
143
143
|
propskit-switch,
|
|
144
144
|
propskit-color,
|
|
145
145
|
propskit-text,
|
|
146
146
|
propskit-number,
|
|
147
147
|
propskit-slider
|
|
148
|
-
)[size="large"] {
|
|
148
|
+
):is(:not([size]), [size="large"]) {
|
|
149
149
|
fig-field:not([direction="vertical"]) {
|
|
150
150
|
padding-left: var(--spacer-2-5);
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
/* Flex-positioned numbers — margin works. Absolute numbers use right: calc(...) below. */
|
|
155
|
-
:is(propskit-color, propskit-number)[size="large"] {
|
|
155
|
+
:is(propskit-color, propskit-number):is(:not([size]), [size="large"]) {
|
|
156
156
|
fig-field fig-input-number {
|
|
157
157
|
margin-right: var(--spacer-1);
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
propskit-text:is(:not([size]), [size="large"]) {
|
|
162
|
+
fig-field > fig-input-text {
|
|
163
|
+
margin-right: var(--spacer-1);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
161
167
|
propskit-switch {
|
|
162
168
|
--propskit-switch-height: 2rem;
|
|
163
169
|
--propskit-switch-vertical-padding: var(--spacer-1);
|
|
@@ -169,6 +175,7 @@ propskit-switch {
|
|
|
169
175
|
padding: var(--propskit-switch-vertical-padding)
|
|
170
176
|
var(--propskit-switch-horizontal-padding);
|
|
171
177
|
|
|
178
|
+
&:not([size]),
|
|
172
179
|
&[size="large"] {
|
|
173
180
|
--propskit-switch-vertical-padding: 0px;
|
|
174
181
|
|
|
@@ -245,6 +252,7 @@ propskit-color {
|
|
|
245
252
|
padding: var(--propskit-color-vertical-padding)
|
|
246
253
|
var(--propskit-color-horizontal-padding);
|
|
247
254
|
|
|
255
|
+
&:not([size]),
|
|
248
256
|
&[size="large"] {
|
|
249
257
|
--propskit-color-vertical-padding: 0px;
|
|
250
258
|
}
|
|
@@ -368,6 +376,7 @@ propskit-select {
|
|
|
368
376
|
padding: var(--propskit-select-vertical-padding)
|
|
369
377
|
var(--propskit-select-horizontal-padding);
|
|
370
378
|
|
|
379
|
+
&:not([size]),
|
|
371
380
|
&[size="large"] {
|
|
372
381
|
--propskit-select-vertical-padding: 0px;
|
|
373
382
|
|
|
@@ -477,6 +486,7 @@ propskit-text {
|
|
|
477
486
|
padding: var(--propskit-text-vertical-padding)
|
|
478
487
|
var(--propskit-text-horizontal-padding);
|
|
479
488
|
|
|
489
|
+
&:not([size]),
|
|
480
490
|
&[size="large"] {
|
|
481
491
|
--propskit-text-vertical-padding: 0px;
|
|
482
492
|
}
|
|
@@ -586,6 +596,7 @@ propskit-number {
|
|
|
586
596
|
padding: var(--propskit-number-vertical-padding)
|
|
587
597
|
var(--propskit-number-horizontal-padding);
|
|
588
598
|
|
|
599
|
+
&:not([size]),
|
|
589
600
|
&[size="large"] {
|
|
590
601
|
--propskit-number-vertical-padding: 0px;
|
|
591
602
|
|
|
@@ -714,6 +725,7 @@ propskit-slider {
|
|
|
714
725
|
padding-left: var(--propskit-slider-horizontal-padding);
|
|
715
726
|
padding-right: var(--propskit-slider-horizontal-padding);
|
|
716
727
|
|
|
728
|
+
&:not([size]),
|
|
717
729
|
&[size="large"] {
|
|
718
730
|
--propskit-slider-vertical-padding: 0px;
|
|
719
731
|
--propskit-slider-fig-slider-thumb-height: calc(
|
|
@@ -1496,9 +1508,9 @@ fig-select::part(listbox) {
|
|
|
1496
1508
|
background-color: var(--fig-popup-bg-color);
|
|
1497
1509
|
color: var(--figma-color-text-menu);
|
|
1498
1510
|
color-scheme: dark;
|
|
1499
|
-
box-shadow: var(--figma-elevation-
|
|
1511
|
+
box-shadow: var(--figma-elevation-400-menu-panel);
|
|
1500
1512
|
/* width/min/max set in JS — ::part width rules override element.style. */
|
|
1501
|
-
max-height:
|
|
1513
|
+
max-height: calc(100vh - 1rem);
|
|
1502
1514
|
height: max-content;
|
|
1503
1515
|
}
|
|
1504
1516
|
|
|
@@ -1512,7 +1524,7 @@ fig-select-options {
|
|
|
1512
1524
|
gap: 0;
|
|
1513
1525
|
width: 100%;
|
|
1514
1526
|
max-width: 100%;
|
|
1515
|
-
max-height:
|
|
1527
|
+
max-height: calc(100vh - 1rem);
|
|
1516
1528
|
/* No block padding — sticky overflow buttons must sit flush to the popup edges. */
|
|
1517
1529
|
padding: 0;
|
|
1518
1530
|
overflow: hidden auto;
|
|
@@ -1595,56 +1607,35 @@ fig-select-options {
|
|
|
1595
1607
|
& > fig-menu-separator {
|
|
1596
1608
|
--fig-menu-separator-color: var(--figma-color-border-menu);
|
|
1597
1609
|
--fig-menu-separator-label-color: var(--figma-color-text-menu-secondary);
|
|
1598
|
-
|
|
1599
|
-
|
|
1610
|
+
|
|
1611
|
+
/* Align label with option text (padding + checkmark column).
|
|
1612
|
+
Negative margins on ::before must match this padding exactly so the
|
|
1613
|
+
rule bleeds to the listbox edges (base rule uses --fig-menu-item-padding). */
|
|
1600
1614
|
&[label]:not([label=""]) {
|
|
1601
1615
|
padding-left: var(--spacer-5);
|
|
1602
1616
|
padding-right: var(--spacer-2);
|
|
1617
|
+
|
|
1618
|
+
&::before {
|
|
1619
|
+
margin-inline: unset;
|
|
1620
|
+
margin-left: calc(-1 * var(--spacer-5));
|
|
1621
|
+
margin-right: calc(-1 * var(--spacer-2));
|
|
1622
|
+
}
|
|
1603
1623
|
}
|
|
1604
1624
|
}
|
|
1605
1625
|
}
|
|
1606
1626
|
|
|
1607
|
-
/*
|
|
1608
|
-
[label]:not([label=""]) {
|
|
1609
|
-
display: flex;
|
|
1610
|
-
flex-direction: column;
|
|
1611
|
-
gap: var(--spacer-2);
|
|
1612
|
-
height: auto;
|
|
1613
|
-
margin: var(--spacer-2) 0;
|
|
1614
|
-
margin-bottom: var(--spacer-1);
|
|
1615
|
-
padding: 0 var(--spacer-2) 0 var(--fig-menu-item-padding, var(--spacer-4));
|
|
1616
|
-
background: transparent;
|
|
1617
|
-
|
|
1618
|
-
&::before {
|
|
1619
|
-
content: "";
|
|
1620
|
-
display: block;
|
|
1621
|
-
height: 1px;
|
|
1622
|
-
margin-left: calc(-1 * var(--fig-menu-item-padding, var(--spacer-4)));
|
|
1623
|
-
margin-right: calc(-1 * var(--spacer-2));
|
|
1624
|
-
background: var(--fig-menu-separator-color);
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
|
-
&::after {
|
|
1628
|
-
content: attr(label);
|
|
1629
|
-
display: block;
|
|
1630
|
-
color: var(--fig-menu-separator-label-color);
|
|
1631
|
-
line-height: var(--spacer-4);
|
|
1632
|
-
min-height: var(--spacer-4);
|
|
1633
|
-
}
|
|
1634
|
-
}*/
|
|
1635
|
-
|
|
1636
1627
|
fig-select-option {
|
|
1637
1628
|
/* Match fig-dropdown[experimental~="modern"] option + option::checkmark */
|
|
1638
1629
|
display: flex;
|
|
1639
1630
|
align-items: center;
|
|
1640
|
-
gap:
|
|
1631
|
+
gap: 0;
|
|
1641
1632
|
position: relative;
|
|
1642
|
-
height: var(--spacer-4);
|
|
1643
|
-
|
|
1633
|
+
min-height: var(--spacer-4);
|
|
1634
|
+
height: auto;
|
|
1635
|
+
padding: var(--spacer-1) var(--spacer-2);
|
|
1644
1636
|
padding-right: var(--spacer-3);
|
|
1645
1637
|
border-radius: var(--radius-medium);
|
|
1646
1638
|
color: var(--figma-color-text-menu);
|
|
1647
|
-
font-weight: var(--body-medium-fontWeight);
|
|
1648
1639
|
cursor: default;
|
|
1649
1640
|
user-select: none;
|
|
1650
1641
|
|
|
@@ -1678,6 +1669,24 @@ fig-select-option {
|
|
|
1678
1669
|
visibility: hidden;
|
|
1679
1670
|
}
|
|
1680
1671
|
|
|
1672
|
+
& > [slot="prepend"] {
|
|
1673
|
+
margin-top: calc(var(--spacer-1) * -1);
|
|
1674
|
+
margin-bottom: calc(var(--spacer-1) * -1);
|
|
1675
|
+
margin-right: var(--spacer-1);
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
|
|
1679
|
+
& > :not([slot="prepend"]):not([slot="append"]) {
|
|
1680
|
+
flex: 1 1 auto;
|
|
1681
|
+
min-width: 0;
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
& > [slot="append"] {
|
|
1685
|
+
flex: 0 0 auto;
|
|
1686
|
+
margin-inline-start: auto;
|
|
1687
|
+
color: var(--figma-color-text-tertiary);
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1681
1690
|
&:hover,
|
|
1682
1691
|
&:focus-visible {
|
|
1683
1692
|
outline: none;
|
package/fig-lab.js
CHANGED
|
@@ -128,12 +128,12 @@ class PropskitSwitch extends HTMLElement {
|
|
|
128
128
|
const reserved = new Set([
|
|
129
129
|
"label",
|
|
130
130
|
"direction",
|
|
131
|
+
"size",
|
|
131
132
|
"oninput",
|
|
132
133
|
"onchange",
|
|
133
134
|
"class",
|
|
134
135
|
"style",
|
|
135
136
|
"id",
|
|
136
|
-
"size",
|
|
137
137
|
"checked",
|
|
138
138
|
"value",
|
|
139
139
|
]);
|
|
@@ -1094,6 +1094,7 @@ class PropskitNumber extends HTMLElement {
|
|
|
1094
1094
|
const reserved = new Set([
|
|
1095
1095
|
"label",
|
|
1096
1096
|
"direction",
|
|
1097
|
+
"size",
|
|
1097
1098
|
"oninput",
|
|
1098
1099
|
"onchange",
|
|
1099
1100
|
"class",
|
|
@@ -5384,9 +5385,19 @@ function figLabOptionEntryLabel(opt) {
|
|
|
5384
5385
|
return String(opt ?? "");
|
|
5385
5386
|
}
|
|
5386
5387
|
|
|
5388
|
+
/**
|
|
5389
|
+
* A selectable option for fig-select.
|
|
5390
|
+
* Supports light-DOM slots: `slot="prepend"` (leading) and `slot="append"` (trailing).
|
|
5391
|
+
* Use the `label` attribute for the closed-trigger label when option content is rich.
|
|
5392
|
+
*
|
|
5393
|
+
* @attr {string} value - Option value
|
|
5394
|
+
* @attr {string} label - Optional display label for the select trigger
|
|
5395
|
+
* @attr {boolean} disabled - Whether the option is disabled
|
|
5396
|
+
* @attr {boolean} selected - Whether the option is selected
|
|
5397
|
+
*/
|
|
5387
5398
|
class FigSelectOption extends HTMLElement {
|
|
5388
5399
|
static get observedAttributes() {
|
|
5389
|
-
return ["value", "disabled", "selected"];
|
|
5400
|
+
return ["value", "disabled", "selected", "label"];
|
|
5390
5401
|
}
|
|
5391
5402
|
|
|
5392
5403
|
get value() {
|
|
@@ -5599,8 +5610,14 @@ class FigSelect extends HTMLElement {
|
|
|
5599
5610
|
#syncingValue = false;
|
|
5600
5611
|
#popupPositionPatched = false;
|
|
5601
5612
|
#originalPositionPopup = null;
|
|
5602
|
-
/**
|
|
5613
|
+
/**
|
|
5614
|
+
* After open align, ignore content/scroll-driven positionPopup passes so
|
|
5615
|
+
* overflow paging isn't yanked back. Still realign when the trigger moves
|
|
5616
|
+
* or the viewport size changes (window resize, layout shift, page scroll).
|
|
5617
|
+
*/
|
|
5603
5618
|
#freezeMenuPosition = false;
|
|
5619
|
+
#frozenLabelRect = null;
|
|
5620
|
+
#frozenViewport = null;
|
|
5604
5621
|
#syncingOptions = false;
|
|
5605
5622
|
#boundTriggerClick = this.#handleTriggerClick.bind(this);
|
|
5606
5623
|
#boundOptionClick = this.#handleOptionClick.bind(this);
|
|
@@ -5871,6 +5888,12 @@ class FigSelect extends HTMLElement {
|
|
|
5871
5888
|
popup.setAttribute("part", "listbox");
|
|
5872
5889
|
popup.setAttribute("theme", "menu");
|
|
5873
5890
|
popup.setAttribute("role", "listbox");
|
|
5891
|
+
// Top-layer via popover so the menu escapes ancestor contain/overflow
|
|
5892
|
+
// (e.g. fig-fill-picker-dialog). Stays in shadow so option slots still work —
|
|
5893
|
+
// unlike tooltips, we cannot portal this popup to the overlay root.
|
|
5894
|
+
if ("popover" in HTMLElement.prototype) {
|
|
5895
|
+
popup.setAttribute("popover", "manual");
|
|
5896
|
+
}
|
|
5874
5897
|
popup.id = figLabUniqueId("fig-select-list");
|
|
5875
5898
|
button.setAttribute("aria-controls", popup.id);
|
|
5876
5899
|
|
|
@@ -5930,10 +5953,73 @@ class FigSelect extends HTMLElement {
|
|
|
5930
5953
|
return { top: 8, right: 8, bottom: 8, left: 8 };
|
|
5931
5954
|
}
|
|
5932
5955
|
|
|
5956
|
+
#readLabelRectSnapshot() {
|
|
5957
|
+
const rect = this.#labelEl?.getBoundingClientRect();
|
|
5958
|
+
if (!rect) return null;
|
|
5959
|
+
return {
|
|
5960
|
+
x: rect.x,
|
|
5961
|
+
y: rect.y,
|
|
5962
|
+
width: rect.width,
|
|
5963
|
+
height: rect.height,
|
|
5964
|
+
};
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5967
|
+
#readViewportSnapshot() {
|
|
5968
|
+
const vv = window.visualViewport;
|
|
5969
|
+
return {
|
|
5970
|
+
width: vv?.width ?? window.innerWidth,
|
|
5971
|
+
height: vv?.height ?? window.innerHeight,
|
|
5972
|
+
offsetLeft: vv?.offsetLeft ?? 0,
|
|
5973
|
+
offsetTop: vv?.offsetTop ?? 0,
|
|
5974
|
+
};
|
|
5975
|
+
}
|
|
5976
|
+
|
|
5977
|
+
#rectSnapshotChanged(prev, next, epsilon = 0.25) {
|
|
5978
|
+
if (!prev && !next) return false;
|
|
5979
|
+
if (!prev || !next) return true;
|
|
5980
|
+
return (
|
|
5981
|
+
Math.abs(prev.x - next.x) > epsilon ||
|
|
5982
|
+
Math.abs(prev.y - next.y) > epsilon ||
|
|
5983
|
+
Math.abs(prev.width - next.width) > epsilon ||
|
|
5984
|
+
Math.abs(prev.height - next.height) > epsilon
|
|
5985
|
+
);
|
|
5986
|
+
}
|
|
5987
|
+
|
|
5988
|
+
#viewportSnapshotChanged(prev, next, epsilon = 0.25) {
|
|
5989
|
+
if (!prev && !next) return false;
|
|
5990
|
+
if (!prev || !next) return true;
|
|
5991
|
+
return (
|
|
5992
|
+
Math.abs(prev.width - next.width) > epsilon ||
|
|
5993
|
+
Math.abs(prev.height - next.height) > epsilon ||
|
|
5994
|
+
Math.abs(prev.offsetLeft - next.offsetLeft) > epsilon ||
|
|
5995
|
+
Math.abs(prev.offsetTop - next.offsetTop) > epsilon
|
|
5996
|
+
);
|
|
5997
|
+
}
|
|
5998
|
+
|
|
5999
|
+
#shouldSkipFrozenPositionPass() {
|
|
6000
|
+
if (!this.#freezeMenuPosition) return false;
|
|
6001
|
+
const labelMoved = this.#rectSnapshotChanged(
|
|
6002
|
+
this.#frozenLabelRect,
|
|
6003
|
+
this.#readLabelRectSnapshot(),
|
|
6004
|
+
);
|
|
6005
|
+
const viewportChanged = this.#viewportSnapshotChanged(
|
|
6006
|
+
this.#frozenViewport,
|
|
6007
|
+
this.#readViewportSnapshot(),
|
|
6008
|
+
);
|
|
6009
|
+
// Skip only when neither the trigger nor the viewport moved — typical of
|
|
6010
|
+
// overflow scroll / content sync fighting the open-time alignment.
|
|
6011
|
+
return !labelMoved && !viewportChanged;
|
|
6012
|
+
}
|
|
6013
|
+
|
|
6014
|
+
#rememberFrozenGeometry() {
|
|
6015
|
+
this.#frozenLabelRect = this.#readLabelRectSnapshot();
|
|
6016
|
+
this.#frozenViewport = this.#readViewportSnapshot();
|
|
6017
|
+
}
|
|
6018
|
+
|
|
5933
6019
|
#positionPopupOverSelected() {
|
|
5934
|
-
// Content ResizeObserver /
|
|
5935
|
-
//
|
|
5936
|
-
if (this.#
|
|
6020
|
+
// Content ResizeObserver / overflow scroll re-enter here; keep the
|
|
6021
|
+
// open-time alignment unless the trigger or viewport actually changed.
|
|
6022
|
+
if (this.#shouldSkipFrozenPositionPass()) return;
|
|
5937
6023
|
|
|
5938
6024
|
const popup = this.#popup;
|
|
5939
6025
|
const label = this.#labelEl;
|
|
@@ -6011,6 +6097,10 @@ class FigSelect extends HTMLElement {
|
|
|
6011
6097
|
}
|
|
6012
6098
|
panel.syncOverflow?.();
|
|
6013
6099
|
}
|
|
6100
|
+
|
|
6101
|
+
if (this.#freezeMenuPosition || this.open) {
|
|
6102
|
+
this.#rememberFrozenGeometry();
|
|
6103
|
+
}
|
|
6014
6104
|
}
|
|
6015
6105
|
|
|
6016
6106
|
#setupListeners() {
|
|
@@ -6055,7 +6145,8 @@ class FigSelect extends HTMLElement {
|
|
|
6055
6145
|
mutation.type === "attributes" &&
|
|
6056
6146
|
mutation.target?.tagName === "FIG-SELECT-OPTION" &&
|
|
6057
6147
|
(mutation.attributeName === "value" ||
|
|
6058
|
-
mutation.attributeName === "disabled"
|
|
6148
|
+
mutation.attributeName === "disabled" ||
|
|
6149
|
+
mutation.attributeName === "label")
|
|
6059
6150
|
) {
|
|
6060
6151
|
needsSync = true;
|
|
6061
6152
|
}
|
|
@@ -6073,7 +6164,7 @@ class FigSelect extends HTMLElement {
|
|
|
6073
6164
|
subtree: true,
|
|
6074
6165
|
characterData: true,
|
|
6075
6166
|
attributes: true,
|
|
6076
|
-
attributeFilter: ["value", "disabled", "selected"],
|
|
6167
|
+
attributeFilter: ["value", "disabled", "selected", "label"],
|
|
6077
6168
|
});
|
|
6078
6169
|
}
|
|
6079
6170
|
|
|
@@ -6095,7 +6186,26 @@ class FigSelect extends HTMLElement {
|
|
|
6095
6186
|
}
|
|
6096
6187
|
|
|
6097
6188
|
#optionLabel(option) {
|
|
6098
|
-
|
|
6189
|
+
if (!option) return "";
|
|
6190
|
+
const labelAttr = option.getAttribute?.("label");
|
|
6191
|
+
if (labelAttr != null && labelAttr !== "") return labelAttr.trim();
|
|
6192
|
+
|
|
6193
|
+
// Ignore prepend/append slot content when deriving a label from children.
|
|
6194
|
+
const parts = [];
|
|
6195
|
+
for (const node of option.childNodes) {
|
|
6196
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
6197
|
+
const text = node.textContent?.trim();
|
|
6198
|
+
if (text) parts.push(text);
|
|
6199
|
+
continue;
|
|
6200
|
+
}
|
|
6201
|
+
if (!(node instanceof Element)) continue;
|
|
6202
|
+
const slot = node.getAttribute("slot");
|
|
6203
|
+
if (slot === "prepend" || slot === "append") continue;
|
|
6204
|
+
const text = node.textContent?.trim();
|
|
6205
|
+
if (text) parts.push(text);
|
|
6206
|
+
}
|
|
6207
|
+
if (parts.length) return parts.join(" ").trim();
|
|
6208
|
+
return (option.textContent || "").trim();
|
|
6099
6209
|
}
|
|
6100
6210
|
|
|
6101
6211
|
#syncPopupAttrs() {
|
|
@@ -6375,6 +6485,8 @@ class FigSelect extends HTMLElement {
|
|
|
6375
6485
|
if (this.#button) this.#popup.anchor = this.#button;
|
|
6376
6486
|
this.#installPopupPositioning();
|
|
6377
6487
|
this.#freezeMenuPosition = false;
|
|
6488
|
+
this.#frozenLabelRect = null;
|
|
6489
|
+
this.#frozenViewport = null;
|
|
6378
6490
|
this.#syncValue();
|
|
6379
6491
|
this.#syncPopupWidth();
|
|
6380
6492
|
this.#popup.open = true;
|
|
@@ -6399,13 +6511,17 @@ class FigSelect extends HTMLElement {
|
|
|
6399
6511
|
}
|
|
6400
6512
|
panel?.syncOverflow?.();
|
|
6401
6513
|
// Freeze after open align so later positionPopup passes don't undo scroll.
|
|
6514
|
+
// Window resize / trigger movement still realigns via geometry checks.
|
|
6402
6515
|
this.#freezeMenuPosition = true;
|
|
6516
|
+
this.#rememberFrozenGeometry();
|
|
6403
6517
|
});
|
|
6404
6518
|
}
|
|
6405
6519
|
|
|
6406
6520
|
#closeList() {
|
|
6407
6521
|
if (!this.#popup) return;
|
|
6408
6522
|
this.#freezeMenuPosition = false;
|
|
6523
|
+
this.#frozenLabelRect = null;
|
|
6524
|
+
this.#frozenViewport = null;
|
|
6409
6525
|
document.removeEventListener("keydown", this.#boundKeydown, true);
|
|
6410
6526
|
this.#popup.open = false;
|
|
6411
6527
|
this.#button?.setAttribute("aria-expanded", "false");
|