@rogieking/figui3 2.10.1 → 2.10.2
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 +1 -11
- package/fig.js +37 -74
- package/package.json +1 -1
package/components.css
CHANGED
|
@@ -581,10 +581,8 @@ input[type="text"][list] {
|
|
|
581
581
|
}
|
|
582
582
|
|
|
583
583
|
::picker(select) {
|
|
584
|
-
position-area: auto;
|
|
585
|
-
align-self: auto;
|
|
586
|
-
max-block-size: 100vh;
|
|
587
584
|
appearance: base-select;
|
|
585
|
+
|
|
588
586
|
scrollbar-width: thin;
|
|
589
587
|
outline: 0;
|
|
590
588
|
scrollbar-color: var(--figma-color-text-menu-tertiary)
|
|
@@ -595,14 +593,6 @@ input[type="text"][list] {
|
|
|
595
593
|
padding: var(--spacer-2) 0;
|
|
596
594
|
box-shadow: var(--figma-elevation-400-menu-panel);
|
|
597
595
|
}
|
|
598
|
-
select {
|
|
599
|
-
&::picker(select) {
|
|
600
|
-
/* --picker-top and --picker-max-height are calculated by JavaScript */
|
|
601
|
-
top: var(--picker-top, 0px);
|
|
602
|
-
max-height: var(--picker-max-height, 100vh);
|
|
603
|
-
overflow-y: auto;
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
596
|
}
|
|
607
597
|
}
|
|
608
598
|
|
package/fig.js
CHANGED
|
@@ -167,9 +167,6 @@ customElements.define("fig-button", FigButton);
|
|
|
167
167
|
class FigDropdown extends HTMLElement {
|
|
168
168
|
#label = "Menu";
|
|
169
169
|
#selectedValue = null; // Stores last selected value for dropdown type
|
|
170
|
-
#optionHeight = 28; // Default option height in pixels
|
|
171
|
-
#pickerPadding = 8; // Padding inside picker (spacer-2)
|
|
172
|
-
#viewportMargin = 8; // Minimum margin from viewport edges
|
|
173
170
|
|
|
174
171
|
get label() {
|
|
175
172
|
return this.#label;
|
|
@@ -187,12 +184,6 @@ class FigDropdown extends HTMLElement {
|
|
|
187
184
|
#addEventListeners() {
|
|
188
185
|
this.select.addEventListener("input", this.#handleSelectInput.bind(this));
|
|
189
186
|
this.select.addEventListener("change", this.#handleSelectChange.bind(this));
|
|
190
|
-
// Calculate picker position before it opens
|
|
191
|
-
this.select.addEventListener(
|
|
192
|
-
"mousedown",
|
|
193
|
-
this.#calculatePickerPosition.bind(this),
|
|
194
|
-
);
|
|
195
|
-
this.select.addEventListener("keydown", this.#handleKeyDown.bind(this));
|
|
196
187
|
}
|
|
197
188
|
|
|
198
189
|
connectedCallback() {
|
|
@@ -230,7 +221,6 @@ class FigDropdown extends HTMLElement {
|
|
|
230
221
|
if (this.type === "dropdown") {
|
|
231
222
|
this.select.selectedIndex = -1;
|
|
232
223
|
}
|
|
233
|
-
this.#calculatePickerPosition();
|
|
234
224
|
}
|
|
235
225
|
|
|
236
226
|
#handleSelectInput(e) {
|
|
@@ -257,7 +247,6 @@ class FigDropdown extends HTMLElement {
|
|
|
257
247
|
if (this.type === "dropdown") {
|
|
258
248
|
this.select.selectedIndex = -1;
|
|
259
249
|
}
|
|
260
|
-
this.#calculatePickerPosition();
|
|
261
250
|
this.dispatchEvent(
|
|
262
251
|
new CustomEvent("change", {
|
|
263
252
|
detail: selectedValue,
|
|
@@ -267,64 +256,6 @@ class FigDropdown extends HTMLElement {
|
|
|
267
256
|
);
|
|
268
257
|
}
|
|
269
258
|
|
|
270
|
-
#handleKeyDown(e) {
|
|
271
|
-
// Recalculate on keyboard navigation that might open the picker
|
|
272
|
-
if (
|
|
273
|
-
e.key === " " ||
|
|
274
|
-
e.key === "Enter" ||
|
|
275
|
-
e.key === "ArrowDown" ||
|
|
276
|
-
e.key === "ArrowUp"
|
|
277
|
-
) {
|
|
278
|
-
this.#calculatePickerPosition();
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
#calculatePickerPosition() {
|
|
283
|
-
// Only apply positioning for neue variant
|
|
284
|
-
if (this.getAttribute("variant") !== "neue") {
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Get positions in viewport
|
|
289
|
-
const dropdownRect = this.getBoundingClientRect();
|
|
290
|
-
const selectRect = this.select.getBoundingClientRect();
|
|
291
|
-
const viewportHeight = window.innerHeight;
|
|
292
|
-
|
|
293
|
-
// Get selected index (use 0 for dropdown type since nothing is visually selected)
|
|
294
|
-
let selectedIndex = this.select.selectedIndex;
|
|
295
|
-
if (this.type === "dropdown" || selectedIndex < 0) {
|
|
296
|
-
selectedIndex = 0;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Calculate the top offset to align selected item with trigger
|
|
300
|
-
// This is relative to the anchor point (bottom of select by default)
|
|
301
|
-
const pickerTopOffset =
|
|
302
|
-
-1 * (selectedIndex + 1) * this.#optionHeight - this.#pickerPadding;
|
|
303
|
-
|
|
304
|
-
// The picker is anchored to the select, and top offset is relative to the anchor
|
|
305
|
-
// Anchor is typically at the bottom of the select element
|
|
306
|
-
// Actual picker top = select.bottom + topOffset (topOffset is negative)
|
|
307
|
-
const pickerActualTop = selectRect.bottom + pickerTopOffset;
|
|
308
|
-
|
|
309
|
-
// Ensure picker doesn't go above viewport
|
|
310
|
-
let adjustedTopOffset = pickerTopOffset;
|
|
311
|
-
if (pickerActualTop < this.#viewportMargin) {
|
|
312
|
-
adjustedTopOffset = this.#viewportMargin - selectRect.bottom;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Recalculate actual top with adjusted offset
|
|
316
|
-
const adjustedActualTop = selectRect.bottom + adjustedTopOffset;
|
|
317
|
-
|
|
318
|
-
// Calculate max-height: from picker's actual top to 1rem (16px) from bottom of viewport
|
|
319
|
-
const bottomMargin = 16; // 1rem
|
|
320
|
-
const maxHeight = viewportHeight - adjustedActualTop - bottomMargin;
|
|
321
|
-
|
|
322
|
-
// Set CSS variables for the picker
|
|
323
|
-
this.select.style.setProperty("--selected-index", selectedIndex);
|
|
324
|
-
this.select.style.setProperty("--picker-top", `${adjustedTopOffset}px`);
|
|
325
|
-
this.select.style.setProperty("--picker-max-height", `${Math.max(0, maxHeight)}px`);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
259
|
focus() {
|
|
329
260
|
this.select.focus();
|
|
330
261
|
}
|
|
@@ -346,7 +277,7 @@ class FigDropdown extends HTMLElement {
|
|
|
346
277
|
this.setAttribute("value", value);
|
|
347
278
|
}
|
|
348
279
|
static get observedAttributes() {
|
|
349
|
-
return ["value", "type"
|
|
280
|
+
return ["value", "type"];
|
|
350
281
|
}
|
|
351
282
|
#syncSelectedValue(value) {
|
|
352
283
|
// For dropdown type, don't sync the visual selection - it should always show the hidden placeholder
|
|
@@ -359,7 +290,6 @@ class FigDropdown extends HTMLElement {
|
|
|
359
290
|
this.select.selectedIndex = i;
|
|
360
291
|
}
|
|
361
292
|
});
|
|
362
|
-
this.#calculatePickerPosition();
|
|
363
293
|
}
|
|
364
294
|
}
|
|
365
295
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -373,9 +303,6 @@ class FigDropdown extends HTMLElement {
|
|
|
373
303
|
this.#label = newValue;
|
|
374
304
|
this.select.setAttribute("aria-label", this.#label);
|
|
375
305
|
}
|
|
376
|
-
if (name === "variant") {
|
|
377
|
-
this.#calculatePickerPosition();
|
|
378
|
-
}
|
|
379
306
|
}
|
|
380
307
|
}
|
|
381
308
|
|
|
@@ -2008,6 +1935,7 @@ class FigInputNumber extends HTMLElement {
|
|
|
2008
1935
|
#boundInput;
|
|
2009
1936
|
#boundFocus;
|
|
2010
1937
|
#boundBlur;
|
|
1938
|
+
#boundKeyDown;
|
|
2011
1939
|
#units;
|
|
2012
1940
|
#unitPosition;
|
|
2013
1941
|
|
|
@@ -2031,6 +1959,9 @@ class FigInputNumber extends HTMLElement {
|
|
|
2031
1959
|
this.#boundBlur = (e) => {
|
|
2032
1960
|
this.#handleBlur(e);
|
|
2033
1961
|
};
|
|
1962
|
+
this.#boundKeyDown = (e) => {
|
|
1963
|
+
this.#handleKeyDown(e);
|
|
1964
|
+
};
|
|
2034
1965
|
}
|
|
2035
1966
|
|
|
2036
1967
|
connectedCallback() {
|
|
@@ -2103,6 +2034,8 @@ class FigInputNumber extends HTMLElement {
|
|
|
2103
2034
|
this.input.addEventListener("focus", this.#boundFocus);
|
|
2104
2035
|
this.input.removeEventListener("blur", this.#boundBlur);
|
|
2105
2036
|
this.input.addEventListener("blur", this.#boundBlur);
|
|
2037
|
+
this.input.removeEventListener("keydown", this.#boundKeyDown);
|
|
2038
|
+
this.input.addEventListener("keydown", this.#boundKeyDown);
|
|
2106
2039
|
});
|
|
2107
2040
|
}
|
|
2108
2041
|
|
|
@@ -2112,6 +2045,7 @@ class FigInputNumber extends HTMLElement {
|
|
|
2112
2045
|
this.input.removeEventListener("input", this.#boundInput);
|
|
2113
2046
|
this.input.removeEventListener("focus", this.#boundFocus);
|
|
2114
2047
|
this.input.removeEventListener("blur", this.#boundBlur);
|
|
2048
|
+
this.input.removeEventListener("keydown", this.#boundKeyDown);
|
|
2115
2049
|
}
|
|
2116
2050
|
this.removeEventListener("pointerdown", this.#boundMouseDown);
|
|
2117
2051
|
window.removeEventListener("pointermove", this.#boundMouseMove);
|
|
@@ -2203,6 +2137,35 @@ class FigInputNumber extends HTMLElement {
|
|
|
2203
2137
|
);
|
|
2204
2138
|
}
|
|
2205
2139
|
|
|
2140
|
+
#handleKeyDown(e) {
|
|
2141
|
+
if (this.disabled) return;
|
|
2142
|
+
|
|
2143
|
+
// Only handle arrow up/down
|
|
2144
|
+
if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
|
|
2145
|
+
|
|
2146
|
+
e.preventDefault();
|
|
2147
|
+
|
|
2148
|
+
const step = this.step || 1;
|
|
2149
|
+
// Shift multiplies step by 10
|
|
2150
|
+
const multiplier = e.shiftKey ? 10 : 1;
|
|
2151
|
+
const delta = step * multiplier * (e.key === "ArrowUp" ? 1 : -1);
|
|
2152
|
+
|
|
2153
|
+
let numericValue = this.#getNumericValue(this.input.value);
|
|
2154
|
+
let value =
|
|
2155
|
+
(numericValue !== "" ? Number(numericValue) / (this.transform || 1) : 0) +
|
|
2156
|
+
delta;
|
|
2157
|
+
value = this.#sanitizeInput(value, false);
|
|
2158
|
+
this.value = value;
|
|
2159
|
+
this.input.value = this.#formatWithUnit(this.value);
|
|
2160
|
+
|
|
2161
|
+
this.dispatchEvent(
|
|
2162
|
+
new CustomEvent("input", { detail: this.value, bubbles: true }),
|
|
2163
|
+
);
|
|
2164
|
+
this.dispatchEvent(
|
|
2165
|
+
new CustomEvent("change", { detail: this.value, bubbles: true }),
|
|
2166
|
+
);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2206
2169
|
#handleInput(e) {
|
|
2207
2170
|
let numericValue = this.#getNumericValue(e.target.value);
|
|
2208
2171
|
if (numericValue !== "") {
|
package/package.json
CHANGED