@assure-one/design-system 1.26.0 → 1.27.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/dist/index.js +118 -100
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18249,6 +18249,8 @@ var SEARCH_THRESHOLD = 8;
|
|
|
18249
18249
|
var HOVER_OPEN_MS = 90;
|
|
18250
18250
|
var HOVER_CLOSE_MS = 220;
|
|
18251
18251
|
var FLYOUT_WIDTH = 224;
|
|
18252
|
+
var MIN_FLYOUT_HEIGHT = 120;
|
|
18253
|
+
var VIEWPORT_MARGIN = 24;
|
|
18252
18254
|
var DEFAULT_GUTTER_PX = 24;
|
|
18253
18255
|
function DisplayMenu({
|
|
18254
18256
|
sections,
|
|
@@ -18265,7 +18267,8 @@ function DisplayMenu({
|
|
|
18265
18267
|
const [openKey, setOpenKey] = useState(null);
|
|
18266
18268
|
const [flyout, setFlyout] = useState({
|
|
18267
18269
|
top: 0,
|
|
18268
|
-
side: "left"
|
|
18270
|
+
side: "left",
|
|
18271
|
+
maxHeight: 0
|
|
18269
18272
|
});
|
|
18270
18273
|
const [panelShift, setPanelShift] = useState(0);
|
|
18271
18274
|
const [rootQuery, setRootQuery] = useState("");
|
|
@@ -18289,10 +18292,14 @@ function DisplayMenu({
|
|
|
18289
18292
|
if (!panel || !row) return;
|
|
18290
18293
|
const panelRect = panel.getBoundingClientRect();
|
|
18291
18294
|
const rowRect = row.getBoundingClientRect();
|
|
18292
|
-
const maxTop = Math.max(0, window.innerHeight - panelRect.top - 24 -
|
|
18295
|
+
const maxTop = Math.max(0, window.innerHeight - panelRect.top - 24 - MIN_FLYOUT_HEIGHT);
|
|
18293
18296
|
const top = Math.min(Math.max(rowRect.top - panelRect.top - 4, 0), maxTop);
|
|
18297
|
+
const maxHeight = Math.max(
|
|
18298
|
+
MIN_FLYOUT_HEIGHT,
|
|
18299
|
+
window.innerHeight - (panelRect.top + top) - VIEWPORT_MARGIN
|
|
18300
|
+
);
|
|
18294
18301
|
const side = panelRect.left >= FLYOUT_WIDTH + 16 ? "left" : "right";
|
|
18295
|
-
setFlyout({ top, side });
|
|
18302
|
+
setFlyout({ top, side, maxHeight });
|
|
18296
18303
|
}, []);
|
|
18297
18304
|
const openSection = useCallback(
|
|
18298
18305
|
(key) => {
|
|
@@ -18423,100 +18430,108 @@ function DisplayMenu({
|
|
|
18423
18430
|
}
|
|
18424
18431
|
)
|
|
18425
18432
|
] }),
|
|
18426
|
-
/* @__PURE__ */ jsx(
|
|
18427
|
-
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
{
|
|
18434
|
-
|
|
18435
|
-
|
|
18436
|
-
"
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
|
|
18447
|
-
|
|
18448
|
-
|
|
18449
|
-
|
|
18450
|
-
className: "shrink-0 text-muted-foreground",
|
|
18451
|
-
"
|
|
18452
|
-
|
|
18453
|
-
|
|
18454
|
-
|
|
18455
|
-
|
|
18456
|
-
|
|
18457
|
-
|
|
18458
|
-
`${section2.key}:${option.key}`
|
|
18459
|
-
);
|
|
18460
|
-
}
|
|
18461
|
-
const { section } = row;
|
|
18462
|
-
const count = section.selected.size;
|
|
18463
|
-
const valueLabel = section.summary ?? (section.mode === "single" ? section.options.find((o) => section.selected.has(o.key))?.label ?? "" : "");
|
|
18464
|
-
const isOpen = section.key === openKey;
|
|
18465
|
-
return (
|
|
18466
|
-
/* Hover handlers sit on the wrapper so the cursor can cross
|
|
18467
|
-
* the gap to `section.trailing` without closing the flyout.
|
|
18468
|
-
* The wrapper is not itself a control — the button inside is,
|
|
18469
|
-
* and it carries the keyboard equivalent (ArrowRight / Enter /
|
|
18470
|
-
* Space open the same flyout). Nothing here is mouse-only. */
|
|
18471
|
-
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
18472
|
-
/* @__PURE__ */ jsxs(
|
|
18473
|
-
"div",
|
|
18474
|
-
{
|
|
18475
|
-
ref: (el) => {
|
|
18476
|
-
if (el) rowRefs.current.set(section.key, el);
|
|
18477
|
-
else rowRefs.current.delete(section.key);
|
|
18478
|
-
},
|
|
18479
|
-
className: "flex items-center gap-0.5",
|
|
18480
|
-
onMouseEnter: () => scheduleOpen(section.key),
|
|
18481
|
-
onMouseLeave: scheduleClose,
|
|
18482
|
-
children: [
|
|
18483
|
-
/* @__PURE__ */ jsxs(
|
|
18484
|
-
"button",
|
|
18485
|
-
{
|
|
18486
|
-
type: "button",
|
|
18487
|
-
role: "menuitem",
|
|
18488
|
-
"aria-haspopup": "menu",
|
|
18489
|
-
"aria-expanded": isOpen,
|
|
18490
|
-
onClick: () => openSection(section.key),
|
|
18491
|
-
onKeyDown: (e) => {
|
|
18492
|
-
if (e.key === "ArrowRight" || e.key === "Enter" || e.key === " ") {
|
|
18493
|
-
e.preventDefault();
|
|
18494
|
-
openSection(section.key);
|
|
18495
|
-
requestAnimationFrame(
|
|
18496
|
-
() => flyoutRef.current?.querySelector("input, [role='menuitemcheckbox'], [role='menuitemradio']")?.focus()
|
|
18497
|
-
);
|
|
18433
|
+
/* @__PURE__ */ jsx(
|
|
18434
|
+
"div",
|
|
18435
|
+
{
|
|
18436
|
+
role: "menu",
|
|
18437
|
+
"aria-label": triggerLabel,
|
|
18438
|
+
className: "scrollbar-thin max-h-[min(32rem,70vh)] overflow-y-auto p-1",
|
|
18439
|
+
children: rootRows.length === 0 ? /* @__PURE__ */ jsx(EmptyRow, {}) : rootRows.map((row) => {
|
|
18440
|
+
if (row.kind === "option") {
|
|
18441
|
+
const { section: section2, option } = row;
|
|
18442
|
+
const isActive = section2.selected.has(option.key);
|
|
18443
|
+
const isMulti = section2.mode === "multi";
|
|
18444
|
+
return /* @__PURE__ */ jsxs(
|
|
18445
|
+
"button",
|
|
18446
|
+
{
|
|
18447
|
+
type: "button",
|
|
18448
|
+
role: isMulti ? "menuitemcheckbox" : "menuitemradio",
|
|
18449
|
+
"aria-checked": isActive,
|
|
18450
|
+
onMouseEnter: () => {
|
|
18451
|
+
clearTimers();
|
|
18452
|
+
setOpenKey(null);
|
|
18453
|
+
},
|
|
18454
|
+
onClick: () => section2.onSelect(option.key),
|
|
18455
|
+
className: "flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-left text-[13px] transition-colors hover:bg-muted/60 focus-visible:bg-muted/60 focus-visible:outline-none",
|
|
18456
|
+
children: [
|
|
18457
|
+
section2.icon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", "aria-hidden": "true", children: section2.icon }),
|
|
18458
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 truncate text-muted-foreground", children: section2.label }),
|
|
18459
|
+
/* @__PURE__ */ jsx(
|
|
18460
|
+
ChevronRightIcon,
|
|
18461
|
+
{
|
|
18462
|
+
size: 12,
|
|
18463
|
+
className: "shrink-0 text-muted-foreground",
|
|
18464
|
+
"aria-hidden": "true"
|
|
18498
18465
|
}
|
|
18499
|
-
},
|
|
18500
|
-
className: cn(
|
|
18501
|
-
"flex min-w-0 flex-1 items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] text-foreground transition-colors hover:bg-muted/60 focus-visible:bg-muted/60 focus-visible:outline-none",
|
|
18502
|
-
isOpen && "bg-muted/60"
|
|
18503
18466
|
),
|
|
18504
|
-
children:
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
|
|
18515
|
-
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18467
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-foreground", children: option.label }),
|
|
18468
|
+
isActive && /* @__PURE__ */ jsx(CheckIcon, { size: 14, className: "shrink-0 text-brand" })
|
|
18469
|
+
]
|
|
18470
|
+
},
|
|
18471
|
+
`${section2.key}:${option.key}`
|
|
18472
|
+
);
|
|
18473
|
+
}
|
|
18474
|
+
const { section } = row;
|
|
18475
|
+
const count = section.selected.size;
|
|
18476
|
+
const valueLabel = section.summary ?? (section.mode === "single" ? section.options.find((o) => section.selected.has(o.key))?.label ?? "" : "");
|
|
18477
|
+
const isOpen = section.key === openKey;
|
|
18478
|
+
return (
|
|
18479
|
+
/* Hover handlers sit on the wrapper so the cursor can cross
|
|
18480
|
+
* the gap to `section.trailing` without closing the flyout.
|
|
18481
|
+
* The wrapper is not itself a control — the button inside is,
|
|
18482
|
+
* and it carries the keyboard equivalent (ArrowRight / Enter /
|
|
18483
|
+
* Space open the same flyout). Nothing here is mouse-only. */
|
|
18484
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
18485
|
+
/* @__PURE__ */ jsxs(
|
|
18486
|
+
"div",
|
|
18487
|
+
{
|
|
18488
|
+
ref: (el) => {
|
|
18489
|
+
if (el) rowRefs.current.set(section.key, el);
|
|
18490
|
+
else rowRefs.current.delete(section.key);
|
|
18491
|
+
},
|
|
18492
|
+
className: "flex items-center gap-0.5",
|
|
18493
|
+
onMouseEnter: () => scheduleOpen(section.key),
|
|
18494
|
+
onMouseLeave: scheduleClose,
|
|
18495
|
+
children: [
|
|
18496
|
+
/* @__PURE__ */ jsxs(
|
|
18497
|
+
"button",
|
|
18498
|
+
{
|
|
18499
|
+
type: "button",
|
|
18500
|
+
role: "menuitem",
|
|
18501
|
+
"aria-haspopup": "menu",
|
|
18502
|
+
"aria-expanded": isOpen,
|
|
18503
|
+
onClick: () => openSection(section.key),
|
|
18504
|
+
onKeyDown: (e) => {
|
|
18505
|
+
if (e.key === "ArrowRight" || e.key === "Enter" || e.key === " ") {
|
|
18506
|
+
e.preventDefault();
|
|
18507
|
+
openSection(section.key);
|
|
18508
|
+
requestAnimationFrame(
|
|
18509
|
+
() => flyoutRef.current?.querySelector("input, [role='menuitemcheckbox'], [role='menuitemradio']")?.focus()
|
|
18510
|
+
);
|
|
18511
|
+
}
|
|
18512
|
+
},
|
|
18513
|
+
className: cn(
|
|
18514
|
+
"flex min-w-0 flex-1 items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] text-foreground transition-colors hover:bg-muted/60 focus-visible:bg-muted/60 focus-visible:outline-none",
|
|
18515
|
+
isOpen && "bg-muted/60"
|
|
18516
|
+
),
|
|
18517
|
+
children: [
|
|
18518
|
+
section.icon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", "aria-hidden": "true", children: section.icon }),
|
|
18519
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: section.label }),
|
|
18520
|
+
section.mode === "multi" && count > 0 && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-brand-bg px-1.5 text-[11px] font-medium text-brand", children: count }),
|
|
18521
|
+
section.mode !== "multi" && valueLabel && /* @__PURE__ */ jsx("span", { className: "max-w-24 shrink-0 truncate text-[13px] text-muted-foreground", children: valueLabel }),
|
|
18522
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { size: 13, className: "shrink-0 text-muted-foreground" })
|
|
18523
|
+
]
|
|
18524
|
+
}
|
|
18525
|
+
),
|
|
18526
|
+
section.trailing
|
|
18527
|
+
]
|
|
18528
|
+
},
|
|
18529
|
+
section.key
|
|
18530
|
+
)
|
|
18531
|
+
);
|
|
18532
|
+
})
|
|
18533
|
+
}
|
|
18534
|
+
),
|
|
18520
18535
|
/* @__PURE__ */ jsx("div", { className: "border-t border-border p-1", children: /* @__PURE__ */ jsxs(
|
|
18521
18536
|
Button,
|
|
18522
18537
|
{
|
|
@@ -18538,9 +18553,12 @@ function DisplayMenu({
|
|
|
18538
18553
|
role: "menu",
|
|
18539
18554
|
"aria-label": activeSection.label,
|
|
18540
18555
|
tabIndex: -1,
|
|
18541
|
-
style: { top: flyout.top, width: FLYOUT_WIDTH },
|
|
18556
|
+
style: { top: flyout.top, width: FLYOUT_WIDTH, maxHeight: flyout.maxHeight },
|
|
18542
18557
|
className: cn(
|
|
18543
|
-
|
|
18558
|
+
// Column + overflow-hidden so the option list (the only flexible
|
|
18559
|
+
// part) absorbs the height cap, while the search box and Clear
|
|
18560
|
+
// footer stay pinned and fully visible.
|
|
18561
|
+
"absolute z-50 flex flex-col overflow-hidden rounded-lg border border-border bg-popover shadow-md",
|
|
18544
18562
|
// -mx-1 lets the flyout tuck against the panel so there's no
|
|
18545
18563
|
// dead gap for the cursor to fall through on the way over.
|
|
18546
18564
|
flyout.side === "left" ? "right-full -mr-1" : "left-full -ml-1"
|
|
@@ -18548,7 +18566,7 @@ function DisplayMenu({
|
|
|
18548
18566
|
onMouseEnter: clearTimers,
|
|
18549
18567
|
onMouseLeave: scheduleClose,
|
|
18550
18568
|
children: [
|
|
18551
|
-
showFlyoutSearch && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 border-b border-border px-2.5 py-1.5", children: [
|
|
18569
|
+
showFlyoutSearch && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5 border-b border-border px-2.5 py-1.5", children: [
|
|
18552
18570
|
/* @__PURE__ */ jsx(SearchIcon, { size: 13, className: "shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
18553
18571
|
/* @__PURE__ */ jsx(
|
|
18554
18572
|
"input",
|
|
@@ -18562,7 +18580,7 @@ function DisplayMenu({
|
|
|
18562
18580
|
}
|
|
18563
18581
|
)
|
|
18564
18582
|
] }),
|
|
18565
|
-
/* @__PURE__ */ jsx("div", { className: "max-h-
|
|
18583
|
+
/* @__PURE__ */ jsx("div", { className: "scrollbar-thin min-h-0 flex-1 max-h-[min(24rem,60vh)] overflow-y-auto p-1", children: activeSection.content ? (
|
|
18566
18584
|
/* Consumer-supplied controls (date range, numeric bound).
|
|
18567
18585
|
* Rendered raw — the section owns its own labelling and
|
|
18568
18586
|
* layout; the flyout only provides the surface. */
|
|
@@ -18615,7 +18633,7 @@ function DisplayMenu({
|
|
|
18615
18633
|
option.key
|
|
18616
18634
|
);
|
|
18617
18635
|
}) }),
|
|
18618
|
-
activeSection.mode === "multi" && activeSection.selected.size > 0 && activeSection.onClear && /* @__PURE__ */ jsx("div", { className: "border-t border-border p-1", children: /* @__PURE__ */ jsxs(
|
|
18636
|
+
activeSection.mode === "multi" && activeSection.selected.size > 0 && activeSection.onClear && /* @__PURE__ */ jsx("div", { className: "shrink-0 border-t border-border p-1", children: /* @__PURE__ */ jsxs(
|
|
18619
18637
|
Button,
|
|
18620
18638
|
{
|
|
18621
18639
|
variant: "ghost",
|