@mshuja288/aksuicore 0.2.1 → 0.4.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/CHANGELOG.md +19 -0
- package/README.md +1 -1
- package/dist/aksui.css +386 -6
- package/dist/index.cjs +496 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -7
- package/dist/index.d.ts +53 -7
- package/dist/index.js +496 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/patterns/AppShell.tsx +140 -17
- package/src/patterns/RecordWorkspace.tsx +426 -43
- package/src/patterns/index.ts +8 -2
- package/src/primitives/SideNav.tsx +3 -1
- package/src/primitives/Topbar.tsx +38 -8
- package/src/theme/patterns.css +223 -0
- package/src/theme/primitives.css +9 -1
- package/src/theme/shell.css +154 -5
package/dist/index.cjs
CHANGED
|
@@ -517,31 +517,48 @@ function Snackbar({
|
|
|
517
517
|
);
|
|
518
518
|
}
|
|
519
519
|
var StatusMessage = Snackbar;
|
|
520
|
+
function MenuIcon({ open }) {
|
|
521
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: open ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 5l10 10M15 5 5 15", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3.5 5.5h13M3.5 10h13M3.5 14.5h13", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) });
|
|
522
|
+
}
|
|
520
523
|
function Topbar({
|
|
521
524
|
title,
|
|
522
525
|
logoSrc,
|
|
523
526
|
logoAlt = "Logo",
|
|
524
527
|
username = "",
|
|
525
528
|
onLogout,
|
|
529
|
+
showMenuButton = false,
|
|
530
|
+
menuOpen = false,
|
|
531
|
+
onMenuClick,
|
|
526
532
|
children
|
|
527
533
|
}) {
|
|
528
|
-
const [
|
|
534
|
+
const [accountOpen, setAccountOpen] = react.useState(false);
|
|
529
535
|
const menuRef = react.useRef(null);
|
|
530
536
|
const initial = (username || "U").slice(0, 1).toUpperCase();
|
|
531
537
|
react.useEffect(() => {
|
|
532
|
-
if (!
|
|
538
|
+
if (!accountOpen) {
|
|
533
539
|
return;
|
|
534
540
|
}
|
|
535
541
|
function onPointerDown(event) {
|
|
536
542
|
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
537
|
-
|
|
543
|
+
setAccountOpen(false);
|
|
538
544
|
}
|
|
539
545
|
}
|
|
540
546
|
document.addEventListener("mousedown", onPointerDown);
|
|
541
547
|
return () => document.removeEventListener("mousedown", onPointerDown);
|
|
542
|
-
}, [
|
|
548
|
+
}, [accountOpen]);
|
|
543
549
|
return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "topbar", children: [
|
|
544
550
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "topbar-brand", children: [
|
|
551
|
+
showMenuButton && onMenuClick ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
552
|
+
"button",
|
|
553
|
+
{
|
|
554
|
+
type: "button",
|
|
555
|
+
className: "ghost topbar-menu-button",
|
|
556
|
+
"aria-label": menuOpen ? "Close navigation menu" : "Open navigation menu",
|
|
557
|
+
"aria-expanded": menuOpen,
|
|
558
|
+
onClick: onMenuClick,
|
|
559
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, { open: menuOpen })
|
|
560
|
+
}
|
|
561
|
+
) : null,
|
|
545
562
|
logoSrc ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
546
563
|
"img",
|
|
547
564
|
{
|
|
@@ -564,13 +581,13 @@ function Topbar({
|
|
|
564
581
|
type: "button",
|
|
565
582
|
className: "avatar-button",
|
|
566
583
|
"aria-haspopup": "menu",
|
|
567
|
-
"aria-expanded":
|
|
568
|
-
onClick: () =>
|
|
584
|
+
"aria-expanded": accountOpen,
|
|
585
|
+
onClick: () => setAccountOpen((open) => !open),
|
|
569
586
|
title: username || "Account",
|
|
570
587
|
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "avatar", children: initial })
|
|
571
588
|
}
|
|
572
589
|
),
|
|
573
|
-
|
|
590
|
+
accountOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "avatar-menu", role: "menu", children: [
|
|
574
591
|
username ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "avatar-name", children: username }) : null,
|
|
575
592
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
576
593
|
Button,
|
|
@@ -578,7 +595,7 @@ function Topbar({
|
|
|
578
595
|
variant: "ghost",
|
|
579
596
|
role: "menuitem",
|
|
580
597
|
onClick: () => {
|
|
581
|
-
|
|
598
|
+
setAccountOpen(false);
|
|
582
599
|
onLogout();
|
|
583
600
|
},
|
|
584
601
|
children: "Logout"
|
|
@@ -593,9 +610,10 @@ function SideNav({
|
|
|
593
610
|
items,
|
|
594
611
|
activeId,
|
|
595
612
|
onSelect,
|
|
596
|
-
label = "Sections"
|
|
613
|
+
label = "Sections",
|
|
614
|
+
className = ""
|
|
597
615
|
}) {
|
|
598
|
-
return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "side-nav", "aria-label": label, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
616
|
+
return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: ["side-nav", className].filter(Boolean).join(" "), "aria-label": label, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
599
617
|
"button",
|
|
600
618
|
{
|
|
601
619
|
type: "button",
|
|
@@ -697,28 +715,131 @@ function AppShell({
|
|
|
697
715
|
activeNavId,
|
|
698
716
|
onNavSelect,
|
|
699
717
|
navLabel = "Sections",
|
|
700
|
-
|
|
718
|
+
mobileNav = "drawer",
|
|
719
|
+
showBottomNav,
|
|
720
|
+
navDrawerOpen,
|
|
721
|
+
onNavDrawerOpenChange,
|
|
701
722
|
topbarActions,
|
|
702
723
|
children,
|
|
703
724
|
screenClassName = ""
|
|
704
725
|
}) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
726
|
+
const [internalDrawerOpen, setInternalDrawerOpen] = react.useState(false);
|
|
727
|
+
const drawerControlled = navDrawerOpen !== void 0;
|
|
728
|
+
const drawerOpen = drawerControlled ? navDrawerOpen : internalDrawerOpen;
|
|
729
|
+
const useBottomNav = showBottomNav ?? (mobileNav === "bottom" || mobileNav === "hybrid");
|
|
730
|
+
const useDrawer = mobileNav === "drawer" || mobileNav === "hybrid";
|
|
731
|
+
const activeItem = navItems.find((item) => item.id === activeNavId);
|
|
732
|
+
function setDrawerOpen(open) {
|
|
733
|
+
if (!drawerControlled) {
|
|
734
|
+
setInternalDrawerOpen(open);
|
|
735
|
+
}
|
|
736
|
+
onNavDrawerOpenChange?.(open);
|
|
737
|
+
}
|
|
738
|
+
react.useEffect(() => {
|
|
739
|
+
if (!drawerOpen) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
function onKeyDown(event) {
|
|
743
|
+
if (event.key === "Escape") {
|
|
744
|
+
if (!drawerControlled) {
|
|
745
|
+
setInternalDrawerOpen(false);
|
|
746
|
+
}
|
|
747
|
+
onNavDrawerOpenChange?.(false);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
document.addEventListener("keydown", onKeyDown);
|
|
751
|
+
const previousOverflow = document.body.style.overflow;
|
|
752
|
+
document.body.style.overflow = "hidden";
|
|
753
|
+
return () => {
|
|
754
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
755
|
+
document.body.style.overflow = previousOverflow;
|
|
756
|
+
};
|
|
757
|
+
}, [drawerControlled, drawerOpen, onNavDrawerOpenChange]);
|
|
758
|
+
function selectNav(id) {
|
|
759
|
+
onNavSelect(id);
|
|
760
|
+
setDrawerOpen(false);
|
|
761
|
+
}
|
|
762
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
763
|
+
"div",
|
|
764
|
+
{
|
|
765
|
+
className: [
|
|
766
|
+
"aksui-root",
|
|
767
|
+
"app-shell",
|
|
768
|
+
`mobile-nav-${mobileNav}`,
|
|
769
|
+
useBottomNav ? "has-bottom-nav" : "",
|
|
770
|
+
drawerOpen ? "nav-drawer-open" : ""
|
|
771
|
+
].filter(Boolean).join(" "),
|
|
772
|
+
children: [
|
|
773
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
774
|
+
Topbar,
|
|
775
|
+
{
|
|
776
|
+
title,
|
|
777
|
+
logoSrc,
|
|
778
|
+
logoAlt,
|
|
779
|
+
username,
|
|
780
|
+
onLogout,
|
|
781
|
+
showMenuButton: useDrawer,
|
|
782
|
+
menuOpen: drawerOpen,
|
|
783
|
+
onMenuClick: () => setDrawerOpen(!drawerOpen),
|
|
784
|
+
children: topbarActions
|
|
785
|
+
}
|
|
786
|
+
),
|
|
787
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "app-body", children: [
|
|
788
|
+
/* @__PURE__ */ jsxRuntime.jsx(SideNav, { items: navItems, activeId: activeNavId, onSelect: onNavSelect, label: navLabel }),
|
|
789
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: ["screen", screenClassName].filter(Boolean).join(" "), children })
|
|
790
|
+
] }),
|
|
791
|
+
useDrawer ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
793
|
+
"button",
|
|
794
|
+
{
|
|
795
|
+
type: "button",
|
|
796
|
+
className: drawerOpen ? "nav-drawer-backdrop open" : "nav-drawer-backdrop",
|
|
797
|
+
"aria-label": "Close navigation menu",
|
|
798
|
+
tabIndex: drawerOpen ? 0 : -1,
|
|
799
|
+
onClick: () => setDrawerOpen(false)
|
|
800
|
+
}
|
|
801
|
+
),
|
|
802
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
803
|
+
"aside",
|
|
804
|
+
{
|
|
805
|
+
className: drawerOpen ? "nav-drawer open" : "nav-drawer",
|
|
806
|
+
"aria-label": navLabel,
|
|
807
|
+
"aria-hidden": !drawerOpen,
|
|
808
|
+
children: [
|
|
809
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nav-drawer-head", children: [
|
|
810
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "nav-drawer-title", children: navLabel }),
|
|
811
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost nav-drawer-close", onClick: () => setDrawerOpen(false), children: "Close" })
|
|
812
|
+
] }),
|
|
813
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
814
|
+
SideNav,
|
|
815
|
+
{
|
|
816
|
+
className: "nav-drawer-nav",
|
|
817
|
+
items: navItems,
|
|
818
|
+
activeId: activeNavId,
|
|
819
|
+
onSelect: selectNav,
|
|
820
|
+
label: navLabel
|
|
821
|
+
}
|
|
822
|
+
)
|
|
823
|
+
]
|
|
824
|
+
}
|
|
825
|
+
)
|
|
826
|
+
] }) : null,
|
|
827
|
+
useBottomNav ? /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "bottom-nav", "aria-label": navLabel, children: mobileNav === "hybrid" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
828
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "active bottom-nav-current", disabled: true, children: activeItem?.short ?? activeItem?.label ?? "Section" }),
|
|
829
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "bottom-nav-menu", onClick: () => setDrawerOpen(true), children: "Menu" })
|
|
830
|
+
] }) : navItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
831
|
+
"button",
|
|
832
|
+
{
|
|
833
|
+
type: "button",
|
|
834
|
+
className: activeNavId === item.id ? "active" : "",
|
|
835
|
+
onClick: () => onNavSelect(item.id),
|
|
836
|
+
children: item.short ?? item.label
|
|
837
|
+
},
|
|
838
|
+
item.id
|
|
839
|
+
)) }) : null
|
|
840
|
+
]
|
|
841
|
+
}
|
|
842
|
+
);
|
|
722
843
|
}
|
|
723
844
|
function useIsClient2() {
|
|
724
845
|
return react.useSyncExternalStore(
|
|
@@ -728,6 +849,42 @@ function useIsClient2() {
|
|
|
728
849
|
() => false
|
|
729
850
|
);
|
|
730
851
|
}
|
|
852
|
+
var EXPORT_FORMAT_OPTIONS = [
|
|
853
|
+
{ format: "csv", label: "CSV" },
|
|
854
|
+
{ format: "xlsx", label: "Excel" },
|
|
855
|
+
{ format: "json", label: "JSON" }
|
|
856
|
+
];
|
|
857
|
+
function defaultVisibleKeys(columns) {
|
|
858
|
+
return columns.filter((column) => column.defaultVisible !== false).map((column) => column.key);
|
|
859
|
+
}
|
|
860
|
+
function readStoredColumnKeys(prefsKey, fallback, allowed) {
|
|
861
|
+
if (!prefsKey || typeof window === "undefined") {
|
|
862
|
+
return fallback;
|
|
863
|
+
}
|
|
864
|
+
try {
|
|
865
|
+
const raw = window.localStorage.getItem(prefsKey);
|
|
866
|
+
if (!raw) {
|
|
867
|
+
return fallback;
|
|
868
|
+
}
|
|
869
|
+
const parsed = JSON.parse(raw);
|
|
870
|
+
if (!Array.isArray(parsed)) {
|
|
871
|
+
return fallback;
|
|
872
|
+
}
|
|
873
|
+
const keys = parsed.filter((entry) => typeof entry === "string" && allowed.has(entry));
|
|
874
|
+
return keys.length > 0 ? keys : fallback;
|
|
875
|
+
} catch {
|
|
876
|
+
return fallback;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
function writeStoredColumnKeys(prefsKey, keys) {
|
|
880
|
+
if (!prefsKey || typeof window === "undefined") {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
try {
|
|
884
|
+
window.localStorage.setItem(prefsKey, JSON.stringify(keys));
|
|
885
|
+
} catch {
|
|
886
|
+
}
|
|
887
|
+
}
|
|
731
888
|
function compareColumnValues(column, left, right) {
|
|
732
889
|
const leftRaw = column.display ? column.display(left) : column.value(left);
|
|
733
890
|
const rightRaw = column.display ? column.display(right) : column.value(right);
|
|
@@ -761,6 +918,9 @@ function ResetIcon() {
|
|
|
761
918
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.5 4.2v4h4", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
762
919
|
] });
|
|
763
920
|
}
|
|
921
|
+
function ColumnsIcon() {
|
|
922
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4.5h3.5v11H4zM8.25 4.5h3.5v11h-3.5zM12.5 4.5H16v11h-3.5z", fill: "none", stroke: "currentColor", strokeWidth: "1.5" }) });
|
|
923
|
+
}
|
|
764
924
|
function ChevronIcon({ open }) {
|
|
765
925
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: open ? "side-rail-chevron open" : "side-rail-chevron", viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 4.5 13.5 10 8 15.5", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
766
926
|
}
|
|
@@ -770,6 +930,20 @@ function PreviewIcon() {
|
|
|
770
930
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "2.4", fill: "none", stroke: "currentColor", strokeWidth: "1.6" })
|
|
771
931
|
] });
|
|
772
932
|
}
|
|
933
|
+
function DownloadIcon() {
|
|
934
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
|
|
935
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3.5v8.2", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
936
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.5 9.2 10 12.8l3.5-3.6", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
937
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 15.5h12", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
|
|
938
|
+
] });
|
|
939
|
+
}
|
|
940
|
+
function MoreIcon() {
|
|
941
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
|
|
942
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "10", r: "1.5", fill: "currentColor" }),
|
|
943
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "1.5", fill: "currentColor" }),
|
|
944
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15.5", cy: "10", r: "1.5", fill: "currentColor" })
|
|
945
|
+
] });
|
|
946
|
+
}
|
|
773
947
|
function DetailList({ lines }) {
|
|
774
948
|
return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "record-detail-list", children: lines.map((line) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "record-detail-row", children: [
|
|
775
949
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { children: line.label }),
|
|
@@ -790,23 +964,86 @@ function RecordWorkspace({
|
|
|
790
964
|
onDelete,
|
|
791
965
|
canUpdate,
|
|
792
966
|
canDelete,
|
|
967
|
+
onDownload,
|
|
968
|
+
canDownload = true,
|
|
969
|
+
downloadBusy = false,
|
|
970
|
+
showColumnPicker = true,
|
|
971
|
+
columnPrefsKey,
|
|
972
|
+
visibleColumnKeys,
|
|
973
|
+
defaultVisibleColumnKeys,
|
|
974
|
+
onVisibleColumnKeysChange,
|
|
793
975
|
toolbar,
|
|
794
976
|
form
|
|
795
977
|
}) {
|
|
796
|
-
const
|
|
978
|
+
const allowedKeys = react.useMemo(() => new Set(columns.map((column) => column.key)), [columns]);
|
|
979
|
+
const fallbackKeys = react.useMemo(
|
|
980
|
+
() => defaultVisibleColumnKeys ?? defaultVisibleKeys(columns),
|
|
981
|
+
[columns, defaultVisibleColumnKeys]
|
|
982
|
+
);
|
|
983
|
+
const isControlled = visibleColumnKeys !== void 0;
|
|
984
|
+
const [internalVisibleKeys, setInternalVisibleKeys] = react.useState(
|
|
985
|
+
() => readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys)
|
|
986
|
+
);
|
|
797
987
|
const [filters, setFilters] = react.useState({});
|
|
798
988
|
const [sort, setSort] = react.useState(null);
|
|
799
989
|
const [sideOpen, setSideOpen] = react.useState(false);
|
|
990
|
+
const [downloadOpen, setDownloadOpen] = react.useState(false);
|
|
991
|
+
const [columnsOpen, setColumnsOpen] = react.useState(false);
|
|
800
992
|
const [previewEnabled, setPreviewEnabled] = react.useState(false);
|
|
801
993
|
const [previewKey, setPreviewKey] = react.useState(null);
|
|
802
994
|
const [tooltip, setTooltip] = react.useState(null);
|
|
803
995
|
const [pageSize, setPageSize] = react.useState("15");
|
|
804
996
|
const [page, setPage] = react.useState(1);
|
|
997
|
+
const [actionsMenuKey, setActionsMenuKey] = react.useState(null);
|
|
998
|
+
const actionsMenuRef = react.useRef(null);
|
|
805
999
|
const isClient = useIsClient2();
|
|
1000
|
+
react.useEffect(() => {
|
|
1001
|
+
if (isControlled) {
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
setInternalVisibleKeys(readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys));
|
|
1005
|
+
}, [allowedKeys, columnPrefsKey, fallbackKeys, isControlled]);
|
|
1006
|
+
const resolvedVisibleKeys = react.useMemo(() => {
|
|
1007
|
+
const source = isControlled ? visibleColumnKeys : internalVisibleKeys;
|
|
1008
|
+
const filtered2 = source.filter((key) => allowedKeys.has(key));
|
|
1009
|
+
return filtered2.length > 0 ? filtered2 : fallbackKeys.filter((key) => allowedKeys.has(key));
|
|
1010
|
+
}, [allowedKeys, fallbackKeys, internalVisibleKeys, isControlled, visibleColumnKeys]);
|
|
1011
|
+
const visibleColumns = react.useMemo(() => {
|
|
1012
|
+
const byKey = new Map(columns.map((column) => [column.key, column]));
|
|
1013
|
+
return resolvedVisibleKeys.map((key) => byKey.get(key)).filter((column) => Boolean(column));
|
|
1014
|
+
}, [columns, resolvedVisibleKeys]);
|
|
1015
|
+
function setVisibleKeys(next) {
|
|
1016
|
+
const unique = Array.from(new Set(next.filter((key) => allowedKeys.has(key))));
|
|
1017
|
+
const safe = unique.length > 0 ? unique : fallbackKeys.filter((key) => allowedKeys.has(key));
|
|
1018
|
+
if (!isControlled) {
|
|
1019
|
+
setInternalVisibleKeys(safe);
|
|
1020
|
+
writeStoredColumnKeys(columnPrefsKey, safe);
|
|
1021
|
+
}
|
|
1022
|
+
onVisibleColumnKeysChange?.(safe);
|
|
1023
|
+
}
|
|
1024
|
+
function toggleColumnVisible(key, checked) {
|
|
1025
|
+
if (checked) {
|
|
1026
|
+
if (resolvedVisibleKeys.includes(key)) {
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
setVisibleKeys([...resolvedVisibleKeys, key]);
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
if (resolvedVisibleKeys.length <= 1) {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
setVisibleKeys(resolvedVisibleKeys.filter((entry) => entry !== key));
|
|
1036
|
+
}
|
|
1037
|
+
function selectAllColumns() {
|
|
1038
|
+
setVisibleKeys(columns.map((column) => column.key));
|
|
1039
|
+
}
|
|
1040
|
+
function resetColumns() {
|
|
1041
|
+
setVisibleKeys(fallbackKeys);
|
|
1042
|
+
}
|
|
1043
|
+
const filterableColumns = visibleColumns.filter((column) => column.filterable !== false);
|
|
806
1044
|
const filtered = react.useMemo(() => {
|
|
807
|
-
const activeFilters = columns.filter((column) => column.filterable !== false);
|
|
808
1045
|
return items.filter(
|
|
809
|
-
(item) =>
|
|
1046
|
+
(item) => filterableColumns.every((column) => {
|
|
810
1047
|
const query = (filters[column.key] ?? "").trim();
|
|
811
1048
|
if (!query) {
|
|
812
1049
|
return true;
|
|
@@ -819,22 +1056,23 @@ function RecordWorkspace({
|
|
|
819
1056
|
return text.toLowerCase().includes(query.toLowerCase());
|
|
820
1057
|
})
|
|
821
1058
|
);
|
|
822
|
-
}, [items, filters,
|
|
1059
|
+
}, [items, filters, filterableColumns]);
|
|
823
1060
|
const sorted = react.useMemo(() => {
|
|
824
1061
|
if (!sort) {
|
|
825
1062
|
return filtered;
|
|
826
1063
|
}
|
|
827
|
-
const column =
|
|
1064
|
+
const column = visibleColumns.find((entry) => entry.key === sort.key);
|
|
828
1065
|
if (!column || column.sortable === false) {
|
|
829
1066
|
return filtered;
|
|
830
1067
|
}
|
|
831
1068
|
const direction = sort.direction === "asc" ? 1 : -1;
|
|
832
1069
|
return [...filtered].sort((left, right) => compareColumnValues(column, left, right) * direction);
|
|
833
|
-
}, [filtered, sort,
|
|
1070
|
+
}, [filtered, sort, visibleColumns]);
|
|
834
1071
|
const activeFilterCount = react.useMemo(
|
|
835
1072
|
() => filterableColumns.reduce((count, column) => count + ((filters[column.key] ?? "").trim() ? 1 : 0), 0),
|
|
836
1073
|
[filterableColumns, filters]
|
|
837
1074
|
);
|
|
1075
|
+
const hiddenColumnCount = columns.length - visibleColumns.length;
|
|
838
1076
|
const showAll = pageSize === "all";
|
|
839
1077
|
const numericPageSize = showAll ? Math.max(sorted.length, 1) : Number(pageSize);
|
|
840
1078
|
const pageCount = showAll ? 1 : Math.max(1, Math.ceil(sorted.length / numericPageSize));
|
|
@@ -842,19 +1080,44 @@ function RecordWorkspace({
|
|
|
842
1080
|
const start = showAll ? 0 : (currentPage - 1) * numericPageSize;
|
|
843
1081
|
const pageItems = showAll ? sorted : sorted.slice(start, start + numericPageSize);
|
|
844
1082
|
const showAdd = canAdd && Boolean(onAdd);
|
|
1083
|
+
const showDownload = Boolean(onDownload) && canDownload;
|
|
845
1084
|
const showFilters = filterableColumns.length > 0;
|
|
1085
|
+
const showColumns = showColumnPicker && columns.length > 0;
|
|
846
1086
|
const previewItem = previewKey === null ? null : sorted.find((item) => rowKey(item) === previewKey) ?? null;
|
|
1087
|
+
const exportColumns = visibleColumns.map((column) => ({
|
|
1088
|
+
key: column.exportKey ?? column.key,
|
|
1089
|
+
header: column.header
|
|
1090
|
+
}));
|
|
1091
|
+
react.useEffect(() => {
|
|
1092
|
+
if (actionsMenuKey === null) {
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
function onPointerDown(event) {
|
|
1096
|
+
if (actionsMenuRef.current && !actionsMenuRef.current.contains(event.target)) {
|
|
1097
|
+
setActionsMenuKey(null);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
document.addEventListener("mousedown", onPointerDown);
|
|
1101
|
+
return () => document.removeEventListener("mousedown", onPointerDown);
|
|
1102
|
+
}, [actionsMenuKey]);
|
|
1103
|
+
function requestDownload(format) {
|
|
1104
|
+
if (!onDownload || downloadBusy) {
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
onDownload(format, exportColumns);
|
|
1108
|
+
setDownloadOpen(false);
|
|
1109
|
+
}
|
|
847
1110
|
function cellText(column, item) {
|
|
848
1111
|
const raw = column.display ? column.display(item) : column.value(item);
|
|
849
1112
|
return raw === null || raw === void 0 || raw === "" ? "\u2014" : String(raw);
|
|
850
1113
|
}
|
|
851
1114
|
function detailLines(item) {
|
|
852
|
-
return
|
|
1115
|
+
return visibleColumns.map((column) => ({
|
|
853
1116
|
label: column.header,
|
|
854
1117
|
value: cellText(column, item)
|
|
855
1118
|
}));
|
|
856
1119
|
}
|
|
857
|
-
const previewTitle = previewItem &&
|
|
1120
|
+
const previewTitle = previewItem && visibleColumns[0] ? cellText(visibleColumns[0], previewItem) : null;
|
|
858
1121
|
function changeFilter(key, value) {
|
|
859
1122
|
setFilters((current) => ({ ...current, [key]: value }));
|
|
860
1123
|
setPage(1);
|
|
@@ -898,6 +1161,99 @@ function RecordWorkspace({
|
|
|
898
1161
|
setTooltip({ x, y, lines: detailLines(item) });
|
|
899
1162
|
}
|
|
900
1163
|
const summary = sorted.length === 0 ? "0 records" : showAll ? `1\u2013${sorted.length} of ${sorted.length}` : `${start + 1}\u2013${Math.min(start + numericPageSize, sorted.length)} of ${sorted.length}`;
|
|
1164
|
+
function renderRowActions(item) {
|
|
1165
|
+
const key = rowKey(item);
|
|
1166
|
+
const updateAllowed = canUpdate ? canUpdate(item) : Boolean(onUpdate);
|
|
1167
|
+
const deleteAllowed = canDelete ? canDelete(item) : Boolean(onDelete);
|
|
1168
|
+
const hasActions = Boolean(onView || onUpdate || onDelete);
|
|
1169
|
+
if (!hasActions) {
|
|
1170
|
+
return null;
|
|
1171
|
+
}
|
|
1172
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1173
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "row-actions row-actions-desktop", children: [
|
|
1174
|
+
onView ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost row-action", onClick: () => onView(item), children: "View" }) : null,
|
|
1175
|
+
onUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1176
|
+
"button",
|
|
1177
|
+
{
|
|
1178
|
+
type: "button",
|
|
1179
|
+
className: "ghost row-action",
|
|
1180
|
+
disabled: !updateAllowed,
|
|
1181
|
+
title: updateAllowed ? "Update" : "Update is not available",
|
|
1182
|
+
onClick: () => onUpdate(item),
|
|
1183
|
+
children: "Update"
|
|
1184
|
+
}
|
|
1185
|
+
) : null,
|
|
1186
|
+
onDelete ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1187
|
+
"button",
|
|
1188
|
+
{
|
|
1189
|
+
type: "button",
|
|
1190
|
+
className: "ghost row-action danger",
|
|
1191
|
+
disabled: !deleteAllowed,
|
|
1192
|
+
title: deleteAllowed ? "Delete" : "Delete is not available",
|
|
1193
|
+
onClick: () => onDelete(item),
|
|
1194
|
+
children: "Delete"
|
|
1195
|
+
}
|
|
1196
|
+
) : null
|
|
1197
|
+
] }),
|
|
1198
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "row-actions row-actions-mobile", ref: actionsMenuKey === key ? actionsMenuRef : void 0, children: [
|
|
1199
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1200
|
+
"button",
|
|
1201
|
+
{
|
|
1202
|
+
type: "button",
|
|
1203
|
+
className: "ghost row-action-menu-trigger",
|
|
1204
|
+
"aria-haspopup": "menu",
|
|
1205
|
+
"aria-expanded": actionsMenuKey === key,
|
|
1206
|
+
"aria-label": "Row actions",
|
|
1207
|
+
onClick: () => setActionsMenuKey((current) => current === key ? null : key),
|
|
1208
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MoreIcon, {})
|
|
1209
|
+
}
|
|
1210
|
+
),
|
|
1211
|
+
actionsMenuKey === key ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "row-action-menu", role: "menu", children: [
|
|
1212
|
+
onView ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1213
|
+
"button",
|
|
1214
|
+
{
|
|
1215
|
+
type: "button",
|
|
1216
|
+
role: "menuitem",
|
|
1217
|
+
className: "ghost",
|
|
1218
|
+
onClick: () => {
|
|
1219
|
+
setActionsMenuKey(null);
|
|
1220
|
+
onView(item);
|
|
1221
|
+
},
|
|
1222
|
+
children: "View"
|
|
1223
|
+
}
|
|
1224
|
+
) : null,
|
|
1225
|
+
onUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1226
|
+
"button",
|
|
1227
|
+
{
|
|
1228
|
+
type: "button",
|
|
1229
|
+
role: "menuitem",
|
|
1230
|
+
className: "ghost",
|
|
1231
|
+
disabled: !updateAllowed,
|
|
1232
|
+
onClick: () => {
|
|
1233
|
+
setActionsMenuKey(null);
|
|
1234
|
+
onUpdate(item);
|
|
1235
|
+
},
|
|
1236
|
+
children: "Update"
|
|
1237
|
+
}
|
|
1238
|
+
) : null,
|
|
1239
|
+
onDelete ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1240
|
+
"button",
|
|
1241
|
+
{
|
|
1242
|
+
type: "button",
|
|
1243
|
+
role: "menuitem",
|
|
1244
|
+
className: "ghost danger",
|
|
1245
|
+
disabled: !deleteAllowed,
|
|
1246
|
+
onClick: () => {
|
|
1247
|
+
setActionsMenuKey(null);
|
|
1248
|
+
onDelete(item);
|
|
1249
|
+
},
|
|
1250
|
+
children: "Delete"
|
|
1251
|
+
}
|
|
1252
|
+
) : null
|
|
1253
|
+
] }) : null
|
|
1254
|
+
] })
|
|
1255
|
+
] });
|
|
1256
|
+
}
|
|
901
1257
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "list-workspace", "aria-label": title, children: [
|
|
902
1258
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
903
1259
|
"div",
|
|
@@ -908,7 +1264,7 @@ function RecordWorkspace({
|
|
|
908
1264
|
toolbar ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-card-bar", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-card-context", children: toolbar }) }) : null,
|
|
909
1265
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-wrap", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "data-table", children: [
|
|
910
1266
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
911
|
-
|
|
1267
|
+
visibleColumns.map((column) => {
|
|
912
1268
|
const sortable = column.sortable !== false;
|
|
913
1269
|
const active = sort?.key === column.key ? sort.direction : null;
|
|
914
1270
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -933,10 +1289,8 @@ function RecordWorkspace({
|
|
|
933
1289
|
}),
|
|
934
1290
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "actions-col", children: "Actions" })
|
|
935
1291
|
] }) }),
|
|
936
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: pageItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan:
|
|
1292
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: pageItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: visibleColumns.length + 1, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "hint table-empty", children: items.length === 0 ? empty : "No records match the current filters." }) }) }) : pageItems.map((item) => {
|
|
937
1293
|
const key = rowKey(item);
|
|
938
|
-
const updateAllowed = canUpdate ? canUpdate(item) : Boolean(onUpdate);
|
|
939
|
-
const deleteAllowed = canDelete ? canDelete(item) : Boolean(onDelete);
|
|
940
1294
|
const selected = previewEnabled && previewKey === key;
|
|
941
1295
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
942
1296
|
"tr",
|
|
@@ -956,32 +1310,8 @@ function RecordWorkspace({
|
|
|
956
1310
|
onMouseLeave: () => setTooltip(null),
|
|
957
1311
|
onClick: () => focusRecord(item),
|
|
958
1312
|
children: [
|
|
959
|
-
|
|
960
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "actions-col", onClick: (event) => event.stopPropagation(), children:
|
|
961
|
-
onView ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost row-action", onClick: () => onView(item), children: "View" }) : null,
|
|
962
|
-
onUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
963
|
-
"button",
|
|
964
|
-
{
|
|
965
|
-
type: "button",
|
|
966
|
-
className: "ghost row-action",
|
|
967
|
-
disabled: !updateAllowed,
|
|
968
|
-
title: updateAllowed ? "Update" : "Update is not available",
|
|
969
|
-
onClick: () => onUpdate(item),
|
|
970
|
-
children: "Update"
|
|
971
|
-
}
|
|
972
|
-
) : null,
|
|
973
|
-
onDelete ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
974
|
-
"button",
|
|
975
|
-
{
|
|
976
|
-
type: "button",
|
|
977
|
-
className: "ghost row-action danger",
|
|
978
|
-
disabled: !deleteAllowed,
|
|
979
|
-
title: deleteAllowed ? "Delete" : "Delete is not available",
|
|
980
|
-
onClick: () => onDelete(item),
|
|
981
|
-
children: "Delete"
|
|
982
|
-
}
|
|
983
|
-
) : null
|
|
984
|
-
] }) })
|
|
1313
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx("td", { children: cellText(column, item) }, column.key)),
|
|
1314
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "actions-col", onClick: (event) => event.stopPropagation(), children: renderRowActions(item) })
|
|
985
1315
|
]
|
|
986
1316
|
},
|
|
987
1317
|
key
|
|
@@ -1043,6 +1373,73 @@ function RecordWorkspace({
|
|
|
1043
1373
|
/* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
|
|
1044
1374
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: addLabel })
|
|
1045
1375
|
] }) : null,
|
|
1376
|
+
showColumns ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns", children: [
|
|
1377
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1378
|
+
"button",
|
|
1379
|
+
{
|
|
1380
|
+
type: "button",
|
|
1381
|
+
className: "ghost side-rail-columns-toggle",
|
|
1382
|
+
"aria-expanded": columnsOpen,
|
|
1383
|
+
onClick: () => setColumnsOpen((open) => !open),
|
|
1384
|
+
children: [
|
|
1385
|
+
/* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {}),
|
|
1386
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1387
|
+
"Columns",
|
|
1388
|
+
hiddenColumnCount > 0 ? ` (${visibleColumns.length}/${columns.length})` : ""
|
|
1389
|
+
] })
|
|
1390
|
+
]
|
|
1391
|
+
}
|
|
1392
|
+
),
|
|
1393
|
+
columnsOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns-panel", role: "group", "aria-label": "Visible columns", children: [
|
|
1394
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns-actions", children: [
|
|
1395
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", onClick: selectAllColumns, children: "Select all" }),
|
|
1396
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", onClick: resetColumns, children: "Reset" })
|
|
1397
|
+
] }),
|
|
1398
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "side-rail-columns-list", children: columns.map((column) => {
|
|
1399
|
+
const checked = resolvedVisibleKeys.includes(column.key);
|
|
1400
|
+
const disableUncheck = checked && resolvedVisibleKeys.length <= 1;
|
|
1401
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-column-option", children: [
|
|
1402
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1403
|
+
"input",
|
|
1404
|
+
{
|
|
1405
|
+
type: "checkbox",
|
|
1406
|
+
checked,
|
|
1407
|
+
disabled: disableUncheck,
|
|
1408
|
+
onChange: (event) => toggleColumnVisible(column.key, event.target.checked)
|
|
1409
|
+
}
|
|
1410
|
+
),
|
|
1411
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: column.header })
|
|
1412
|
+
] }, column.key);
|
|
1413
|
+
}) })
|
|
1414
|
+
] }) : null
|
|
1415
|
+
] }) : null,
|
|
1416
|
+
showDownload ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-download", children: [
|
|
1417
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1418
|
+
"button",
|
|
1419
|
+
{
|
|
1420
|
+
type: "button",
|
|
1421
|
+
className: "ghost side-rail-download-toggle",
|
|
1422
|
+
"aria-expanded": downloadOpen,
|
|
1423
|
+
disabled: downloadBusy,
|
|
1424
|
+
onClick: () => setDownloadOpen((open) => !open),
|
|
1425
|
+
children: [
|
|
1426
|
+
/* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {}),
|
|
1427
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: downloadBusy ? "Downloading\u2026" : "Download" })
|
|
1428
|
+
]
|
|
1429
|
+
}
|
|
1430
|
+
),
|
|
1431
|
+
downloadOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "side-rail-download-formats", role: "group", "aria-label": "Download format", children: EXPORT_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1432
|
+
"button",
|
|
1433
|
+
{
|
|
1434
|
+
type: "button",
|
|
1435
|
+
className: "ghost side-rail-download-format",
|
|
1436
|
+
disabled: downloadBusy,
|
|
1437
|
+
onClick: () => requestDownload(option.format),
|
|
1438
|
+
children: option.label
|
|
1439
|
+
},
|
|
1440
|
+
option.format
|
|
1441
|
+
)) }) : null
|
|
1442
|
+
] }) : null,
|
|
1046
1443
|
showFilters ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-filters", children: [
|
|
1047
1444
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "filter-panel-head", children: [
|
|
1048
1445
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Filters" }),
|
|
@@ -1096,6 +1493,39 @@ function RecordWorkspace({
|
|
|
1096
1493
|
/* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, {})
|
|
1097
1494
|
] }),
|
|
1098
1495
|
showAdd ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost side-rail-icon", title: addLabel, "aria-label": addLabel, onClick: onAdd, children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}) }) : null,
|
|
1496
|
+
showColumns ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1497
|
+
"button",
|
|
1498
|
+
{
|
|
1499
|
+
type: "button",
|
|
1500
|
+
className: "ghost side-rail-icon",
|
|
1501
|
+
title: "Columns",
|
|
1502
|
+
"aria-label": "Columns",
|
|
1503
|
+
onClick: () => {
|
|
1504
|
+
setSideOpen(true);
|
|
1505
|
+
setColumnsOpen(true);
|
|
1506
|
+
},
|
|
1507
|
+
children: [
|
|
1508
|
+
/* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {}),
|
|
1509
|
+
hiddenColumnCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "filter-badge", children: hiddenColumnCount }) : null
|
|
1510
|
+
]
|
|
1511
|
+
}
|
|
1512
|
+
) : null,
|
|
1513
|
+
showDownload ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1514
|
+
"button",
|
|
1515
|
+
{
|
|
1516
|
+
type: "button",
|
|
1517
|
+
className: "ghost side-rail-icon",
|
|
1518
|
+
title: "Download",
|
|
1519
|
+
"aria-label": "Download",
|
|
1520
|
+
"aria-expanded": downloadOpen,
|
|
1521
|
+
disabled: downloadBusy,
|
|
1522
|
+
onClick: () => {
|
|
1523
|
+
setSideOpen(true);
|
|
1524
|
+
setDownloadOpen(true);
|
|
1525
|
+
},
|
|
1526
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {})
|
|
1527
|
+
}
|
|
1528
|
+
) : null,
|
|
1099
1529
|
showFilters ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1100
1530
|
"button",
|
|
1101
1531
|
{
|