@dimaan/ui 0.0.29 → 0.0.31
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.cjs +227 -220
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +227 -220
- package/dist/index.js.map +1 -1
- package/dist/preset.css +23 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -372,7 +372,7 @@ function DashboardMain({ className, children, ...props }) {
|
|
|
372
372
|
// stretching the whole layout past 100%.
|
|
373
373
|
"flex min-h-screen min-w-0 flex-1 flex-col transition-[margin] duration-200 ease-out",
|
|
374
374
|
// On desktop, push the main column past the fixed sidebar using logical margin.
|
|
375
|
-
collapsed ? "lg:ms-
|
|
375
|
+
collapsed ? "lg:ms-0" : "lg:ms-(--sidebar-width)",
|
|
376
376
|
className
|
|
377
377
|
),
|
|
378
378
|
...props,
|
|
@@ -541,14 +541,16 @@ function Sidebar({ className, children, ...props }) {
|
|
|
541
541
|
"fixed inset-y-0 start-0 z-40 flex flex-col",
|
|
542
542
|
// Surface
|
|
543
543
|
"bg-sidebar text-sidebar-foreground border-e border-sidebar-border",
|
|
544
|
-
// Sizing — width
|
|
545
|
-
|
|
544
|
+
// Sizing — always full width; collapse hides it off-canvas (below).
|
|
545
|
+
"w-[var(--sidebar-width)]",
|
|
546
546
|
// Motion
|
|
547
|
-
"transition-
|
|
548
|
-
// Mobile slide
|
|
549
|
-
//
|
|
550
|
-
|
|
551
|
-
|
|
547
|
+
"transition-transform duration-200 ease-out",
|
|
548
|
+
// Mobile: slide in/out via mobileOpen. Logical translate (rtl variant)
|
|
549
|
+
// so it slides off the inline-start edge in both LTR and RTL.
|
|
550
|
+
mobileOpen ? "translate-x-0" : "-translate-x-full rtl:translate-x-full",
|
|
551
|
+
// Desktop: collapse fully hides the sidebar off-canvas; the header
|
|
552
|
+
// trigger slides it back in and the main content reclaims the width.
|
|
553
|
+
collapsed ? "lg:-translate-x-full lg:rtl:translate-x-full" : "lg:translate-x-0 lg:rtl:translate-x-0",
|
|
552
554
|
className
|
|
553
555
|
),
|
|
554
556
|
...props,
|
|
@@ -571,18 +573,8 @@ function SidebarFooter({ className, children, ...props }) {
|
|
|
571
573
|
);
|
|
572
574
|
}
|
|
573
575
|
function SidebarGroup({ label, className, children, ...props }) {
|
|
574
|
-
const { collapsed } = useDashboardLayout();
|
|
575
576
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1 py-2", className), ...props, children: [
|
|
576
|
-
label ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
577
|
-
"div",
|
|
578
|
-
{
|
|
579
|
-
className: cn(
|
|
580
|
-
"px-3 pb-1 text-xs font-medium uppercase tracking-wider text-muted-foreground transition-opacity",
|
|
581
|
-
collapsed && "pointer-events-none h-0 overflow-hidden opacity-0"
|
|
582
|
-
),
|
|
583
|
-
children: label
|
|
584
|
-
}
|
|
585
|
-
) : null,
|
|
577
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-1 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: label }) : null,
|
|
586
578
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children })
|
|
587
579
|
] });
|
|
588
580
|
}
|
|
@@ -616,7 +608,6 @@ function SidebarNavGroup({
|
|
|
616
608
|
onClick,
|
|
617
609
|
...props
|
|
618
610
|
}) {
|
|
619
|
-
const { collapsed } = useDashboardLayout();
|
|
620
611
|
const submenuId = react.useId();
|
|
621
612
|
const [internalOpen, setInternalOpen] = react.useState(defaultOpen);
|
|
622
613
|
const isControlled = openProp !== void 0;
|
|
@@ -643,27 +634,23 @@ function SidebarNavGroup({
|
|
|
643
634
|
const isActive = active || hasActiveChild;
|
|
644
635
|
const prevHasActiveChild = react.useRef(false);
|
|
645
636
|
react.useEffect(() => {
|
|
646
|
-
if (hasActiveChild && !prevHasActiveChild.current
|
|
637
|
+
if (hasActiveChild && !prevHasActiveChild.current) {
|
|
647
638
|
setOpen(true);
|
|
648
639
|
}
|
|
649
640
|
prevHasActiveChild.current = hasActiveChild;
|
|
650
|
-
}, [hasActiveChild,
|
|
651
|
-
|
|
652
|
-
if (collapsed && open) setOpen(false);
|
|
653
|
-
}, [collapsed, open, setOpen]);
|
|
654
|
-
const titleAttr = collapsed && typeof label === "string" ? label : props.title ?? void 0;
|
|
655
|
-
const showChildren = !collapsed;
|
|
641
|
+
}, [hasActiveChild, setOpen]);
|
|
642
|
+
const titleAttr = props.title ?? void 0;
|
|
656
643
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 flex-col", children: [
|
|
657
644
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
658
645
|
"button",
|
|
659
646
|
{
|
|
660
647
|
type: "button",
|
|
661
|
-
"aria-expanded":
|
|
662
|
-
"aria-controls":
|
|
648
|
+
"aria-expanded": open,
|
|
649
|
+
"aria-controls": submenuId,
|
|
663
650
|
"data-active": isActive ? "true" : void 0,
|
|
664
651
|
title: titleAttr,
|
|
665
652
|
onClick: (e) => {
|
|
666
|
-
|
|
653
|
+
setOpen(!open);
|
|
667
654
|
onClick?.(e);
|
|
668
655
|
},
|
|
669
656
|
className: cn(
|
|
@@ -671,7 +658,6 @@ function SidebarNavGroup({
|
|
|
671
658
|
"text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
672
659
|
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-sidebar",
|
|
673
660
|
isActive && "bg-sidebar-accent text-sidebar-accent-foreground",
|
|
674
|
-
collapsed && "justify-center px-0",
|
|
675
661
|
className
|
|
676
662
|
),
|
|
677
663
|
...props,
|
|
@@ -684,18 +670,9 @@ function SidebarNavGroup({
|
|
|
684
670
|
}
|
|
685
671
|
) : null,
|
|
686
672
|
icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "flex size-5 shrink-0 items-center justify-center", children: icon }) : null,
|
|
687
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
className: cn(
|
|
691
|
-
"flex-1 truncate text-start transition-[opacity,width]",
|
|
692
|
-
collapsed && "pointer-events-none w-0 opacity-0"
|
|
693
|
-
),
|
|
694
|
-
children: label
|
|
695
|
-
}
|
|
696
|
-
),
|
|
697
|
-
endSlot && !collapsed ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center", children: endSlot }) : null,
|
|
698
|
-
showChildren ? /* @__PURE__ */ jsxRuntime.jsx(ChevronCaret, { open }) : null
|
|
673
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-start", children: label }),
|
|
674
|
+
endSlot ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center", children: endSlot }) : null,
|
|
675
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChevronCaret, { open })
|
|
699
676
|
]
|
|
700
677
|
}
|
|
701
678
|
),
|
|
@@ -703,10 +680,10 @@ function SidebarNavGroup({
|
|
|
703
680
|
"div",
|
|
704
681
|
{
|
|
705
682
|
id: submenuId,
|
|
706
|
-
hidden: !
|
|
683
|
+
hidden: !open,
|
|
707
684
|
className: cn(
|
|
708
685
|
"grid transition-[grid-template-rows] duration-200 ease-out",
|
|
709
|
-
|
|
686
|
+
open ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
|
|
710
687
|
),
|
|
711
688
|
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5 ps-7 pt-1", children: /* @__PURE__ */ jsxRuntime.jsx(SidebarNavGroupContext.Provider, { value: contextValue, children }) }) })
|
|
712
689
|
}
|
|
@@ -737,7 +714,6 @@ function SidebarNavItem({
|
|
|
737
714
|
end,
|
|
738
715
|
...props
|
|
739
716
|
}) {
|
|
740
|
-
const { collapsed } = useDashboardLayout();
|
|
741
717
|
const resolved = reactRouterDom.useResolvedPath(to);
|
|
742
718
|
const group = react.useContext(SidebarNavGroupContext);
|
|
743
719
|
const itemId = react.useId();
|
|
@@ -749,13 +725,12 @@ function SidebarNavItem({
|
|
|
749
725
|
return () => group.reportActive(itemId, false);
|
|
750
726
|
}, [group, itemId, isActive]);
|
|
751
727
|
const labelContent = label ?? children;
|
|
752
|
-
const titleAttr =
|
|
728
|
+
const titleAttr = props.title;
|
|
753
729
|
const getClassName = (active) => cn(
|
|
754
730
|
"group relative flex h-9 shrink-0 items-center gap-3 rounded-md px-3 text-sm font-medium outline-none transition-colors",
|
|
755
731
|
"text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
756
732
|
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-sidebar",
|
|
757
733
|
active && "bg-sidebar-accent text-sidebar-accent-foreground",
|
|
758
|
-
collapsed && "justify-center px-0",
|
|
759
734
|
className
|
|
760
735
|
);
|
|
761
736
|
const innerContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -767,17 +742,8 @@ function SidebarNavItem({
|
|
|
767
742
|
}
|
|
768
743
|
) : null,
|
|
769
744
|
icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "flex size-5 shrink-0 items-center justify-center", children: icon }) : null,
|
|
770
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
771
|
-
|
|
772
|
-
{
|
|
773
|
-
className: cn(
|
|
774
|
-
"flex-1 truncate text-start transition-[opacity,width]",
|
|
775
|
-
collapsed && "pointer-events-none w-0 opacity-0"
|
|
776
|
-
),
|
|
777
|
-
children: labelContent
|
|
778
|
-
}
|
|
779
|
-
),
|
|
780
|
-
endSlot && !collapsed ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ms-auto flex shrink-0 items-center", children: endSlot }) : null
|
|
745
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-start", children: labelContent }),
|
|
746
|
+
endSlot ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ms-auto flex shrink-0 items-center", children: endSlot }) : null
|
|
781
747
|
] });
|
|
782
748
|
if (render) {
|
|
783
749
|
return render({
|
|
@@ -939,7 +905,7 @@ var badgeDotSizeClass = {
|
|
|
939
905
|
md: "size-2"
|
|
940
906
|
};
|
|
941
907
|
var badgeBaseClass = "inline-flex shrink-0 items-center rounded-full border font-medium leading-none whitespace-nowrap select-none transition-colors";
|
|
942
|
-
var Badge = react.forwardRef(function Badge2({ variant = "default", size = "md", tone = "
|
|
908
|
+
var Badge = react.forwardRef(function Badge2({ variant = "default", size = "md", tone = "soft", dot = false, className, children, ...props }, ref) {
|
|
943
909
|
const variantClass = tone === "soft" ? badgeSoftVariantClass[variant] : badgeVariantClass[variant];
|
|
944
910
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
945
911
|
"span",
|
|
@@ -2355,9 +2321,9 @@ function Pagination({
|
|
|
2355
2321
|
children: isRtl ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": "true", className: "size-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { "aria-hidden": "true", className: "size-3.5" })
|
|
2356
2322
|
}
|
|
2357
2323
|
),
|
|
2358
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2359
|
-
|
|
2360
|
-
"
|
|
2324
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-7 items-center justify-center rounded-lg bg-gradient-table px-2.5 py-0.5 text-xs font-semibold text-white", children: pageIndex + 1 }),
|
|
2325
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-0.5 text-muted-foreground", children: [
|
|
2326
|
+
"/ ",
|
|
2361
2327
|
pageCount
|
|
2362
2328
|
] }),
|
|
2363
2329
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2382,7 +2348,7 @@ function Toolbar({ count, onClear, renderLabel, clearLabel, children }) {
|
|
|
2382
2348
|
{
|
|
2383
2349
|
role: "toolbar",
|
|
2384
2350
|
"aria-label": "Bulk actions",
|
|
2385
|
-
className: "flex flex-wrap items-center gap-3 rounded-
|
|
2351
|
+
className: "flex flex-wrap items-center gap-3 rounded-xl border border-border bg-muted/50 px-3.5 py-2.5 text-sm shadow-[var(--shadow-xs)]",
|
|
2386
2352
|
children: [
|
|
2387
2353
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: renderLabel ? renderLabel(count) : `${count} selected` }),
|
|
2388
2354
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ms-auto flex flex-wrap items-center gap-2", children: [
|
|
@@ -2398,18 +2364,18 @@ function Toolbar({ count, onClear, renderLabel, clearLabel, children }) {
|
|
|
2398
2364
|
var tableSizeClass = {
|
|
2399
2365
|
sm: {
|
|
2400
2366
|
row: "",
|
|
2401
|
-
cell: "px-3 py-
|
|
2402
|
-
head: "whitespace-nowrap px-3 py-
|
|
2367
|
+
cell: "px-3 py-2 text-xs tabular-nums",
|
|
2368
|
+
head: "whitespace-nowrap px-3 py-3 text-[11px] font-semibold uppercase tracking-wider"
|
|
2403
2369
|
},
|
|
2404
2370
|
md: {
|
|
2405
2371
|
row: "",
|
|
2406
|
-
cell: "px-4 py-
|
|
2407
|
-
head: "whitespace-nowrap px-4 py-
|
|
2372
|
+
cell: "px-4 py-3.5 text-sm tabular-nums",
|
|
2373
|
+
head: "whitespace-nowrap px-4 py-4 text-xs font-semibold uppercase tracking-wider"
|
|
2408
2374
|
},
|
|
2409
2375
|
lg: {
|
|
2410
2376
|
row: "",
|
|
2411
|
-
cell: "px-
|
|
2412
|
-
head: "whitespace-nowrap px-
|
|
2377
|
+
cell: "px-6 py-4 text-sm tabular-nums",
|
|
2378
|
+
head: "whitespace-nowrap px-6 py-5 text-[13px] font-semibold uppercase tracking-wider"
|
|
2413
2379
|
}
|
|
2414
2380
|
};
|
|
2415
2381
|
var tableBaseClass = "w-full caption-bottom border-collapse";
|
|
@@ -2466,6 +2432,7 @@ function Table(props) {
|
|
|
2466
2432
|
maxHeight,
|
|
2467
2433
|
striped = false,
|
|
2468
2434
|
onRowClick,
|
|
2435
|
+
getRowAccent,
|
|
2469
2436
|
tableRef,
|
|
2470
2437
|
pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,
|
|
2471
2438
|
showPagination,
|
|
@@ -2537,166 +2504,198 @@ function Table(props) {
|
|
|
2537
2504
|
children: bulkActions(selectedRowsInData)
|
|
2538
2505
|
}
|
|
2539
2506
|
),
|
|
2540
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
"
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
"bg-card text-muted-foreground shadow-[inset_0_-1px_0_var(--color-border)]",
|
|
2567
|
-
maxHeight !== void 0 && "sticky top-0 z-10"
|
|
2568
|
-
),
|
|
2569
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2570
|
-
enableRowSelection ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: cn("w-10", sizeClasses.head), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2571
|
-
Checkbox,
|
|
2572
|
-
{
|
|
2573
|
-
"aria-label": "Select all rows on this page",
|
|
2574
|
-
checked: allOnPageSelected,
|
|
2575
|
-
indeterminate: someOnPageSelected,
|
|
2576
|
-
disabled: selectableRowIds.length === 0,
|
|
2577
|
-
onCheckedChange: toggleHeader
|
|
2578
|
-
}
|
|
2579
|
-
) }) : null,
|
|
2580
|
-
columns.map((column) => {
|
|
2581
|
-
const isSorted = effectiveSort.columnId === column.id;
|
|
2582
|
-
const ariaSort = isSorted ? effectiveSort.direction === "asc" ? "ascending" : "descending" : "none";
|
|
2583
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2584
|
-
"th",
|
|
2585
|
-
{
|
|
2586
|
-
scope: "col",
|
|
2587
|
-
"aria-sort": column.sortable ? ariaSort : void 0,
|
|
2588
|
-
className: cn(
|
|
2589
|
-
sizeClasses.head,
|
|
2590
|
-
alignClass[column.align ?? "start"],
|
|
2591
|
-
column.className
|
|
2592
|
-
),
|
|
2593
|
-
children: column.sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2594
|
-
"button",
|
|
2595
|
-
{
|
|
2596
|
-
type: "button",
|
|
2597
|
-
onClick: () => handleSortClick(column.id),
|
|
2598
|
-
className: "inline-flex items-center gap-1.5 font-inherit uppercase tracking-inherit text-inherit hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
|
2599
|
-
"aria-label": sortAriaLabel(column, effectiveSort),
|
|
2600
|
-
children: [
|
|
2601
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: renderHeader(column.header) }),
|
|
2602
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2603
|
-
SortIndicator,
|
|
2604
|
-
{
|
|
2605
|
-
active: isSorted,
|
|
2606
|
-
direction: isSorted ? effectiveSort.direction : null
|
|
2607
|
-
}
|
|
2608
|
-
)
|
|
2609
|
-
]
|
|
2610
|
-
}
|
|
2611
|
-
) : renderHeader(column.header)
|
|
2612
|
-
},
|
|
2613
|
-
column.id
|
|
2614
|
-
);
|
|
2615
|
-
})
|
|
2616
|
-
] })
|
|
2617
|
-
}
|
|
2618
|
-
),
|
|
2619
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2620
|
-
SkeletonRows,
|
|
2621
|
-
{
|
|
2622
|
-
rowCount: skeletonCount,
|
|
2623
|
-
columnCount: totalColumnCount,
|
|
2624
|
-
cellClassName: sizeClasses.cell
|
|
2625
|
-
}
|
|
2626
|
-
) : data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2627
|
-
"td",
|
|
2628
|
-
{
|
|
2629
|
-
colSpan: totalColumnCount,
|
|
2630
|
-
className: cn(sizeClasses.cell, "py-10 text-center text-muted-foreground"),
|
|
2631
|
-
children: emptyState ?? "No data"
|
|
2632
|
-
}
|
|
2633
|
-
) }) : data.map((row, rowIndex) => {
|
|
2634
|
-
const id = getRowId(row, rowIndex);
|
|
2635
|
-
const isSelected = selected.has(id);
|
|
2636
|
-
const rowSelectable = isRowSelectable ? isRowSelectable(row) : true;
|
|
2637
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2638
|
-
"tr",
|
|
2507
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-hidden rounded-xl border border-border bg-card shadow-[var(--shadow-card)]", children: [
|
|
2508
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2509
|
+
"span",
|
|
2510
|
+
{
|
|
2511
|
+
"aria-hidden": "true",
|
|
2512
|
+
"data-testid": "table-accent",
|
|
2513
|
+
className: "pointer-events-none absolute inset-x-0 top-0 z-20 h-[3px] bg-gradient-table"
|
|
2514
|
+
}
|
|
2515
|
+
),
|
|
2516
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2517
|
+
"div",
|
|
2518
|
+
{
|
|
2519
|
+
className: cn("overflow-x-auto", maxHeight !== void 0 && "overflow-y-auto"),
|
|
2520
|
+
style: maxHeight !== void 0 ? { maxHeight } : void 0,
|
|
2521
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2522
|
+
"table",
|
|
2523
|
+
{
|
|
2524
|
+
ref: tableRef,
|
|
2525
|
+
"aria-label": ariaLabel,
|
|
2526
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2527
|
+
"aria-rowcount": totalRowCount,
|
|
2528
|
+
className: cn(tableBaseClass, "text-sm text-foreground", tableClassName),
|
|
2529
|
+
children: [
|
|
2530
|
+
caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
|
|
2531
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2532
|
+
"thead",
|
|
2639
2533
|
{
|
|
2640
|
-
"data-selected": isSelected ? "true" : void 0,
|
|
2641
|
-
"aria-selected": enableRowSelection ? isSelected : void 0,
|
|
2642
2534
|
className: cn(
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2535
|
+
// Clean opaque header (so a sticky header fully hides the rows
|
|
2536
|
+
// scrolling underneath it) with a hairline bottom rule drawn via an
|
|
2537
|
+
// inset shadow — it stays attached to the sticky header instead of
|
|
2538
|
+
// collapsing into the first row's border.
|
|
2539
|
+
// Opaque header background so a sticky header fully hides the rows
|
|
2540
|
+
// scrolling underneath it (a translucent tint would let them bleed through).
|
|
2541
|
+
"bg-muted text-muted-foreground shadow-[inset_0_-1px_0_var(--color-border)]",
|
|
2542
|
+
maxHeight !== void 0 && "sticky top-0 z-10"
|
|
2648
2543
|
),
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
enableRowSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn(sizeClasses.cell, "w-10"), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2544
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2545
|
+
enableRowSelection ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: cn("w-10", sizeClasses.head), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2652
2546
|
Checkbox,
|
|
2653
2547
|
{
|
|
2654
|
-
"aria-label":
|
|
2655
|
-
checked:
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2548
|
+
"aria-label": "Select all rows on this page",
|
|
2549
|
+
checked: allOnPageSelected,
|
|
2550
|
+
indeterminate: someOnPageSelected,
|
|
2551
|
+
disabled: selectableRowIds.length === 0,
|
|
2552
|
+
onCheckedChange: toggleHeader
|
|
2659
2553
|
}
|
|
2660
2554
|
) }) : null,
|
|
2661
|
-
columns.map((column) =>
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2555
|
+
columns.map((column) => {
|
|
2556
|
+
const isSorted = effectiveSort.columnId === column.id;
|
|
2557
|
+
const ariaSort = isSorted ? effectiveSort.direction === "asc" ? "ascending" : "descending" : "none";
|
|
2558
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2559
|
+
"th",
|
|
2560
|
+
{
|
|
2561
|
+
scope: "col",
|
|
2562
|
+
"aria-sort": column.sortable ? ariaSort : void 0,
|
|
2563
|
+
className: cn(
|
|
2564
|
+
sizeClasses.head,
|
|
2565
|
+
alignClass[column.align ?? "start"],
|
|
2566
|
+
column.className,
|
|
2567
|
+
isSorted && "text-primary"
|
|
2568
|
+
),
|
|
2569
|
+
children: column.sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2570
|
+
"button",
|
|
2571
|
+
{
|
|
2572
|
+
type: "button",
|
|
2573
|
+
onClick: () => handleSortClick(column.id),
|
|
2574
|
+
className: "inline-flex items-center gap-1.5 font-inherit uppercase tracking-inherit text-inherit hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
|
2575
|
+
"aria-label": sortAriaLabel(column, effectiveSort),
|
|
2576
|
+
children: [
|
|
2577
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: renderHeader(column.header) }),
|
|
2578
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2579
|
+
SortIndicator,
|
|
2580
|
+
{
|
|
2581
|
+
active: isSorted,
|
|
2582
|
+
direction: isSorted ? effectiveSort.direction : null
|
|
2583
|
+
}
|
|
2584
|
+
)
|
|
2585
|
+
]
|
|
2586
|
+
}
|
|
2587
|
+
) : renderHeader(column.header)
|
|
2588
|
+
},
|
|
2589
|
+
column.id
|
|
2590
|
+
);
|
|
2591
|
+
})
|
|
2592
|
+
] })
|
|
2593
|
+
}
|
|
2594
|
+
),
|
|
2595
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2596
|
+
SkeletonRows,
|
|
2597
|
+
{
|
|
2598
|
+
rowCount: skeletonCount,
|
|
2599
|
+
columnCount: totalColumnCount,
|
|
2600
|
+
cellClassName: sizeClasses.cell
|
|
2601
|
+
}
|
|
2602
|
+
) : data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2603
|
+
"td",
|
|
2604
|
+
{
|
|
2605
|
+
colSpan: totalColumnCount,
|
|
2606
|
+
className: cn(sizeClasses.cell, "py-10 text-center text-muted-foreground"),
|
|
2607
|
+
children: emptyState ?? "No data"
|
|
2608
|
+
}
|
|
2609
|
+
) }) : data.map((row, rowIndex) => {
|
|
2610
|
+
const id = getRowId(row, rowIndex);
|
|
2611
|
+
const isSelected = selected.has(id);
|
|
2612
|
+
const rowSelectable = isRowSelectable ? isRowSelectable(row) : true;
|
|
2613
|
+
const accent = getRowAccent?.(row, rowIndex);
|
|
2614
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2615
|
+
"tr",
|
|
2616
|
+
{
|
|
2617
|
+
"data-selected": isSelected ? "true" : void 0,
|
|
2618
|
+
"aria-selected": enableRowSelection ? isSelected : void 0,
|
|
2619
|
+
className: cn(
|
|
2620
|
+
"border-b border-border/60 last:border-b-0 transition-colors",
|
|
2621
|
+
"hover:bg-muted/60",
|
|
2622
|
+
striped && rowIndex % 2 === 1 && "bg-muted/20",
|
|
2623
|
+
isSelected && selectedRowClass,
|
|
2624
|
+
onRowClick && "cursor-pointer"
|
|
2625
|
+
),
|
|
2626
|
+
onClick: onRowClick ? () => onRowClick(row, rowIndex) : void 0,
|
|
2627
|
+
children: [
|
|
2628
|
+
enableRowSelection ? /* @__PURE__ */ jsxRuntime.jsxs("td", { className: cn(sizeClasses.cell, "relative w-10"), children: [
|
|
2629
|
+
accent ? /* @__PURE__ */ jsxRuntime.jsx(RowAccent, { color: accent }) : null,
|
|
2630
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2631
|
+
Checkbox,
|
|
2632
|
+
{
|
|
2633
|
+
"aria-label": `Select row ${rowIndex + 1}`,
|
|
2634
|
+
checked: isSelected,
|
|
2635
|
+
disabled: !rowSelectable,
|
|
2636
|
+
onCheckedChange: (next) => toggleRow(id, next),
|
|
2637
|
+
onClick: stopRowClickPropagation
|
|
2638
|
+
}
|
|
2639
|
+
)
|
|
2640
|
+
] }) : null,
|
|
2641
|
+
columns.map((column, colIndex) => {
|
|
2642
|
+
const isFirst = colIndex === 0 && !enableRowSelection;
|
|
2643
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2644
|
+
"td",
|
|
2645
|
+
{
|
|
2646
|
+
className: cn(
|
|
2647
|
+
sizeClasses.cell,
|
|
2648
|
+
alignClass[column.align ?? "start"],
|
|
2649
|
+
column.className,
|
|
2650
|
+
isFirst && "relative"
|
|
2651
|
+
),
|
|
2652
|
+
children: [
|
|
2653
|
+
isFirst && accent ? /* @__PURE__ */ jsxRuntime.jsx(RowAccent, { color: accent }) : null,
|
|
2654
|
+
renderCell(column, row, rowIndex)
|
|
2655
|
+
]
|
|
2656
|
+
},
|
|
2657
|
+
column.id
|
|
2658
|
+
);
|
|
2659
|
+
})
|
|
2660
|
+
]
|
|
2661
|
+
},
|
|
2662
|
+
id
|
|
2663
|
+
);
|
|
2664
|
+
}) })
|
|
2665
|
+
]
|
|
2666
|
+
}
|
|
2667
|
+
)
|
|
2668
|
+
}
|
|
2669
|
+
),
|
|
2670
|
+
paginationVisible ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2671
|
+
Pagination,
|
|
2672
|
+
{
|
|
2673
|
+
pageIndex,
|
|
2674
|
+
pageSize,
|
|
2675
|
+
pageCount,
|
|
2676
|
+
totalRowCount,
|
|
2677
|
+
pageSizeOptions,
|
|
2678
|
+
onChange: handlePaginationChange,
|
|
2679
|
+
labels
|
|
2680
|
+
}
|
|
2681
|
+
) }) : null
|
|
2682
|
+
] })
|
|
2695
2683
|
] });
|
|
2696
2684
|
}
|
|
2697
2685
|
function renderHeader(header) {
|
|
2698
2686
|
return typeof header === "function" ? header() : header;
|
|
2699
2687
|
}
|
|
2688
|
+
function RowAccent({ color }) {
|
|
2689
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2690
|
+
"span",
|
|
2691
|
+
{
|
|
2692
|
+
"aria-hidden": "true",
|
|
2693
|
+
"data-testid": "row-accent",
|
|
2694
|
+
className: "pointer-events-none absolute inset-y-1 start-0 w-[3px] rounded-full",
|
|
2695
|
+
style: { background: color }
|
|
2696
|
+
}
|
|
2697
|
+
);
|
|
2698
|
+
}
|
|
2700
2699
|
function renderCell(column, row, rowIndex) {
|
|
2701
2700
|
if (column.render) return column.render(row, rowIndex);
|
|
2702
2701
|
if (column.accessor !== void 0) {
|
|
@@ -2721,10 +2720,18 @@ function stopRowClickPropagation(event) {
|
|
|
2721
2720
|
function SkeletonRows({ rowCount, columnCount, cellClassName }) {
|
|
2722
2721
|
const rowKeys = Array.from({ length: Math.max(0, rowCount) }, (_, i) => `skeleton-row-${i}`);
|
|
2723
2722
|
const colKeys = Array.from({ length: Math.max(1, columnCount) }, (_, i) => `skeleton-col-${i}`);
|
|
2724
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: rowKeys.map((rowKey) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2723
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: rowKeys.map((rowKey) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2724
|
+
"tr",
|
|
2725
|
+
{
|
|
2726
|
+
className: "border-b border-border/60 last:border-b-0",
|
|
2727
|
+
"data-testid": "table-skeleton-row",
|
|
2728
|
+
children: colKeys.map((colKey) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: cellClassName, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block h-3 w-full animate-pulse rounded bg-muted" }) }, `${rowKey}-${colKey}`))
|
|
2729
|
+
},
|
|
2730
|
+
rowKey
|
|
2731
|
+
)) });
|
|
2725
2732
|
}
|
|
2726
2733
|
function SortIndicator({ active, direction }) {
|
|
2727
|
-
const className = cn("size-3.5 shrink-0", active ? "text-
|
|
2734
|
+
const className = cn("size-3.5 shrink-0", active ? "text-primary" : "text-muted-foreground");
|
|
2728
2735
|
if (!active) return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { "aria-hidden": "true", className });
|
|
2729
2736
|
return direction === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { "aria-hidden": "true", className }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": "true", className });
|
|
2730
2737
|
}
|