@mshuja288/aksuicore 0.3.0 → 0.4.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.js CHANGED
@@ -515,31 +515,48 @@ function Snackbar({
515
515
  );
516
516
  }
517
517
  var StatusMessage = Snackbar;
518
+ function MenuIcon({ open }) {
519
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: open ? /* @__PURE__ */ jsx("path", { d: "M5 5l10 10M15 5 5 15", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) : /* @__PURE__ */ jsx("path", { d: "M3.5 5.5h13M3.5 10h13M3.5 14.5h13", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) });
520
+ }
518
521
  function Topbar({
519
522
  title,
520
523
  logoSrc,
521
524
  logoAlt = "Logo",
522
525
  username = "",
523
526
  onLogout,
527
+ showMenuButton = false,
528
+ menuOpen = false,
529
+ onMenuClick,
524
530
  children
525
531
  }) {
526
- const [menuOpen, setMenuOpen] = useState(false);
532
+ const [accountOpen, setAccountOpen] = useState(false);
527
533
  const menuRef = useRef(null);
528
534
  const initial = (username || "U").slice(0, 1).toUpperCase();
529
535
  useEffect(() => {
530
- if (!menuOpen) {
536
+ if (!accountOpen) {
531
537
  return;
532
538
  }
533
539
  function onPointerDown(event) {
534
540
  if (menuRef.current && !menuRef.current.contains(event.target)) {
535
- setMenuOpen(false);
541
+ setAccountOpen(false);
536
542
  }
537
543
  }
538
544
  document.addEventListener("mousedown", onPointerDown);
539
545
  return () => document.removeEventListener("mousedown", onPointerDown);
540
- }, [menuOpen]);
546
+ }, [accountOpen]);
541
547
  return /* @__PURE__ */ jsxs("header", { className: "topbar", children: [
542
548
  /* @__PURE__ */ jsxs("div", { className: "topbar-brand", children: [
549
+ showMenuButton && onMenuClick ? /* @__PURE__ */ jsx(
550
+ "button",
551
+ {
552
+ type: "button",
553
+ className: "ghost topbar-menu-button",
554
+ "aria-label": menuOpen ? "Close navigation menu" : "Open navigation menu",
555
+ "aria-expanded": menuOpen,
556
+ onClick: onMenuClick,
557
+ children: /* @__PURE__ */ jsx(MenuIcon, { open: menuOpen })
558
+ }
559
+ ) : null,
543
560
  logoSrc ? /* @__PURE__ */ jsx(
544
561
  "img",
545
562
  {
@@ -562,13 +579,13 @@ function Topbar({
562
579
  type: "button",
563
580
  className: "avatar-button",
564
581
  "aria-haspopup": "menu",
565
- "aria-expanded": menuOpen,
566
- onClick: () => setMenuOpen((open) => !open),
582
+ "aria-expanded": accountOpen,
583
+ onClick: () => setAccountOpen((open) => !open),
567
584
  title: username || "Account",
568
585
  children: /* @__PURE__ */ jsx("span", { className: "avatar", children: initial })
569
586
  }
570
587
  ),
571
- menuOpen ? /* @__PURE__ */ jsxs("div", { className: "avatar-menu", role: "menu", children: [
588
+ accountOpen ? /* @__PURE__ */ jsxs("div", { className: "avatar-menu", role: "menu", children: [
572
589
  username ? /* @__PURE__ */ jsx("p", { className: "avatar-name", children: username }) : null,
573
590
  /* @__PURE__ */ jsx(
574
591
  Button,
@@ -576,7 +593,7 @@ function Topbar({
576
593
  variant: "ghost",
577
594
  role: "menuitem",
578
595
  onClick: () => {
579
- setMenuOpen(false);
596
+ setAccountOpen(false);
580
597
  onLogout();
581
598
  },
582
599
  children: "Logout"
@@ -591,9 +608,10 @@ function SideNav({
591
608
  items,
592
609
  activeId,
593
610
  onSelect,
594
- label = "Sections"
611
+ label = "Sections",
612
+ className = ""
595
613
  }) {
596
- return /* @__PURE__ */ jsx("nav", { className: "side-nav", "aria-label": label, children: items.map((item) => /* @__PURE__ */ jsx(
614
+ return /* @__PURE__ */ jsx("nav", { className: ["side-nav", className].filter(Boolean).join(" "), "aria-label": label, children: items.map((item) => /* @__PURE__ */ jsx(
597
615
  "button",
598
616
  {
599
617
  type: "button",
@@ -695,28 +713,131 @@ function AppShell({
695
713
  activeNavId,
696
714
  onNavSelect,
697
715
  navLabel = "Sections",
698
- showBottomNav = true,
716
+ mobileNav = "drawer",
717
+ showBottomNav,
718
+ navDrawerOpen,
719
+ onNavDrawerOpenChange,
699
720
  topbarActions,
700
721
  children,
701
722
  screenClassName = ""
702
723
  }) {
703
- return /* @__PURE__ */ jsxs("div", { className: "aksui-root app-shell", children: [
704
- /* @__PURE__ */ jsx(Topbar, { title, logoSrc, logoAlt, username, onLogout, children: topbarActions }),
705
- /* @__PURE__ */ jsxs("div", { className: "app-body", children: [
706
- /* @__PURE__ */ jsx(SideNav, { items: navItems, activeId: activeNavId, onSelect: onNavSelect, label: navLabel }),
707
- /* @__PURE__ */ jsx("div", { className: ["screen", screenClassName].filter(Boolean).join(" "), children })
708
- ] }),
709
- showBottomNav ? /* @__PURE__ */ jsx("nav", { className: "bottom-nav", "aria-label": navLabel, children: navItems.map((item) => /* @__PURE__ */ jsx(
710
- "button",
711
- {
712
- type: "button",
713
- className: activeNavId === item.id ? "active" : "",
714
- onClick: () => onNavSelect(item.id),
715
- children: item.short ?? item.label
716
- },
717
- item.id
718
- )) }) : null
719
- ] });
724
+ const [internalDrawerOpen, setInternalDrawerOpen] = useState(false);
725
+ const drawerControlled = navDrawerOpen !== void 0;
726
+ const drawerOpen = drawerControlled ? navDrawerOpen : internalDrawerOpen;
727
+ const useBottomNav = showBottomNav ?? (mobileNav === "bottom" || mobileNav === "hybrid");
728
+ const useDrawer = mobileNav === "drawer" || mobileNav === "hybrid";
729
+ const activeItem = navItems.find((item) => item.id === activeNavId);
730
+ function setDrawerOpen(open) {
731
+ if (!drawerControlled) {
732
+ setInternalDrawerOpen(open);
733
+ }
734
+ onNavDrawerOpenChange?.(open);
735
+ }
736
+ useEffect(() => {
737
+ if (!drawerOpen) {
738
+ return;
739
+ }
740
+ function onKeyDown(event) {
741
+ if (event.key === "Escape") {
742
+ if (!drawerControlled) {
743
+ setInternalDrawerOpen(false);
744
+ }
745
+ onNavDrawerOpenChange?.(false);
746
+ }
747
+ }
748
+ document.addEventListener("keydown", onKeyDown);
749
+ const previousOverflow = document.body.style.overflow;
750
+ document.body.style.overflow = "hidden";
751
+ return () => {
752
+ document.removeEventListener("keydown", onKeyDown);
753
+ document.body.style.overflow = previousOverflow;
754
+ };
755
+ }, [drawerControlled, drawerOpen, onNavDrawerOpenChange]);
756
+ function selectNav(id) {
757
+ onNavSelect(id);
758
+ setDrawerOpen(false);
759
+ }
760
+ return /* @__PURE__ */ jsxs(
761
+ "div",
762
+ {
763
+ className: [
764
+ "aksui-root",
765
+ "app-shell",
766
+ `mobile-nav-${mobileNav}`,
767
+ useBottomNav ? "has-bottom-nav" : "",
768
+ drawerOpen ? "nav-drawer-open" : ""
769
+ ].filter(Boolean).join(" "),
770
+ children: [
771
+ /* @__PURE__ */ jsx(
772
+ Topbar,
773
+ {
774
+ title,
775
+ logoSrc,
776
+ logoAlt,
777
+ username,
778
+ onLogout,
779
+ showMenuButton: useDrawer,
780
+ menuOpen: drawerOpen,
781
+ onMenuClick: () => setDrawerOpen(!drawerOpen),
782
+ children: topbarActions
783
+ }
784
+ ),
785
+ /* @__PURE__ */ jsxs("div", { className: "app-body", children: [
786
+ /* @__PURE__ */ jsx(SideNav, { items: navItems, activeId: activeNavId, onSelect: onNavSelect, label: navLabel }),
787
+ /* @__PURE__ */ jsx("div", { className: ["screen", screenClassName].filter(Boolean).join(" "), children })
788
+ ] }),
789
+ useDrawer ? /* @__PURE__ */ jsxs(Fragment, { children: [
790
+ /* @__PURE__ */ jsx(
791
+ "button",
792
+ {
793
+ type: "button",
794
+ className: drawerOpen ? "nav-drawer-backdrop open" : "nav-drawer-backdrop",
795
+ "aria-label": "Close navigation menu",
796
+ tabIndex: drawerOpen ? 0 : -1,
797
+ onClick: () => setDrawerOpen(false)
798
+ }
799
+ ),
800
+ /* @__PURE__ */ jsxs(
801
+ "aside",
802
+ {
803
+ className: drawerOpen ? "nav-drawer open" : "nav-drawer",
804
+ "aria-label": navLabel,
805
+ "aria-hidden": !drawerOpen,
806
+ children: [
807
+ /* @__PURE__ */ jsxs("div", { className: "nav-drawer-head", children: [
808
+ /* @__PURE__ */ jsx("p", { className: "nav-drawer-title", children: navLabel }),
809
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ghost nav-drawer-close", onClick: () => setDrawerOpen(false), children: "Close" })
810
+ ] }),
811
+ /* @__PURE__ */ jsx(
812
+ SideNav,
813
+ {
814
+ className: "nav-drawer-nav",
815
+ items: navItems,
816
+ activeId: activeNavId,
817
+ onSelect: selectNav,
818
+ label: navLabel
819
+ }
820
+ )
821
+ ]
822
+ }
823
+ )
824
+ ] }) : null,
825
+ useBottomNav ? /* @__PURE__ */ jsx("nav", { className: "bottom-nav", "aria-label": navLabel, children: mobileNav === "hybrid" ? /* @__PURE__ */ jsxs(Fragment, { children: [
826
+ /* @__PURE__ */ jsx("button", { type: "button", className: "active bottom-nav-current", disabled: true, children: activeItem?.short ?? activeItem?.label ?? "Section" }),
827
+ /* @__PURE__ */ jsx("button", { type: "button", className: "bottom-nav-menu", onClick: () => setDrawerOpen(true), children: "Menu" })
828
+ ] }) : navItems.map((item) => /* @__PURE__ */ jsx(
829
+ "button",
830
+ {
831
+ type: "button",
832
+ className: activeNavId === item.id ? "active" : "",
833
+ onClick: () => onNavSelect(item.id),
834
+ children: item.short ?? item.label
835
+ },
836
+ item.id
837
+ )) }) : null
838
+ ]
839
+ }
840
+ );
720
841
  }
721
842
  function useIsClient2() {
722
843
  return useSyncExternalStore(
@@ -726,11 +847,57 @@ function useIsClient2() {
726
847
  () => false
727
848
  );
728
849
  }
850
+ function useHoverTooltipsEnabled() {
851
+ return useSyncExternalStore(
852
+ (onStoreChange) => {
853
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
854
+ return () => {
855
+ };
856
+ }
857
+ const media = window.matchMedia("(hover: hover) and (pointer: fine)");
858
+ media.addEventListener("change", onStoreChange);
859
+ return () => media.removeEventListener("change", onStoreChange);
860
+ },
861
+ () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(hover: hover) and (pointer: fine)").matches,
862
+ () => false
863
+ );
864
+ }
729
865
  var EXPORT_FORMAT_OPTIONS = [
730
866
  { format: "csv", label: "CSV" },
731
867
  { format: "xlsx", label: "Excel" },
732
868
  { format: "json", label: "JSON" }
733
869
  ];
870
+ function defaultVisibleKeys(columns) {
871
+ return columns.filter((column) => column.defaultVisible !== false).map((column) => column.key);
872
+ }
873
+ function readStoredColumnKeys(prefsKey, fallback, allowed) {
874
+ if (!prefsKey || typeof window === "undefined") {
875
+ return fallback;
876
+ }
877
+ try {
878
+ const raw = window.localStorage.getItem(prefsKey);
879
+ if (!raw) {
880
+ return fallback;
881
+ }
882
+ const parsed = JSON.parse(raw);
883
+ if (!Array.isArray(parsed)) {
884
+ return fallback;
885
+ }
886
+ const keys = parsed.filter((entry) => typeof entry === "string" && allowed.has(entry));
887
+ return keys.length > 0 ? keys : fallback;
888
+ } catch {
889
+ return fallback;
890
+ }
891
+ }
892
+ function writeStoredColumnKeys(prefsKey, keys) {
893
+ if (!prefsKey || typeof window === "undefined") {
894
+ return;
895
+ }
896
+ try {
897
+ window.localStorage.setItem(prefsKey, JSON.stringify(keys));
898
+ } catch {
899
+ }
900
+ }
734
901
  function compareColumnValues(column, left, right) {
735
902
  const leftRaw = column.display ? column.display(left) : column.value(left);
736
903
  const rightRaw = column.display ? column.display(right) : column.value(right);
@@ -764,6 +931,9 @@ function ResetIcon() {
764
931
  /* @__PURE__ */ jsx("path", { d: "M4.5 4.2v4h4", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" })
765
932
  ] });
766
933
  }
934
+ function ColumnsIcon() {
935
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ 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" }) });
936
+ }
767
937
  function ChevronIcon({ open }) {
768
938
  return /* @__PURE__ */ jsx("svg", { className: open ? "side-rail-chevron open" : "side-rail-chevron", viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M8 4.5 13.5 10 8 15.5", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
769
939
  }
@@ -780,6 +950,26 @@ function DownloadIcon() {
780
950
  /* @__PURE__ */ jsx("path", { d: "M4 15.5h12", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
781
951
  ] });
782
952
  }
953
+ function MoreIcon() {
954
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
955
+ /* @__PURE__ */ jsx("circle", { cx: "4.5", cy: "10", r: "1.5", fill: "currentColor" }),
956
+ /* @__PURE__ */ jsx("circle", { cx: "10", cy: "10", r: "1.5", fill: "currentColor" }),
957
+ /* @__PURE__ */ jsx("circle", { cx: "15.5", cy: "10", r: "1.5", fill: "currentColor" })
958
+ ] });
959
+ }
960
+ function ToolsIcon() {
961
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
962
+ "path",
963
+ {
964
+ d: "M11.5 3.5h5v5M16.2 3.8 10 10M8.2 5.2H3.8v11h11V12",
965
+ fill: "none",
966
+ stroke: "currentColor",
967
+ strokeWidth: "1.6",
968
+ strokeLinecap: "round",
969
+ strokeLinejoin: "round"
970
+ }
971
+ ) });
972
+ }
783
973
  function DetailList({ lines }) {
784
974
  return /* @__PURE__ */ jsx("dl", { className: "record-detail-list", children: lines.map((line) => /* @__PURE__ */ jsxs("div", { className: "record-detail-row", children: [
785
975
  /* @__PURE__ */ jsx("dt", { children: line.label }),
@@ -803,24 +993,85 @@ function RecordWorkspace({
803
993
  onDownload,
804
994
  canDownload = true,
805
995
  downloadBusy = false,
996
+ showColumnPicker = true,
997
+ columnPrefsKey,
998
+ visibleColumnKeys,
999
+ defaultVisibleColumnKeys,
1000
+ onVisibleColumnKeysChange,
806
1001
  toolbar,
807
1002
  form
808
1003
  }) {
809
- const filterableColumns = columns.filter((column) => column.filterable !== false);
1004
+ const allowedKeys = useMemo(() => new Set(columns.map((column) => column.key)), [columns]);
1005
+ const fallbackKeys = useMemo(
1006
+ () => defaultVisibleColumnKeys ?? defaultVisibleKeys(columns),
1007
+ [columns, defaultVisibleColumnKeys]
1008
+ );
1009
+ const isControlled = visibleColumnKeys !== void 0;
1010
+ const [internalVisibleKeys, setInternalVisibleKeys] = useState(
1011
+ () => readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys)
1012
+ );
810
1013
  const [filters, setFilters] = useState({});
811
1014
  const [sort, setSort] = useState(null);
812
1015
  const [sideOpen, setSideOpen] = useState(false);
1016
+ const [toolsDrawerOpen, setToolsDrawerOpen] = useState(false);
813
1017
  const [downloadOpen, setDownloadOpen] = useState(false);
1018
+ const [columnsOpen, setColumnsOpen] = useState(false);
814
1019
  const [previewEnabled, setPreviewEnabled] = useState(false);
815
1020
  const [previewKey, setPreviewKey] = useState(null);
816
1021
  const [tooltip, setTooltip] = useState(null);
817
1022
  const [pageSize, setPageSize] = useState("15");
818
1023
  const [page, setPage] = useState(1);
1024
+ const [actionsMenu, setActionsMenu] = useState(null);
1025
+ const actionsMenuRef = useRef(null);
819
1026
  const isClient = useIsClient2();
1027
+ const hoverTooltipsEnabled = useHoverTooltipsEnabled();
1028
+ useEffect(() => {
1029
+ if (isControlled) {
1030
+ return;
1031
+ }
1032
+ setInternalVisibleKeys(readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys));
1033
+ }, [allowedKeys, columnPrefsKey, fallbackKeys, isControlled]);
1034
+ const resolvedVisibleKeys = useMemo(() => {
1035
+ const source = isControlled ? visibleColumnKeys : internalVisibleKeys;
1036
+ const filtered2 = source.filter((key) => allowedKeys.has(key));
1037
+ return filtered2.length > 0 ? filtered2 : fallbackKeys.filter((key) => allowedKeys.has(key));
1038
+ }, [allowedKeys, fallbackKeys, internalVisibleKeys, isControlled, visibleColumnKeys]);
1039
+ const visibleColumns = useMemo(() => {
1040
+ const byKey = new Map(columns.map((column) => [column.key, column]));
1041
+ return resolvedVisibleKeys.map((key) => byKey.get(key)).filter((column) => Boolean(column));
1042
+ }, [columns, resolvedVisibleKeys]);
1043
+ function setVisibleKeys(next) {
1044
+ const unique = Array.from(new Set(next.filter((key) => allowedKeys.has(key))));
1045
+ const safe = unique.length > 0 ? unique : fallbackKeys.filter((key) => allowedKeys.has(key));
1046
+ if (!isControlled) {
1047
+ setInternalVisibleKeys(safe);
1048
+ writeStoredColumnKeys(columnPrefsKey, safe);
1049
+ }
1050
+ onVisibleColumnKeysChange?.(safe);
1051
+ }
1052
+ function toggleColumnVisible(key, checked) {
1053
+ if (checked) {
1054
+ if (resolvedVisibleKeys.includes(key)) {
1055
+ return;
1056
+ }
1057
+ setVisibleKeys([...resolvedVisibleKeys, key]);
1058
+ return;
1059
+ }
1060
+ if (resolvedVisibleKeys.length <= 1) {
1061
+ return;
1062
+ }
1063
+ setVisibleKeys(resolvedVisibleKeys.filter((entry) => entry !== key));
1064
+ }
1065
+ function selectAllColumns() {
1066
+ setVisibleKeys(columns.map((column) => column.key));
1067
+ }
1068
+ function resetColumns() {
1069
+ setVisibleKeys(fallbackKeys);
1070
+ }
1071
+ const filterableColumns = visibleColumns.filter((column) => column.filterable !== false);
820
1072
  const filtered = useMemo(() => {
821
- const activeFilters = columns.filter((column) => column.filterable !== false);
822
1073
  return items.filter(
823
- (item) => activeFilters.every((column) => {
1074
+ (item) => filterableColumns.every((column) => {
824
1075
  const query = (filters[column.key] ?? "").trim();
825
1076
  if (!query) {
826
1077
  return true;
@@ -833,22 +1084,24 @@ function RecordWorkspace({
833
1084
  return text.toLowerCase().includes(query.toLowerCase());
834
1085
  })
835
1086
  );
836
- }, [items, filters, columns]);
1087
+ }, [items, filters, filterableColumns]);
837
1088
  const sorted = useMemo(() => {
838
1089
  if (!sort) {
839
1090
  return filtered;
840
1091
  }
841
- const column = columns.find((entry) => entry.key === sort.key);
1092
+ const column = visibleColumns.find((entry) => entry.key === sort.key);
842
1093
  if (!column || column.sortable === false) {
843
1094
  return filtered;
844
1095
  }
845
1096
  const direction = sort.direction === "asc" ? 1 : -1;
846
1097
  return [...filtered].sort((left, right) => compareColumnValues(column, left, right) * direction);
847
- }, [filtered, sort, columns]);
1098
+ }, [filtered, sort, visibleColumns]);
848
1099
  const activeFilterCount = useMemo(
849
1100
  () => filterableColumns.reduce((count, column) => count + ((filters[column.key] ?? "").trim() ? 1 : 0), 0),
850
1101
  [filterableColumns, filters]
851
1102
  );
1103
+ const hiddenColumnCount = columns.length - visibleColumns.length;
1104
+ const toolsBadgeCount = activeFilterCount + (hiddenColumnCount > 0 ? 1 : 0) + (previewEnabled ? 1 : 0);
852
1105
  const showAll = pageSize === "all";
853
1106
  const numericPageSize = showAll ? Math.max(sorted.length, 1) : Number(pageSize);
854
1107
  const pageCount = showAll ? 1 : Math.max(1, Math.ceil(sorted.length / numericPageSize));
@@ -858,12 +1111,47 @@ function RecordWorkspace({
858
1111
  const showAdd = canAdd && Boolean(onAdd);
859
1112
  const showDownload = Boolean(onDownload) && canDownload;
860
1113
  const showFilters = filterableColumns.length > 0;
1114
+ const showColumns = showColumnPicker && columns.length > 0;
861
1115
  const previewItem = previewKey === null ? null : sorted.find((item) => rowKey(item) === previewKey) ?? null;
1116
+ const exportColumns = visibleColumns.map((column) => ({
1117
+ key: column.exportKey ?? column.key,
1118
+ header: column.header
1119
+ }));
1120
+ const canShowTooltip = hoverTooltipsEnabled && !previewEnabled && actionsMenu === null;
1121
+ useEffect(() => {
1122
+ if (actionsMenu === null) {
1123
+ return;
1124
+ }
1125
+ function onPointerDown(event) {
1126
+ if (actionsMenuRef.current && !actionsMenuRef.current.contains(event.target)) {
1127
+ setActionsMenu(null);
1128
+ }
1129
+ }
1130
+ document.addEventListener("mousedown", onPointerDown);
1131
+ return () => document.removeEventListener("mousedown", onPointerDown);
1132
+ }, [actionsMenu]);
1133
+ useEffect(() => {
1134
+ if (!toolsDrawerOpen) {
1135
+ return;
1136
+ }
1137
+ function onKeyDown(event) {
1138
+ if (event.key === "Escape") {
1139
+ setToolsDrawerOpen(false);
1140
+ }
1141
+ }
1142
+ document.addEventListener("keydown", onKeyDown);
1143
+ const previousOverflow = document.body.style.overflow;
1144
+ document.body.style.overflow = "hidden";
1145
+ return () => {
1146
+ document.removeEventListener("keydown", onKeyDown);
1147
+ document.body.style.overflow = previousOverflow;
1148
+ };
1149
+ }, [toolsDrawerOpen]);
862
1150
  function requestDownload(format) {
863
1151
  if (!onDownload || downloadBusy) {
864
1152
  return;
865
1153
  }
866
- onDownload(format);
1154
+ onDownload(format, exportColumns);
867
1155
  setDownloadOpen(false);
868
1156
  }
869
1157
  function cellText(column, item) {
@@ -871,12 +1159,12 @@ function RecordWorkspace({
871
1159
  return raw === null || raw === void 0 || raw === "" ? "\u2014" : String(raw);
872
1160
  }
873
1161
  function detailLines(item) {
874
- return columns.map((column) => ({
1162
+ return visibleColumns.map((column) => ({
875
1163
  label: column.header,
876
1164
  value: cellText(column, item)
877
1165
  }));
878
1166
  }
879
- const previewTitle = previewItem && columns[0] ? cellText(columns[0], previewItem) : null;
1167
+ const previewTitle = previewItem && visibleColumns[0] ? cellText(visibleColumns[0], previewItem) : null;
880
1168
  function changeFilter(key, value) {
881
1169
  setFilters((current) => ({ ...current, [key]: value }));
882
1170
  setPage(1);
@@ -913,14 +1201,317 @@ function RecordWorkspace({
913
1201
  }
914
1202
  }
915
1203
  function showTooltip(item, event) {
1204
+ if (!canShowTooltip) {
1205
+ return;
1206
+ }
916
1207
  const padding = 16;
917
1208
  const width = 280;
918
1209
  const x = Math.min(event.clientX + 14, window.innerWidth - width - padding);
919
1210
  const y = Math.min(event.clientY + 14, window.innerHeight - padding - 24);
920
1211
  setTooltip({ x, y, lines: detailLines(item) });
921
1212
  }
1213
+ function openRowActions(item, event) {
1214
+ event.stopPropagation();
1215
+ setTooltip(null);
1216
+ const key = rowKey(item);
1217
+ if (actionsMenu?.key === key) {
1218
+ setActionsMenu(null);
1219
+ return;
1220
+ }
1221
+ const rect = event.currentTarget.getBoundingClientRect();
1222
+ const menuWidth = 168;
1223
+ const menuHeight = 148;
1224
+ const x = Math.min(Math.max(8, rect.right - menuWidth), window.innerWidth - menuWidth - 8);
1225
+ const y = Math.min(rect.bottom + 6, window.innerHeight - menuHeight - 8);
1226
+ setActionsMenu({ key, item, x, y });
1227
+ }
922
1228
  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}`;
923
- return /* @__PURE__ */ jsxs("div", { className: "list-workspace", "aria-label": title, children: [
1229
+ function renderToolsBody({ compactIcons }) {
1230
+ if (compactIcons) {
1231
+ return /* @__PURE__ */ jsxs("div", { className: "side-rail-icons", children: [
1232
+ /* @__PURE__ */ jsxs("label", { className: "side-rail-icon preview-check-icon", title: "Preview", children: [
1233
+ /* @__PURE__ */ jsx(
1234
+ "input",
1235
+ {
1236
+ type: "checkbox",
1237
+ checked: previewEnabled,
1238
+ onChange: (event) => setPreviewEnabledValue(event.target.checked),
1239
+ "aria-label": "Preview"
1240
+ }
1241
+ ),
1242
+ /* @__PURE__ */ jsx(PreviewIcon, {})
1243
+ ] }),
1244
+ showAdd ? /* @__PURE__ */ jsx("button", { type: "button", className: "ghost side-rail-icon", title: addLabel, "aria-label": addLabel, onClick: onAdd, children: /* @__PURE__ */ jsx(PlusIcon, {}) }) : null,
1245
+ showColumns ? /* @__PURE__ */ jsxs(
1246
+ "button",
1247
+ {
1248
+ type: "button",
1249
+ className: "ghost side-rail-icon",
1250
+ title: "Columns",
1251
+ "aria-label": "Columns",
1252
+ onClick: () => {
1253
+ setSideOpen(true);
1254
+ setColumnsOpen(true);
1255
+ },
1256
+ children: [
1257
+ /* @__PURE__ */ jsx(ColumnsIcon, {}),
1258
+ hiddenColumnCount > 0 ? /* @__PURE__ */ jsx("span", { className: "filter-badge", children: hiddenColumnCount }) : null
1259
+ ]
1260
+ }
1261
+ ) : null,
1262
+ showDownload ? /* @__PURE__ */ jsx(
1263
+ "button",
1264
+ {
1265
+ type: "button",
1266
+ className: "ghost side-rail-icon",
1267
+ title: "Download",
1268
+ "aria-label": "Download",
1269
+ disabled: downloadBusy,
1270
+ onClick: () => {
1271
+ setSideOpen(true);
1272
+ setDownloadOpen(true);
1273
+ },
1274
+ children: /* @__PURE__ */ jsx(DownloadIcon, {})
1275
+ }
1276
+ ) : null,
1277
+ showFilters ? /* @__PURE__ */ jsxs(
1278
+ "button",
1279
+ {
1280
+ type: "button",
1281
+ className: "ghost side-rail-icon",
1282
+ title: "Show filters",
1283
+ "aria-label": "Show filters",
1284
+ onClick: () => setSideOpen(true),
1285
+ children: [
1286
+ /* @__PURE__ */ jsx(FilterIcon, {}),
1287
+ activeFilterCount > 0 ? /* @__PURE__ */ jsx("span", { className: "filter-badge", children: activeFilterCount }) : null
1288
+ ]
1289
+ }
1290
+ ) : null,
1291
+ showFilters ? /* @__PURE__ */ jsx(
1292
+ "button",
1293
+ {
1294
+ type: "button",
1295
+ className: "ghost side-rail-icon",
1296
+ title: "Reset filters",
1297
+ "aria-label": "Reset filters",
1298
+ disabled: activeFilterCount === 0,
1299
+ onClick: clearFilters,
1300
+ children: /* @__PURE__ */ jsx(ResetIcon, {})
1301
+ }
1302
+ ) : null
1303
+ ] });
1304
+ }
1305
+ return /* @__PURE__ */ jsxs("div", { className: "side-rail-body", children: [
1306
+ /* @__PURE__ */ jsxs("div", { className: "preview-check", children: [
1307
+ /* @__PURE__ */ jsx(
1308
+ "input",
1309
+ {
1310
+ type: "checkbox",
1311
+ checked: previewEnabled,
1312
+ onChange: (event) => setPreviewEnabledValue(event.target.checked),
1313
+ "aria-label": "Preview"
1314
+ }
1315
+ ),
1316
+ /* @__PURE__ */ jsx(PreviewIcon, {}),
1317
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "Preview" })
1318
+ ] }),
1319
+ showAdd ? /* @__PURE__ */ jsxs(
1320
+ "button",
1321
+ {
1322
+ type: "button",
1323
+ className: "side-rail-add",
1324
+ onClick: () => {
1325
+ setToolsDrawerOpen(false);
1326
+ onAdd?.();
1327
+ },
1328
+ children: [
1329
+ /* @__PURE__ */ jsx(PlusIcon, {}),
1330
+ /* @__PURE__ */ jsx("span", { children: addLabel })
1331
+ ]
1332
+ }
1333
+ ) : null,
1334
+ showColumns ? /* @__PURE__ */ jsxs("div", { className: "side-rail-columns", children: [
1335
+ /* @__PURE__ */ jsxs(
1336
+ "button",
1337
+ {
1338
+ type: "button",
1339
+ className: "ghost side-rail-columns-toggle",
1340
+ "aria-expanded": columnsOpen,
1341
+ onClick: () => setColumnsOpen((open) => !open),
1342
+ children: [
1343
+ /* @__PURE__ */ jsx(ColumnsIcon, {}),
1344
+ /* @__PURE__ */ jsxs("span", { children: [
1345
+ "Columns",
1346
+ hiddenColumnCount > 0 ? ` (${visibleColumns.length}/${columns.length})` : ""
1347
+ ] })
1348
+ ]
1349
+ }
1350
+ ),
1351
+ columnsOpen ? /* @__PURE__ */ jsxs("div", { className: "side-rail-columns-panel", role: "group", "aria-label": "Visible columns", children: [
1352
+ /* @__PURE__ */ jsxs("div", { className: "side-rail-columns-actions", children: [
1353
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ghost", onClick: selectAllColumns, children: "Select all" }),
1354
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ghost", onClick: resetColumns, children: "Reset" })
1355
+ ] }),
1356
+ /* @__PURE__ */ jsx("div", { className: "side-rail-columns-list", children: columns.map((column) => {
1357
+ const checked = resolvedVisibleKeys.includes(column.key);
1358
+ const disableUncheck = checked && resolvedVisibleKeys.length <= 1;
1359
+ return /* @__PURE__ */ jsxs("label", { className: "side-rail-column-option", children: [
1360
+ /* @__PURE__ */ jsx(
1361
+ "input",
1362
+ {
1363
+ type: "checkbox",
1364
+ checked,
1365
+ disabled: disableUncheck,
1366
+ onChange: (event) => toggleColumnVisible(column.key, event.target.checked)
1367
+ }
1368
+ ),
1369
+ /* @__PURE__ */ jsx("span", { children: column.header })
1370
+ ] }, column.key);
1371
+ }) })
1372
+ ] }) : null
1373
+ ] }) : null,
1374
+ showDownload ? /* @__PURE__ */ jsxs("div", { className: "side-rail-download", children: [
1375
+ /* @__PURE__ */ jsxs(
1376
+ "button",
1377
+ {
1378
+ type: "button",
1379
+ className: "ghost side-rail-download-toggle",
1380
+ "aria-expanded": downloadOpen,
1381
+ disabled: downloadBusy,
1382
+ onClick: () => setDownloadOpen((open) => !open),
1383
+ children: [
1384
+ /* @__PURE__ */ jsx(DownloadIcon, {}),
1385
+ /* @__PURE__ */ jsx("span", { children: downloadBusy ? "Downloading\u2026" : "Download" })
1386
+ ]
1387
+ }
1388
+ ),
1389
+ downloadOpen ? /* @__PURE__ */ jsx("div", { className: "side-rail-download-formats", role: "group", "aria-label": "Download format", children: EXPORT_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsx(
1390
+ "button",
1391
+ {
1392
+ type: "button",
1393
+ className: "ghost side-rail-download-format",
1394
+ disabled: downloadBusy,
1395
+ onClick: () => requestDownload(option.format),
1396
+ children: option.label
1397
+ },
1398
+ option.format
1399
+ )) }) : null
1400
+ ] }) : null,
1401
+ showFilters ? /* @__PURE__ */ jsxs("div", { className: "side-rail-filters", children: [
1402
+ /* @__PURE__ */ jsxs("div", { className: "filter-panel-head", children: [
1403
+ /* @__PURE__ */ jsx("h3", { children: "Filters" }),
1404
+ /* @__PURE__ */ jsxs(
1405
+ "button",
1406
+ {
1407
+ type: "button",
1408
+ className: "ghost filter-clear",
1409
+ title: "Reset filters",
1410
+ "aria-label": "Reset filters",
1411
+ disabled: activeFilterCount === 0,
1412
+ onClick: clearFilters,
1413
+ children: [
1414
+ /* @__PURE__ */ jsx(ResetIcon, {}),
1415
+ /* @__PURE__ */ jsx("span", { children: "Reset" })
1416
+ ]
1417
+ }
1418
+ )
1419
+ ] }),
1420
+ /* @__PURE__ */ jsx("div", { className: "filter-panel-stack", children: filterableColumns.map((column) => /* @__PURE__ */ jsxs("label", { children: [
1421
+ column.header,
1422
+ column.filterOptions ? /* @__PURE__ */ jsx(
1423
+ Select,
1424
+ {
1425
+ value: filters[column.key] ?? "",
1426
+ options: [{ value: "", label: column.filterPlaceholder ?? "All" }, ...column.filterOptions],
1427
+ onChange: (value) => changeFilter(column.key, value),
1428
+ placeholder: column.filterPlaceholder ?? "All"
1429
+ }
1430
+ ) : /* @__PURE__ */ jsx(
1431
+ "input",
1432
+ {
1433
+ value: filters[column.key] ?? "",
1434
+ onChange: (event) => changeFilter(column.key, event.target.value),
1435
+ placeholder: `Filter ${column.header.toLowerCase()}`
1436
+ }
1437
+ )
1438
+ ] }, column.key)) })
1439
+ ] }) : null
1440
+ ] });
1441
+ }
1442
+ function renderRowActions(item) {
1443
+ const key = rowKey(item);
1444
+ const updateAllowed = canUpdate ? canUpdate(item) : Boolean(onUpdate);
1445
+ const deleteAllowed = canDelete ? canDelete(item) : Boolean(onDelete);
1446
+ const hasActions = Boolean(onView || onUpdate || onDelete);
1447
+ if (!hasActions) {
1448
+ return null;
1449
+ }
1450
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1451
+ /* @__PURE__ */ jsxs("div", { className: "row-actions row-actions-desktop", children: [
1452
+ onView ? /* @__PURE__ */ jsx("button", { type: "button", className: "ghost row-action", onClick: () => onView(item), children: "View" }) : null,
1453
+ onUpdate ? /* @__PURE__ */ jsx(
1454
+ "button",
1455
+ {
1456
+ type: "button",
1457
+ className: "ghost row-action",
1458
+ disabled: !updateAllowed,
1459
+ title: updateAllowed ? "Update" : "Update is not available",
1460
+ onClick: () => onUpdate(item),
1461
+ children: "Update"
1462
+ }
1463
+ ) : null,
1464
+ onDelete ? /* @__PURE__ */ jsx(
1465
+ "button",
1466
+ {
1467
+ type: "button",
1468
+ className: "ghost row-action danger",
1469
+ disabled: !deleteAllowed,
1470
+ title: deleteAllowed ? "Delete" : "Delete is not available",
1471
+ onClick: () => onDelete(item),
1472
+ children: "Delete"
1473
+ }
1474
+ ) : null
1475
+ ] }),
1476
+ /* @__PURE__ */ jsx("div", { className: "row-actions row-actions-mobile", children: /* @__PURE__ */ jsx(
1477
+ "button",
1478
+ {
1479
+ type: "button",
1480
+ className: actionsMenu?.key === key ? "ghost row-action-menu-trigger open" : "ghost row-action-menu-trigger",
1481
+ "aria-haspopup": "menu",
1482
+ "aria-expanded": actionsMenu?.key === key,
1483
+ "aria-label": "Row actions",
1484
+ onClick: (event) => openRowActions(item, event),
1485
+ children: /* @__PURE__ */ jsx(MoreIcon, {})
1486
+ }
1487
+ ) })
1488
+ ] });
1489
+ }
1490
+ const actionsMenuItem = actionsMenu?.item;
1491
+ const actionsUpdateAllowed = actionsMenuItem ? canUpdate ? canUpdate(actionsMenuItem) : Boolean(onUpdate) : false;
1492
+ const actionsDeleteAllowed = actionsMenuItem ? canDelete ? canDelete(actionsMenuItem) : Boolean(onDelete) : false;
1493
+ return /* @__PURE__ */ jsxs("div", { className: toolsDrawerOpen ? "list-workspace tools-drawer-open" : "list-workspace", "aria-label": title, children: [
1494
+ /* @__PURE__ */ jsxs("div", { className: "tools-mobile-bar", children: [
1495
+ /* @__PURE__ */ jsx("div", { className: "tools-mobile-bar-start", children: showAdd ? /* @__PURE__ */ jsxs("button", { type: "button", className: "tools-mobile-add", onClick: onAdd, children: [
1496
+ /* @__PURE__ */ jsx(PlusIcon, {}),
1497
+ /* @__PURE__ */ jsx("span", { children: addLabel })
1498
+ ] }) : /* @__PURE__ */ jsx("p", { className: "tools-mobile-title", children: title }) }),
1499
+ /* @__PURE__ */ jsxs(
1500
+ "button",
1501
+ {
1502
+ type: "button",
1503
+ className: "ghost tools-mobile-toggle",
1504
+ "aria-expanded": toolsDrawerOpen,
1505
+ "aria-controls": "aksui-tools-drawer",
1506
+ onClick: () => setToolsDrawerOpen(true),
1507
+ children: [
1508
+ /* @__PURE__ */ jsx(ToolsIcon, {}),
1509
+ /* @__PURE__ */ jsx("span", { children: "Tools" }),
1510
+ toolsBadgeCount > 0 ? /* @__PURE__ */ jsx("span", { className: "filter-badge", children: toolsBadgeCount }) : null
1511
+ ]
1512
+ }
1513
+ )
1514
+ ] }),
924
1515
  /* @__PURE__ */ jsxs(
925
1516
  "div",
926
1517
  {
@@ -930,7 +1521,7 @@ function RecordWorkspace({
930
1521
  toolbar ? /* @__PURE__ */ jsx("div", { className: "table-card-bar", children: /* @__PURE__ */ jsx("div", { className: "table-card-context", children: toolbar }) }) : null,
931
1522
  /* @__PURE__ */ jsx("div", { className: "table-wrap", children: /* @__PURE__ */ jsxs("table", { className: "data-table", children: [
932
1523
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
933
- columns.map((column) => {
1524
+ visibleColumns.map((column) => {
934
1525
  const sortable = column.sortable !== false;
935
1526
  const active = sort?.key === column.key ? sort.direction : null;
936
1527
  return /* @__PURE__ */ jsx(
@@ -955,55 +1546,23 @@ function RecordWorkspace({
955
1546
  }),
956
1547
  /* @__PURE__ */ jsx("th", { className: "actions-col", children: "Actions" })
957
1548
  ] }) }),
958
- /* @__PURE__ */ jsx("tbody", { children: pageItems.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columns.length + 1, children: /* @__PURE__ */ jsx("p", { className: "hint table-empty", children: items.length === 0 ? empty : "No records match the current filters." }) }) }) : pageItems.map((item) => {
1549
+ /* @__PURE__ */ jsx("tbody", { children: pageItems.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: visibleColumns.length + 1, children: /* @__PURE__ */ jsx("p", { className: "hint table-empty", children: items.length === 0 ? empty : "No records match the current filters." }) }) }) : pageItems.map((item) => {
959
1550
  const key = rowKey(item);
960
- const updateAllowed = canUpdate ? canUpdate(item) : Boolean(onUpdate);
961
- const deleteAllowed = canDelete ? canDelete(item) : Boolean(onDelete);
962
1551
  const selected = previewEnabled && previewKey === key;
963
1552
  return /* @__PURE__ */ jsxs(
964
1553
  "tr",
965
1554
  {
966
1555
  className: selected ? "data-row selected" : "data-row",
967
1556
  onMouseEnter: (event) => {
968
- if (!previewEnabled) {
969
- showTooltip(item, event);
970
- }
1557
+ showTooltip(item, event);
971
1558
  focusRecord(item);
972
1559
  },
973
- onMouseMove: (event) => {
974
- if (!previewEnabled) {
975
- showTooltip(item, event);
976
- }
977
- },
1560
+ onMouseMove: (event) => showTooltip(item, event),
978
1561
  onMouseLeave: () => setTooltip(null),
979
1562
  onClick: () => focusRecord(item),
980
1563
  children: [
981
- columns.map((column) => /* @__PURE__ */ jsx("td", { children: cellText(column, item) }, column.key)),
982
- /* @__PURE__ */ jsx("td", { className: "actions-col", onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxs("div", { className: "row-actions", children: [
983
- onView ? /* @__PURE__ */ jsx("button", { type: "button", className: "ghost row-action", onClick: () => onView(item), children: "View" }) : null,
984
- onUpdate ? /* @__PURE__ */ jsx(
985
- "button",
986
- {
987
- type: "button",
988
- className: "ghost row-action",
989
- disabled: !updateAllowed,
990
- title: updateAllowed ? "Update" : "Update is not available",
991
- onClick: () => onUpdate(item),
992
- children: "Update"
993
- }
994
- ) : null,
995
- onDelete ? /* @__PURE__ */ jsx(
996
- "button",
997
- {
998
- type: "button",
999
- className: "ghost row-action danger",
1000
- disabled: !deleteAllowed,
1001
- title: deleteAllowed ? "Delete" : "Delete is not available",
1002
- onClick: () => onDelete(item),
1003
- children: "Delete"
1004
- }
1005
- ) : null
1006
- ] }) })
1564
+ visibleColumns.map((column) => /* @__PURE__ */ jsx("td", { children: cellText(column, item) }, column.key)),
1565
+ /* @__PURE__ */ jsx("td", { className: "actions-col", onClick: (event) => event.stopPropagation(), children: renderRowActions(item) })
1007
1566
  ]
1008
1567
  },
1009
1568
  key
@@ -1030,7 +1589,7 @@ function RecordWorkspace({
1030
1589
  /* @__PURE__ */ jsx("p", { className: "preview-kicker", children: "Preview" }),
1031
1590
  /* @__PURE__ */ jsx("h3", { children: previewTitle ?? "No record selected" })
1032
1591
  ] }) }),
1033
- /* @__PURE__ */ jsx("div", { className: "preview-panel-body", children: previewItem ? /* @__PURE__ */ jsx(DetailList, { lines: detailLines(previewItem) }) : /* @__PURE__ */ jsx("p", { className: "preview-empty", children: "Hover or click a row to preview its details here." }) })
1592
+ /* @__PURE__ */ jsx("div", { className: "preview-panel-body", children: previewItem ? /* @__PURE__ */ jsx(DetailList, { lines: detailLines(previewItem) }) : /* @__PURE__ */ jsx("p", { className: "preview-empty", children: "Select a row to preview its details here." }) })
1034
1593
  ] }) : null,
1035
1594
  /* @__PURE__ */ jsxs("aside", { className: sideOpen ? "side-rail open" : "side-rail", "aria-label": "Actions and filters", children: [
1036
1595
  /* @__PURE__ */ jsxs(
@@ -1047,153 +1606,102 @@ function RecordWorkspace({
1047
1606
  ]
1048
1607
  }
1049
1608
  ),
1050
- sideOpen ? /* @__PURE__ */ jsxs("div", { className: "side-rail-body", children: [
1051
- /* @__PURE__ */ jsxs("div", { className: "preview-check", children: [
1052
- /* @__PURE__ */ jsx(
1053
- "input",
1054
- {
1055
- type: "checkbox",
1056
- checked: previewEnabled,
1057
- onChange: (event) => setPreviewEnabledValue(event.target.checked),
1058
- "aria-label": "Preview"
1059
- }
1060
- ),
1061
- /* @__PURE__ */ jsx(PreviewIcon, {}),
1062
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "Preview" })
1063
- ] }),
1064
- showAdd ? /* @__PURE__ */ jsxs("button", { type: "button", className: "side-rail-add", onClick: onAdd, children: [
1065
- /* @__PURE__ */ jsx(PlusIcon, {}),
1066
- /* @__PURE__ */ jsx("span", { children: addLabel })
1067
- ] }) : null,
1068
- showDownload ? /* @__PURE__ */ jsxs("div", { className: "side-rail-download", children: [
1069
- /* @__PURE__ */ jsxs(
1070
- "button",
1071
- {
1072
- type: "button",
1073
- className: "ghost side-rail-download-toggle",
1074
- "aria-expanded": downloadOpen,
1075
- disabled: downloadBusy,
1076
- onClick: () => setDownloadOpen((open) => !open),
1077
- children: [
1078
- /* @__PURE__ */ jsx(DownloadIcon, {}),
1079
- /* @__PURE__ */ jsx("span", { children: downloadBusy ? "Downloading\u2026" : "Download" })
1080
- ]
1081
- }
1082
- ),
1083
- downloadOpen ? /* @__PURE__ */ jsx("div", { className: "side-rail-download-formats", role: "group", "aria-label": "Download format", children: EXPORT_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsx(
1084
- "button",
1085
- {
1086
- type: "button",
1087
- className: "ghost side-rail-download-format",
1088
- disabled: downloadBusy,
1089
- onClick: () => requestDownload(option.format),
1090
- children: option.label
1091
- },
1092
- option.format
1093
- )) }) : null
1094
- ] }) : null,
1095
- showFilters ? /* @__PURE__ */ jsxs("div", { className: "side-rail-filters", children: [
1096
- /* @__PURE__ */ jsxs("div", { className: "filter-panel-head", children: [
1097
- /* @__PURE__ */ jsx("h3", { children: "Filters" }),
1098
- /* @__PURE__ */ jsxs(
1099
- "button",
1100
- {
1101
- type: "button",
1102
- className: "ghost filter-clear",
1103
- title: "Reset filters",
1104
- "aria-label": "Reset filters",
1105
- disabled: activeFilterCount === 0,
1106
- onClick: clearFilters,
1107
- children: [
1108
- /* @__PURE__ */ jsx(ResetIcon, {}),
1109
- /* @__PURE__ */ jsx("span", { children: "Reset" })
1110
- ]
1111
- }
1112
- )
1113
- ] }),
1114
- /* @__PURE__ */ jsx("div", { className: "filter-panel-stack", children: filterableColumns.map((column) => /* @__PURE__ */ jsxs("label", { children: [
1115
- column.header,
1116
- column.filterOptions ? /* @__PURE__ */ jsx(
1117
- Select,
1118
- {
1119
- value: filters[column.key] ?? "",
1120
- options: [{ value: "", label: column.filterPlaceholder ?? "All" }, ...column.filterOptions],
1121
- onChange: (value) => changeFilter(column.key, value),
1122
- placeholder: column.filterPlaceholder ?? "All"
1123
- }
1124
- ) : /* @__PURE__ */ jsx(
1125
- "input",
1126
- {
1127
- value: filters[column.key] ?? "",
1128
- onChange: (event) => changeFilter(column.key, event.target.value),
1129
- placeholder: `Filter ${column.header.toLowerCase()}`
1130
- }
1131
- )
1132
- ] }, column.key)) })
1133
- ] }) : null
1134
- ] }) : /* @__PURE__ */ jsxs("div", { className: "side-rail-icons", children: [
1135
- /* @__PURE__ */ jsxs("label", { className: "side-rail-icon preview-check-icon", title: "Preview", children: [
1136
- /* @__PURE__ */ jsx(
1137
- "input",
1138
- {
1139
- type: "checkbox",
1140
- checked: previewEnabled,
1141
- onChange: (event) => setPreviewEnabledValue(event.target.checked),
1142
- "aria-label": "Preview"
1143
- }
1144
- ),
1145
- /* @__PURE__ */ jsx(PreviewIcon, {})
1146
- ] }),
1147
- showAdd ? /* @__PURE__ */ jsx("button", { type: "button", className: "ghost side-rail-icon", title: addLabel, "aria-label": addLabel, onClick: onAdd, children: /* @__PURE__ */ jsx(PlusIcon, {}) }) : null,
1148
- showDownload ? /* @__PURE__ */ jsx(
1149
- "button",
1150
- {
1151
- type: "button",
1152
- className: "ghost side-rail-icon",
1153
- title: "Download",
1154
- "aria-label": "Download",
1155
- "aria-expanded": downloadOpen,
1156
- disabled: downloadBusy,
1157
- onClick: () => {
1158
- setSideOpen(true);
1159
- setDownloadOpen(true);
1160
- },
1161
- children: /* @__PURE__ */ jsx(DownloadIcon, {})
1162
- }
1163
- ) : null,
1164
- showFilters ? /* @__PURE__ */ jsxs(
1165
- "button",
1166
- {
1167
- type: "button",
1168
- className: "ghost side-rail-icon",
1169
- title: "Show filters",
1170
- "aria-label": "Show filters",
1171
- onClick: () => setSideOpen(true),
1172
- children: [
1173
- /* @__PURE__ */ jsx(FilterIcon, {}),
1174
- activeFilterCount > 0 ? /* @__PURE__ */ jsx("span", { className: "filter-badge", children: activeFilterCount }) : null
1175
- ]
1176
- }
1177
- ) : null,
1178
- showFilters ? /* @__PURE__ */ jsx(
1179
- "button",
1180
- {
1181
- type: "button",
1182
- className: "ghost side-rail-icon",
1183
- title: "Reset filters",
1184
- "aria-label": "Reset filters",
1185
- disabled: activeFilterCount === 0,
1186
- onClick: clearFilters,
1187
- children: /* @__PURE__ */ jsx(ResetIcon, {})
1188
- }
1189
- ) : null
1190
- ] })
1609
+ sideOpen ? renderToolsBody({ compactIcons: false }) : renderToolsBody({ compactIcons: true })
1191
1610
  ] })
1192
1611
  ]
1193
1612
  }
1194
1613
  ),
1614
+ isClient ? createPortal(
1615
+ /* @__PURE__ */ jsxs(Fragment, { children: [
1616
+ /* @__PURE__ */ jsx(
1617
+ "button",
1618
+ {
1619
+ type: "button",
1620
+ className: toolsDrawerOpen ? "tools-drawer-backdrop open" : "tools-drawer-backdrop",
1621
+ "aria-label": "Close tools",
1622
+ tabIndex: toolsDrawerOpen ? 0 : -1,
1623
+ onClick: () => setToolsDrawerOpen(false)
1624
+ }
1625
+ ),
1626
+ /* @__PURE__ */ jsxs(
1627
+ "aside",
1628
+ {
1629
+ id: "aksui-tools-drawer",
1630
+ className: toolsDrawerOpen ? "tools-drawer open" : "tools-drawer",
1631
+ "aria-label": "Workspace tools",
1632
+ "aria-hidden": !toolsDrawerOpen,
1633
+ children: [
1634
+ /* @__PURE__ */ jsxs("div", { className: "tools-drawer-head", children: [
1635
+ /* @__PURE__ */ jsxs("div", { children: [
1636
+ /* @__PURE__ */ jsx("p", { className: "tools-drawer-kicker", children: "Workspace" }),
1637
+ /* @__PURE__ */ jsx("h3", { children: "Tools" })
1638
+ ] }),
1639
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ghost tools-drawer-close", onClick: () => setToolsDrawerOpen(false), children: "Close" })
1640
+ ] }),
1641
+ /* @__PURE__ */ jsx("div", { className: "tools-drawer-body", children: renderToolsBody({ compactIcons: false }) })
1642
+ ]
1643
+ }
1644
+ )
1645
+ ] }),
1646
+ document.body
1647
+ ) : null,
1195
1648
  form,
1196
- isClient && tooltip && !previewEnabled ? createPortal(
1649
+ isClient && actionsMenu && actionsMenuItem ? createPortal(
1650
+ /* @__PURE__ */ jsxs(
1651
+ "div",
1652
+ {
1653
+ ref: actionsMenuRef,
1654
+ className: "row-action-menu row-action-menu-portal",
1655
+ role: "menu",
1656
+ style: { left: actionsMenu.x, top: actionsMenu.y },
1657
+ children: [
1658
+ onView ? /* @__PURE__ */ jsx(
1659
+ "button",
1660
+ {
1661
+ type: "button",
1662
+ role: "menuitem",
1663
+ className: "ghost",
1664
+ onClick: () => {
1665
+ setActionsMenu(null);
1666
+ onView(actionsMenuItem);
1667
+ },
1668
+ children: "View"
1669
+ }
1670
+ ) : null,
1671
+ onUpdate ? /* @__PURE__ */ jsx(
1672
+ "button",
1673
+ {
1674
+ type: "button",
1675
+ role: "menuitem",
1676
+ className: "ghost",
1677
+ disabled: !actionsUpdateAllowed,
1678
+ onClick: () => {
1679
+ setActionsMenu(null);
1680
+ onUpdate(actionsMenuItem);
1681
+ },
1682
+ children: "Update"
1683
+ }
1684
+ ) : null,
1685
+ onDelete ? /* @__PURE__ */ jsx(
1686
+ "button",
1687
+ {
1688
+ type: "button",
1689
+ role: "menuitem",
1690
+ className: "ghost danger",
1691
+ disabled: !actionsDeleteAllowed,
1692
+ onClick: () => {
1693
+ setActionsMenu(null);
1694
+ onDelete(actionsMenuItem);
1695
+ },
1696
+ children: "Delete"
1697
+ }
1698
+ ) : null
1699
+ ]
1700
+ }
1701
+ ),
1702
+ document.body
1703
+ ) : null,
1704
+ isClient && tooltip && canShowTooltip ? createPortal(
1197
1705
  /* @__PURE__ */ jsxs("div", { className: "record-tooltip", style: { left: tooltip.x, top: tooltip.y }, role: "tooltip", children: [
1198
1706
  /* @__PURE__ */ jsx("p", { className: "record-tooltip-title", children: title }),
1199
1707
  /* @__PURE__ */ jsx(DetailList, { lines: tooltip.lines })