@bigtablet/design-system 1.15.0 → 1.16.1
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/dist/index.css +11 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +106 -96
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -683,6 +683,17 @@
|
|
|
683
683
|
overflow-x: hidden;
|
|
684
684
|
padding: 0.25rem 0;
|
|
685
685
|
}
|
|
686
|
+
.select_list_up {
|
|
687
|
+
top: auto;
|
|
688
|
+
bottom: 100%;
|
|
689
|
+
margin-top: 0;
|
|
690
|
+
margin-bottom: 0.25rem;
|
|
691
|
+
}
|
|
692
|
+
.select_list_portal {
|
|
693
|
+
position: fixed;
|
|
694
|
+
margin-top: 0;
|
|
695
|
+
margin-bottom: 0;
|
|
696
|
+
}
|
|
686
697
|
.select_option {
|
|
687
698
|
width: 100%;
|
|
688
699
|
box-sizing: border-box;
|
package/dist/index.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ interface SelectProps {
|
|
|
109
109
|
className?: string;
|
|
110
110
|
textAlign?: "left" | "center";
|
|
111
111
|
}
|
|
112
|
-
declare const Select: ({ id, label, placeholder, options, value, onChange, defaultValue, disabled, size, variant, fullWidth, className, textAlign }: SelectProps) => react_jsx_runtime.JSX.Element;
|
|
112
|
+
declare const Select: ({ id, label, placeholder, options, value, onChange, defaultValue, disabled, size, variant, fullWidth, className, textAlign, }: SelectProps) => react_jsx_runtime.JSX.Element;
|
|
113
113
|
|
|
114
114
|
interface SwitchProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange"> {
|
|
115
115
|
checked?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -315,7 +315,11 @@ var Select = ({
|
|
|
315
315
|
const currentValue = isControlled ? value ?? null : internalValue;
|
|
316
316
|
const [isOpen, setIsOpen] = React3.useState(false);
|
|
317
317
|
const [activeIndex, setActiveIndex] = React3.useState(-1);
|
|
318
|
+
const [dropUp, setDropUp] = React3.useState(false);
|
|
319
|
+
const [listPosition, setListPosition] = React3.useState({ top: 0, left: 0, width: 0 });
|
|
318
320
|
const wrapperRef = React3.useRef(null);
|
|
321
|
+
const controlRef = React3.useRef(null);
|
|
322
|
+
const listRef = React3.useRef(null);
|
|
319
323
|
const currentOption = React3.useMemo(
|
|
320
324
|
() => options.find((o) => o.value === currentValue) ?? null,
|
|
321
325
|
[options, currentValue]
|
|
@@ -330,10 +334,10 @@ var Select = ({
|
|
|
330
334
|
);
|
|
331
335
|
React3.useEffect(() => {
|
|
332
336
|
const onDocClick = (e) => {
|
|
333
|
-
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
|
|
337
|
+
const target = e.target;
|
|
338
|
+
if (wrapperRef.current?.contains(target)) return;
|
|
339
|
+
if (listRef.current?.contains(target)) return;
|
|
340
|
+
setIsOpen(false);
|
|
337
341
|
};
|
|
338
342
|
document.addEventListener("mousedown", onDocClick);
|
|
339
343
|
return () => document.removeEventListener("mousedown", onDocClick);
|
|
@@ -381,9 +385,7 @@ var Select = ({
|
|
|
381
385
|
case "Home":
|
|
382
386
|
e.preventDefault();
|
|
383
387
|
setIsOpen(true);
|
|
384
|
-
setActiveIndex(
|
|
385
|
-
options.findIndex((o) => !o.disabled)
|
|
386
|
-
);
|
|
388
|
+
setActiveIndex(options.findIndex((o) => !o.disabled));
|
|
387
389
|
break;
|
|
388
390
|
case "End":
|
|
389
391
|
e.preventDefault();
|
|
@@ -403,16 +405,36 @@ var Select = ({
|
|
|
403
405
|
};
|
|
404
406
|
React3.useEffect(() => {
|
|
405
407
|
if (!isOpen) return;
|
|
406
|
-
const idx = options.findIndex(
|
|
407
|
-
|
|
408
|
-
);
|
|
409
|
-
setActiveIndex(
|
|
410
|
-
idx >= 0 ? idx : Math.max(
|
|
411
|
-
0,
|
|
412
|
-
options.findIndex((o) => !o.disabled)
|
|
413
|
-
)
|
|
414
|
-
);
|
|
408
|
+
const idx = options.findIndex((o) => o.value === currentValue && !o.disabled);
|
|
409
|
+
setActiveIndex(idx >= 0 ? idx : Math.max(0, options.findIndex((o) => !o.disabled)));
|
|
415
410
|
}, [isOpen, options, currentValue]);
|
|
411
|
+
const updatePosition = React3.useCallback(() => {
|
|
412
|
+
if (!controlRef.current) return;
|
|
413
|
+
const rect = controlRef.current.getBoundingClientRect();
|
|
414
|
+
const listHeight = Math.min(options.length * 40, 288);
|
|
415
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
416
|
+
const spaceAbove = rect.top;
|
|
417
|
+
const shouldDropUp = spaceBelow < listHeight && spaceAbove > spaceBelow;
|
|
418
|
+
setDropUp(shouldDropUp);
|
|
419
|
+
setListPosition({
|
|
420
|
+
top: shouldDropUp ? rect.top - listHeight - 4 : rect.bottom + 4,
|
|
421
|
+
left: rect.left,
|
|
422
|
+
width: rect.width
|
|
423
|
+
});
|
|
424
|
+
}, [options.length]);
|
|
425
|
+
React3.useLayoutEffect(() => {
|
|
426
|
+
if (!isOpen) return;
|
|
427
|
+
updatePosition();
|
|
428
|
+
}, [isOpen, updatePosition]);
|
|
429
|
+
React3.useEffect(() => {
|
|
430
|
+
if (!isOpen) return;
|
|
431
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
432
|
+
window.addEventListener("resize", updatePosition);
|
|
433
|
+
return () => {
|
|
434
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
435
|
+
window.removeEventListener("resize", updatePosition);
|
|
436
|
+
};
|
|
437
|
+
}, [isOpen, updatePosition]);
|
|
416
438
|
const rootClassName = ["select", className ?? ""].filter(Boolean).join(" ");
|
|
417
439
|
const controlClassName = [
|
|
418
440
|
"select_control",
|
|
@@ -421,92 +443,80 @@ var Select = ({
|
|
|
421
443
|
isOpen && "is_open",
|
|
422
444
|
disabled && "is_disabled"
|
|
423
445
|
].filter(Boolean).join(" ");
|
|
424
|
-
|
|
425
|
-
"
|
|
446
|
+
const renderList = () => /* @__PURE__ */ jsx(
|
|
447
|
+
"ul",
|
|
426
448
|
{
|
|
427
|
-
ref:
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
449
|
+
ref: listRef,
|
|
450
|
+
id: `${selectId}_listbox`,
|
|
451
|
+
role: "listbox",
|
|
452
|
+
className: `select_list select_list_portal${dropUp ? " select_list_up" : ""}`,
|
|
453
|
+
style: {
|
|
454
|
+
position: "fixed",
|
|
455
|
+
top: listPosition.top,
|
|
456
|
+
left: listPosition.left,
|
|
457
|
+
width: listPosition.width
|
|
458
|
+
},
|
|
459
|
+
children: options.map((opt, i) => {
|
|
460
|
+
const selected = currentValue === opt.value;
|
|
461
|
+
const active = i === activeIndex;
|
|
462
|
+
const optionClassName = [
|
|
463
|
+
"select_option",
|
|
464
|
+
selected && "is_selected",
|
|
465
|
+
active && "is_active",
|
|
466
|
+
opt.disabled && "is_disabled"
|
|
467
|
+
].filter(Boolean).join(" ");
|
|
468
|
+
return /* @__PURE__ */ jsxs(
|
|
469
|
+
"li",
|
|
441
470
|
{
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
className:
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
471
|
+
role: "option",
|
|
472
|
+
"aria-selected": selected,
|
|
473
|
+
className: optionClassName,
|
|
474
|
+
onMouseEnter: () => !opt.disabled && setActiveIndex(i),
|
|
475
|
+
onClick: () => {
|
|
476
|
+
if (opt.disabled) return;
|
|
477
|
+
setValue(opt.value);
|
|
478
|
+
setIsOpen(false);
|
|
479
|
+
},
|
|
451
480
|
children: [
|
|
452
|
-
/* @__PURE__ */ jsx(
|
|
453
|
-
|
|
454
|
-
{
|
|
455
|
-
className: currentOption ? "select_value" : "select_placeholder",
|
|
456
|
-
style: textAlign === "left" ? { textAlign: "start" } : void 0,
|
|
457
|
-
children: currentOption ? currentOption.label : placeholder
|
|
458
|
-
}
|
|
459
|
-
),
|
|
460
|
-
/* @__PURE__ */ jsx("span", { className: "select_icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { size: 16 }) })
|
|
481
|
+
/* @__PURE__ */ jsx("span", { children: opt.label }),
|
|
482
|
+
selected && /* @__PURE__ */ jsx(Check, { size: 16, "aria-hidden": "true" })
|
|
461
483
|
]
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
{
|
|
467
|
-
id: `${selectId}_listbox`,
|
|
468
|
-
role: "listbox",
|
|
469
|
-
className: "select_list",
|
|
470
|
-
children: options.map((opt, i) => {
|
|
471
|
-
const selected = currentValue === opt.value;
|
|
472
|
-
const active = i === activeIndex;
|
|
473
|
-
const optionClassName = [
|
|
474
|
-
"select_option",
|
|
475
|
-
selected && "is_selected",
|
|
476
|
-
active && "is_active",
|
|
477
|
-
opt.disabled && "is_disabled"
|
|
478
|
-
].filter(Boolean).join(" ");
|
|
479
|
-
return /* @__PURE__ */ jsxs(
|
|
480
|
-
"li",
|
|
481
|
-
{
|
|
482
|
-
role: "option",
|
|
483
|
-
"aria-selected": selected,
|
|
484
|
-
className: optionClassName,
|
|
485
|
-
onMouseEnter: () => !opt.disabled && setActiveIndex(i),
|
|
486
|
-
onClick: () => {
|
|
487
|
-
if (opt.disabled) return;
|
|
488
|
-
setValue(opt.value);
|
|
489
|
-
setIsOpen(false);
|
|
490
|
-
},
|
|
491
|
-
children: [
|
|
492
|
-
/* @__PURE__ */ jsx("span", { children: opt.label }),
|
|
493
|
-
selected && /* @__PURE__ */ jsx(
|
|
494
|
-
Check,
|
|
495
|
-
{
|
|
496
|
-
size: 16,
|
|
497
|
-
"aria-hidden": "true"
|
|
498
|
-
}
|
|
499
|
-
)
|
|
500
|
-
]
|
|
501
|
-
},
|
|
502
|
-
opt.value
|
|
503
|
-
);
|
|
504
|
-
})
|
|
505
|
-
}
|
|
506
|
-
)
|
|
507
|
-
]
|
|
484
|
+
},
|
|
485
|
+
opt.value
|
|
486
|
+
);
|
|
487
|
+
})
|
|
508
488
|
}
|
|
509
489
|
);
|
|
490
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: rootClassName, style: fullWidth ? { width: "100%" } : void 0, children: [
|
|
491
|
+
label && /* @__PURE__ */ jsx("label", { htmlFor: selectId, className: "select_label", children: label }),
|
|
492
|
+
/* @__PURE__ */ jsxs(
|
|
493
|
+
"button",
|
|
494
|
+
{
|
|
495
|
+
ref: controlRef,
|
|
496
|
+
id: selectId,
|
|
497
|
+
type: "button",
|
|
498
|
+
className: controlClassName,
|
|
499
|
+
"aria-haspopup": "listbox",
|
|
500
|
+
"aria-expanded": isOpen,
|
|
501
|
+
"aria-controls": `${selectId}_listbox`,
|
|
502
|
+
onClick: () => !disabled && setIsOpen((o) => !o),
|
|
503
|
+
onKeyDown,
|
|
504
|
+
disabled,
|
|
505
|
+
children: [
|
|
506
|
+
/* @__PURE__ */ jsx(
|
|
507
|
+
"span",
|
|
508
|
+
{
|
|
509
|
+
className: currentOption ? "select_value" : "select_placeholder",
|
|
510
|
+
style: textAlign === "left" ? { textAlign: "start" } : void 0,
|
|
511
|
+
children: currentOption ? currentOption.label : placeholder
|
|
512
|
+
}
|
|
513
|
+
),
|
|
514
|
+
/* @__PURE__ */ jsx("span", { className: "select_icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { size: 16 }) })
|
|
515
|
+
]
|
|
516
|
+
}
|
|
517
|
+
),
|
|
518
|
+
isOpen && typeof document !== "undefined" && createPortal(renderList(), document.body)
|
|
519
|
+
] });
|
|
510
520
|
};
|
|
511
521
|
var Switch = ({
|
|
512
522
|
checked,
|