@juicemantics/veloiq-ui 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,8 +1,9 @@
1
- import React6, { createContext, lazy, useContext, useMemo, useState, useRef, useEffect, useCallback, useLayoutEffect, useSyncExternalStore, Suspense, useId, useImperativeHandle } from 'react';
1
+ import React8, { createContext, lazy, useContext, useMemo, useState, useRef, useEffect, useCallback, useLayoutEffect, useSyncExternalStore, Suspense, useId, useImperativeHandle } from 'react';
2
2
  import { ThemedLayoutV2, Show, List, useForm, DeleteButton, useTable, RefineThemes, Breadcrumb as Breadcrumb$1, Create, useSelect, Edit, ListButton, EditButton, RefreshButton } from '@refinedev/antd';
3
3
  import { useMenu, useGo, useGetIdentity, useLogout, useOne, useApiUrl, useInvalidate, useCan, useCustom, useLogin, useWarnAboutChange } from '@refinedev/core';
4
- import { Typography, Menu, theme, Layout, Space, AutoComplete, Input, Spin, Grid, Form, Drawer, Modal, Button, Tooltip, Skeleton, message, Switch, Divider, Tabs, Alert, Card, Table, Select, DatePicker, InputNumber, Checkbox, Pagination, Collapse, Breadcrumb, Tree, ConfigProvider, Empty, Tag, List as List$1, Popover, Dropdown, Avatar, TimePicker, Upload, Rate, Progress } from 'antd';
5
- import { SearchOutlined, LockOutlined, LogoutOutlined, InfoCircleOutlined, SaveOutlined, UnorderedListOutlined, DownloadOutlined, SettingOutlined, PlusOutlined, LinkOutlined, ShareAltOutlined, BarChartOutlined, ColumnHeightOutlined, SwapOutlined, FilterOutlined, ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined, ArrowLeftOutlined, ArrowRightOutlined, FileTextOutlined, BugOutlined, EyeOutlined, EditOutlined, FilePdfOutlined, CloseCircleOutlined, DownOutlined, UserOutlined, ReloadOutlined, ClockCircleOutlined, PushpinFilled, PushpinOutlined, DashboardOutlined, CheckCircleOutlined, CopyOutlined, ApartmentOutlined, SaveFilled, CalendarOutlined, MenuOutlined, MenuUnfoldOutlined, MenuFoldOutlined, LayoutOutlined, AppstoreOutlined, CommentOutlined, MinusSquareOutlined, FullscreenOutlined, CloseOutlined, DatabaseOutlined, ShopOutlined, BookOutlined, CheckOutlined, UploadOutlined, FolderOutlined, FileOutlined, RightOutlined } from '@ant-design/icons';
4
+ import { Typography, Menu, theme, Layout, Space, AutoComplete, Input, Spin, ConfigProvider, Row, Col, Card, Divider, Grid, Form, Drawer, Modal, Button, Tooltip, Skeleton, message, Switch, Tabs, Alert, Table, Select, DatePicker, InputNumber, Checkbox, Pagination, Collapse, Breadcrumb, Tree, Empty, Tag, List as List$1, Popover, Dropdown, Avatar, TimePicker, Upload, Rate, Progress } from 'antd';
5
+ import * as AntDIcons2 from '@ant-design/icons';
6
+ import { SearchOutlined, CloseOutlined, LockOutlined, LogoutOutlined, InfoCircleOutlined, SaveOutlined, UnorderedListOutlined, DownloadOutlined, SettingOutlined, PlusOutlined, LinkOutlined, ShareAltOutlined, BarChartOutlined, ColumnHeightOutlined, SwapOutlined, FilterOutlined, ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined, ArrowLeftOutlined, ArrowRightOutlined, FileTextOutlined, BugOutlined, EyeOutlined, EditOutlined, FilePdfOutlined, CloseCircleOutlined, DownOutlined, UserOutlined, ReloadOutlined, ClockCircleOutlined, PushpinFilled, PushpinOutlined, DashboardOutlined, CheckCircleOutlined, CopyOutlined, ApartmentOutlined, SaveFilled, CalendarOutlined, MenuOutlined, MenuUnfoldOutlined, MenuFoldOutlined, LayoutOutlined, AppstoreOutlined, BorderInnerOutlined, CommentOutlined, MinusSquareOutlined, FullscreenOutlined, CheckOutlined, UploadOutlined, FolderOutlined, FileOutlined, RightOutlined } from '@ant-design/icons';
6
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
8
  import { useNavigate, useParams, useSearchParams, useLocation, Link, UNSAFE_RouteContext } from 'react-router-dom';
8
9
  import { createPortal } from 'react-dom';
@@ -233,9 +234,66 @@ if (typeof localStorage !== "undefined") {
233
234
  });
234
235
  }
235
236
  }
236
- var HorizontalMenu = () => {
237
+ var KEYWORD_ICON_MAP = [
238
+ [/dashboard|overview|home/i, "DashboardOutlined"],
239
+ [/user|person|people|member|staff|employee|contact|customer|client/i, "UserOutlined"],
240
+ [/team|group|department|division|unit|crew/i, "TeamOutlined"],
241
+ [/role|permission|access|security|privilege|policy/i, "LockOutlined"],
242
+ [/tenant|organization|company|account|workspace|business/i, "BankOutlined"],
243
+ [/task|todo|checklist|backlog|ticket/i, "CheckSquareOutlined"],
244
+ [/project|initiative|program|campaign|sprint|epic/i, "FolderOpenOutlined"],
245
+ [/invoice|bill|payment|financ|transaction|ledger|accounting|receipt/i, "FileTextOutlined"],
246
+ [/product|catalog|inventory|stock|sku|variant/i, "ShoppingOutlined"],
247
+ [/order|purchase|sale|cart|checkout|shipment/i, "ShoppingCartOutlined"],
248
+ [/setting|config|preference|option|setup/i, "SettingOutlined"],
249
+ [/report|analytic|metric|stat|chart|analysis|insight/i, "BarChartOutlined"],
250
+ [/document|file|attachment|note|memo|contract|paper/i, "FileOutlined"],
251
+ [/calendar|event|schedule|appointment|booking|slot/i, "CalendarOutlined"],
252
+ [/message|email|notification|comment|chat|inbox|mail/i, "MailOutlined"],
253
+ [/categor|tag|label|class/i, "TagOutlined"],
254
+ [/location|address|region|area|country|city|place|site/i, "EnvironmentOutlined"],
255
+ [/equipment|asset|machine|hardware/i, "ToolOutlined"],
256
+ [/log|audit|histor|trail|activity/i, "HistoryOutlined"],
257
+ [/animal|pet|livestock|breed|horse/i, "DatabaseOutlined"],
258
+ [/building|room|floor|facility|barn|stable|stall/i, "HomeOutlined"],
259
+ [/vehicle|car|truck|fleet|transport|bike/i, "CarOutlined"],
260
+ [/health|medical|clinical|treatment|drug|patient/i, "MedicineBoxOutlined"]
261
+ ];
262
+ function guessIcon(text, isModule = false) {
263
+ const normalized = text.toLowerCase().replace(/[_:-]/g, " ");
264
+ for (const [pattern, icon] of KEYWORD_ICON_MAP) {
265
+ if (pattern.test(normalized)) return icon;
266
+ }
267
+ return isModule ? "FolderOutlined" : "TableOutlined";
268
+ }
269
+ function resolveIcon(iconName) {
270
+ const registry = AntDIcons2;
271
+ const IconCls = registry[iconName];
272
+ return IconCls ? React8.createElement(IconCls) : React8.createElement(registry["TableOutlined"]);
273
+ }
274
+ function getNavEntry(navConfig, key) {
275
+ return navConfig.find((e) => e.key === key);
276
+ }
277
+ function sortItemsByNavConfig(items, navConfig) {
278
+ return [...items].sort((a, b) => {
279
+ const aSeq = getNavEntry(navConfig, a.key ?? a.name ?? "")?.sequence ?? 999;
280
+ const bSeq = getNavEntry(navConfig, b.key ?? b.name ?? "")?.sequence ?? 999;
281
+ return aSeq - bSeq;
282
+ });
283
+ }
284
+ var HorizontalMenu = ({ navConfig = [] }) => {
237
285
  const { menuItems, selectedKey } = useMenu();
238
286
  const go = useGo();
287
+ const getIcon = (item) => {
288
+ const key = String(item?.key || "");
289
+ const label = String(item?.label || item?.name || "");
290
+ const isModule = key.startsWith("module:") || key === "dashboard";
291
+ const entry = getNavEntry(navConfig, key);
292
+ const iconName = entry?.icon ?? guessIcon(label || key, isModule);
293
+ const Icon = AntDIcons2[iconName];
294
+ const Fallback = AntDIcons2["DatabaseOutlined"];
295
+ return Icon ? /* @__PURE__ */ jsx(Icon, {}) : /* @__PURE__ */ jsx(Fallback, {});
296
+ };
239
297
  const resolveModelSeed = (item) => {
240
298
  const route = String(item?.route || "");
241
299
  const routeParts = route.split("/").filter(Boolean);
@@ -271,7 +329,7 @@ var HorizontalMenu = () => {
271
329
  return {
272
330
  key: item.key,
273
331
  label: renderLabel(item, depth, hasChildren),
274
- icon: item.icon,
332
+ icon: getIcon(item),
275
333
  onClick: hasChildren ? void 0 : () => go({ to: item.route }),
276
334
  children: hasChildren ? transformItems(item.children, depth + 1) : void 0
277
335
  };
@@ -292,27 +350,20 @@ var HorizontalMenu = () => {
292
350
  }
293
351
  );
294
352
  };
295
- var CustomSider = ({ collapsed, logo, appTitle }) => {
353
+ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
296
354
  const { token } = theme.useToken();
297
355
  const { mode } = useContext(ColorModeContext);
298
356
  const { menuItems, selectedKey } = useMenu();
299
357
  const go = useGo();
300
358
  const getIcon = (item) => {
301
- const key = String(item?.key || "").toLowerCase();
302
- switch (key) {
303
- case "dashboard":
304
- return /* @__PURE__ */ jsx(DashboardOutlined, {});
305
- case "module:pim":
306
- return /* @__PURE__ */ jsx(DatabaseOutlined, {});
307
- case "module:alloplan":
308
- return /* @__PURE__ */ jsx(BarChartOutlined, {});
309
- case "module:catim":
310
- return /* @__PURE__ */ jsx(BookOutlined, {});
311
- case "module:bsim":
312
- return /* @__PURE__ */ jsx(ShopOutlined, {});
313
- default:
314
- return /* @__PURE__ */ jsx(DatabaseOutlined, {});
315
- }
359
+ const key = String(item?.key || "");
360
+ const label = String(item?.label || item?.name || "");
361
+ const isModule = key.startsWith("module:") || key === "dashboard";
362
+ const entry = getNavEntry(navConfig, key);
363
+ const iconName = entry?.icon ?? guessIcon(label || key, isModule);
364
+ const Icon = AntDIcons2[iconName];
365
+ const Fallback = AntDIcons2["DatabaseOutlined"];
366
+ return Icon ? /* @__PURE__ */ jsx(Icon, {}) : /* @__PURE__ */ jsx(Fallback, {});
316
367
  };
317
368
  const resolveModelSeed = (item) => {
318
369
  const route = String(item?.route || "");
@@ -349,13 +400,17 @@ var CustomSider = ({ collapsed, logo, appTitle }) => {
349
400
  return {
350
401
  key: item.key,
351
402
  label: renderLabel(item, depth, hasChildren),
352
- icon: item.icon || getIcon(item),
403
+ icon: getIcon(item),
353
404
  onClick: hasChildren ? void 0 : () => go({ to: item.route }),
354
405
  children: hasChildren ? transformItems(item.children, depth + 1) : void 0
355
406
  };
356
407
  });
357
408
  };
358
- const items = useMemo(() => transformItems(menuItems), [menuItems, mode]);
409
+ const sortedMenuItems = useMemo(
410
+ () => navConfig.length > 0 ? sortItemsByNavConfig(menuItems, navConfig) : menuItems,
411
+ [menuItems, navConfig]
412
+ );
413
+ const items = useMemo(() => transformItems(sortedMenuItems), [sortedMenuItems, mode, navConfig]);
359
414
  return /* @__PURE__ */ jsx(
360
415
  Layout.Sider,
361
416
  {
@@ -669,6 +724,255 @@ var GlobalSearch = () => {
669
724
  }
670
725
  ) });
671
726
  };
727
+ function resolveAntIcon(iconName) {
728
+ const Icon = AntDIcons2[iconName];
729
+ const Fallback = AntDIcons2["TableOutlined"];
730
+ return Icon ? /* @__PURE__ */ jsx(Icon, {}) : /* @__PURE__ */ jsx(Fallback, {});
731
+ }
732
+ var CommandCenterPortal = ({
733
+ open,
734
+ onClose,
735
+ navConfig = []
736
+ }) => {
737
+ const { menuItems } = useMenu();
738
+ const go = useGo();
739
+ const searchRef = useRef(null);
740
+ const [query, setQuery] = useState("");
741
+ useEffect(() => {
742
+ if (open) {
743
+ setQuery("");
744
+ const t = setTimeout(() => searchRef.current?.focus(), 60);
745
+ return () => clearTimeout(t);
746
+ }
747
+ }, [open]);
748
+ useEffect(() => {
749
+ if (!open) return;
750
+ const handler = (e) => {
751
+ if (e.key === "Escape") onClose();
752
+ };
753
+ window.addEventListener("keydown", handler);
754
+ return () => window.removeEventListener("keydown", handler);
755
+ }, [open, onClose]);
756
+ const modules = useMemo(() => {
757
+ const q2 = query.toLowerCase().trim();
758
+ const moduleItems = menuItems.filter((item) => item.children && item.children.length > 0);
759
+ const sorted = navConfig.length > 0 ? sortItemsByNavConfig(moduleItems, navConfig) : moduleItems;
760
+ if (!q2) return sorted;
761
+ return sorted.map((module) => {
762
+ const moduleMatch = (module.label || "").toLowerCase().includes(q2);
763
+ const filteredChildren = (module.children || []).filter(
764
+ (child) => (child.label || "").toLowerCase().includes(q2)
765
+ );
766
+ if (!moduleMatch && filteredChildren.length === 0) return null;
767
+ return moduleMatch ? module : { ...module, children: filteredChildren };
768
+ }).filter((m) => m !== null);
769
+ }, [menuItems, query, navConfig]);
770
+ if (!open) return null;
771
+ const getItemIcon = (key, label, isModule) => {
772
+ const entry = getNavEntry(navConfig, key);
773
+ return resolveAntIcon(entry?.icon ?? guessIcon(label || key, isModule));
774
+ };
775
+ return /* @__PURE__ */ jsx(ConfigProvider, { theme: { algorithm: theme.darkAlgorithm }, children: /* @__PURE__ */ jsxs(
776
+ "div",
777
+ {
778
+ onClick: (e) => {
779
+ if (e.target === e.currentTarget) onClose();
780
+ },
781
+ style: {
782
+ position: "fixed",
783
+ inset: 0,
784
+ zIndex: 2e3,
785
+ backdropFilter: "blur(14px)",
786
+ WebkitBackdropFilter: "blur(14px)",
787
+ backgroundColor: "rgba(5, 5, 18, 0.78)",
788
+ display: "flex",
789
+ flexDirection: "column",
790
+ alignItems: "center",
791
+ paddingTop: 52,
792
+ paddingBottom: 48,
793
+ paddingLeft: 24,
794
+ paddingRight: 24,
795
+ overflowY: "auto"
796
+ },
797
+ children: [
798
+ /* @__PURE__ */ jsx(
799
+ "button",
800
+ {
801
+ onClick: onClose,
802
+ style: {
803
+ position: "fixed",
804
+ top: 14,
805
+ right: 18,
806
+ background: "rgba(255,255,255,0.08)",
807
+ border: "1px solid rgba(255,255,255,0.15)",
808
+ borderRadius: "50%",
809
+ cursor: "pointer",
810
+ color: "rgba(255,255,255,0.65)",
811
+ width: 34,
812
+ height: 34,
813
+ display: "flex",
814
+ alignItems: "center",
815
+ justifyContent: "center",
816
+ fontSize: 14,
817
+ zIndex: 2001,
818
+ outline: "none",
819
+ padding: 0
820
+ },
821
+ title: "Close (Esc)",
822
+ children: /* @__PURE__ */ jsx(CloseOutlined, {})
823
+ }
824
+ ),
825
+ /* @__PURE__ */ jsx(
826
+ Typography.Title,
827
+ {
828
+ level: 3,
829
+ style: {
830
+ color: "#ffffff",
831
+ marginTop: 0,
832
+ marginBottom: 28,
833
+ letterSpacing: "0.06em",
834
+ fontWeight: 200,
835
+ textTransform: "uppercase",
836
+ fontSize: 18
837
+ },
838
+ children: "Command Center"
839
+ }
840
+ ),
841
+ /* @__PURE__ */ jsx("div", { style: { width: "100%", maxWidth: 600, marginBottom: 36 }, children: /* @__PURE__ */ jsx(
842
+ Input,
843
+ {
844
+ ref: searchRef,
845
+ size: "large",
846
+ placeholder: "Search modules and models\u2026",
847
+ prefix: /* @__PURE__ */ jsx(SearchOutlined, { style: { color: "rgba(255,255,255,0.4)", fontSize: 16 } }),
848
+ value: query,
849
+ onChange: (e) => setQuery(e.target.value),
850
+ allowClear: true,
851
+ style: { fontSize: 15, height: 52, borderRadius: 10 }
852
+ }
853
+ ) }),
854
+ /* @__PURE__ */ jsx("div", { style: { width: "100%", maxWidth: 1200 }, children: modules.length === 0 && query ? /* @__PURE__ */ jsx("div", { style: { textAlign: "center", paddingTop: 56 }, children: /* @__PURE__ */ jsxs(Typography.Text, { style: { color: "rgba(255,255,255,0.35)", fontSize: 16 }, children: [
855
+ "No results for \u201C",
856
+ query,
857
+ "\u201D"
858
+ ] }) }) : /* @__PURE__ */ jsx(Row, { gutter: [20, 20], children: modules.map((module) => {
859
+ const moduleKey = String(module.key || module.name || "");
860
+ const moduleLabel = String(module.label || module.name || "");
861
+ const tone = getModelTone(moduleKey);
862
+ const moduleIcon = getItemIcon(moduleKey, moduleLabel, true);
863
+ const children = navConfig.length > 0 ? sortItemsByNavConfig(module.children || [], navConfig) : module.children || [];
864
+ return /* @__PURE__ */ jsx(Col, { xs: 24, sm: 12, md: 8, lg: 6, children: /* @__PURE__ */ jsxs(
865
+ Card,
866
+ {
867
+ style: {
868
+ background: "rgba(18, 18, 32, 0.95)",
869
+ border: "1px solid rgba(255,255,255,0.08)",
870
+ borderTop: `3px solid ${tone.solid}`,
871
+ borderRadius: 14,
872
+ height: "100%",
873
+ boxShadow: `0 8px 32px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.04)`
874
+ },
875
+ styles: {
876
+ header: {
877
+ background: `linear-gradient(90deg, ${tone.solid}1a 0%, rgba(18,18,32,0.95) 70%)`,
878
+ borderBottom: "1px solid rgba(255,255,255,0.07)",
879
+ padding: "10px 16px",
880
+ minHeight: 52
881
+ },
882
+ body: { padding: "12px 16px 14px", background: "rgba(18,18,32,0.95)" }
883
+ },
884
+ title: /* @__PURE__ */ jsxs(Space, { size: 10, children: [
885
+ /* @__PURE__ */ jsx("div", { style: {
886
+ background: `${tone.solid}28`,
887
+ border: `1px solid ${tone.solid}50`,
888
+ borderRadius: 8,
889
+ width: 32,
890
+ height: 32,
891
+ display: "flex",
892
+ alignItems: "center",
893
+ justifyContent: "center",
894
+ flexShrink: 0
895
+ }, children: /* @__PURE__ */ jsx("span", { style: { color: tone.text, fontSize: 15, display: "flex" }, children: moduleIcon }) }),
896
+ /* @__PURE__ */ jsx(
897
+ Typography.Text,
898
+ {
899
+ style: { color: "#ffffff", fontWeight: 600, fontSize: 14, letterSpacing: "0.01em" },
900
+ children: moduleLabel
901
+ }
902
+ )
903
+ ] }),
904
+ children: [
905
+ children.length > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: children.map((child, idx) => {
906
+ const childKey = String(child.key || child.name || "");
907
+ const childLabel = String(child.label || child.name || "");
908
+ const childTone = getModelTone(childKey);
909
+ const childIcon = getItemIcon(childKey, childLabel, false);
910
+ return /* @__PURE__ */ jsxs(React8.Fragment, { children: [
911
+ idx > 0 && /* @__PURE__ */ jsx(Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.05)" } }),
912
+ /* @__PURE__ */ jsxs(
913
+ "div",
914
+ {
915
+ role: "button",
916
+ tabIndex: 0,
917
+ onClick: () => {
918
+ go({ to: child.route || `/${childKey}` });
919
+ onClose();
920
+ },
921
+ onKeyDown: (e) => {
922
+ if (e.key === "Enter") {
923
+ go({ to: child.route || `/${childKey}` });
924
+ onClose();
925
+ }
926
+ },
927
+ style: {
928
+ display: "flex",
929
+ alignItems: "center",
930
+ gap: 10,
931
+ padding: "7px 10px",
932
+ borderRadius: 8,
933
+ cursor: "pointer",
934
+ transition: "background 0.13s, border-color 0.13s",
935
+ border: "1px solid transparent",
936
+ outline: "none"
937
+ },
938
+ onMouseEnter: (e) => {
939
+ const el = e.currentTarget;
940
+ el.style.background = `${childTone.solid}1a`;
941
+ el.style.borderColor = `${childTone.solid}40`;
942
+ },
943
+ onMouseLeave: (e) => {
944
+ const el = e.currentTarget;
945
+ el.style.background = "transparent";
946
+ el.style.borderColor = "transparent";
947
+ },
948
+ children: [
949
+ /* @__PURE__ */ jsx("span", { style: {
950
+ color: childTone.text,
951
+ fontSize: 13,
952
+ flexShrink: 0,
953
+ display: "flex",
954
+ alignItems: "center",
955
+ opacity: 0.85
956
+ }, children: childIcon }),
957
+ /* @__PURE__ */ jsx(Typography.Text, { style: {
958
+ color: "rgba(220, 220, 240, 0.88)",
959
+ fontSize: 13,
960
+ fontWeight: 400
961
+ }, children: childLabel })
962
+ ]
963
+ }
964
+ )
965
+ ] }, childKey);
966
+ }) }),
967
+ children.length === 0 && /* @__PURE__ */ jsx(Typography.Text, { style: { color: "rgba(255,255,255,0.2)", fontSize: 12 }, children: "No models" })
968
+ ]
969
+ }
970
+ ) }, moduleKey);
971
+ }) }) })
972
+ ]
973
+ }
974
+ ) });
975
+ };
672
976
  var API_URL2 = "/api";
673
977
  var DefaultLogo = ({ logo, appTitle, collapsed, isHeader = false, hideTitle = false }) => {
674
978
  const logoEl = typeof logo === "string" ? /* @__PURE__ */ jsx("img", { src: logo, alt: appTitle || "App", style: { height: isHeader ? "32px" : "40px", width: "auto", marginRight: collapsed || hideTitle ? 0 : 10 } }) : logo ? /* @__PURE__ */ jsx("span", { style: { marginRight: collapsed || hideTitle ? 0 : 10, display: "flex", alignItems: "center" }, children: logo }) : null;
@@ -704,7 +1008,8 @@ var LayoutWrapper = ({
704
1008
  children,
705
1009
  logo,
706
1010
  appTitle,
707
- extraUserMenuItems = []
1011
+ extraUserMenuItems = [],
1012
+ navConfig = []
708
1013
  }) => {
709
1014
  const [layoutMode, setLayoutMode] = useState(
710
1015
  () => localStorage.getItem("layoutMode") || "vertical"
@@ -722,6 +1027,17 @@ var LayoutWrapper = ({
722
1027
  const [pwdLoading, setPwdLoading] = useState(false);
723
1028
  const [pwdForm] = Form.useForm();
724
1029
  const [drawerOpen, setDrawerOpen] = useState(false);
1030
+ const [portalOpen, setPortalOpen] = useState(false);
1031
+ useEffect(() => {
1032
+ const handler = (e) => {
1033
+ if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "g") {
1034
+ e.preventDefault();
1035
+ setPortalOpen((prev) => !prev);
1036
+ }
1037
+ };
1038
+ window.addEventListener("keydown", handler);
1039
+ return () => window.removeEventListener("keydown", handler);
1040
+ }, []);
725
1041
  const toggleSider = () => {
726
1042
  const next = !siderCollapsed;
727
1043
  setSiderCollapsed(next);
@@ -781,23 +1097,33 @@ var LayoutWrapper = ({
781
1097
  layoutMode === "horizontal" && /* @__PURE__ */ jsxs(Fragment, { children: [
782
1098
  isMobile && /* @__PURE__ */ jsx(Tooltip, { title: "Open menu", children: /* @__PURE__ */ jsx(Button, { type: "text", icon: /* @__PURE__ */ jsx(MenuOutlined, {}), onClick: () => setDrawerOpen(true), style: { marginRight: 6, flexShrink: 0 } }) }),
783
1099
  /* @__PURE__ */ jsx("div", { style: { marginRight: isMobile ? 4 : 10, flexShrink: 0 }, children: /* @__PURE__ */ jsx(DefaultLogo, { logo, appTitle, isHeader: true, hideTitle: isMobile }) }),
784
- !isMobile && /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx(HorizontalMenu, {}) })
1100
+ !isMobile && /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx(HorizontalMenu, { navConfig }) })
785
1101
  ] })
786
1102
  ] }),
787
1103
  /* @__PURE__ */ jsx("div", { style: { flexShrink: 0, marginLeft: 4, marginRight: 4 }, children: /* @__PURE__ */ jsx(GlobalSearch, {}) }),
788
1104
  /* @__PURE__ */ jsxs(Space, { size: isMobile ? "small" : "middle", style: { flexShrink: 0, marginLeft: 6 }, children: [
789
- /* @__PURE__ */ jsx(Tooltip, { title: layoutMode === "vertical" ? "Top Menu" : "Sidebar", children: /* @__PURE__ */ jsx(
790
- Button,
791
- {
792
- icon: layoutMode === "vertical" ? /* @__PURE__ */ jsx(LayoutOutlined, {}) : /* @__PURE__ */ jsx(AppstoreOutlined, {}),
793
- onClick: () => {
794
- const next = layoutMode === "vertical" ? "horizontal" : "vertical";
795
- setLayoutMode(next);
796
- localStorage.setItem("layoutMode", next);
797
- },
798
- type: "text"
799
- }
800
- ) }),
1105
+ /* @__PURE__ */ jsxs(Space.Compact, { children: [
1106
+ /* @__PURE__ */ jsx(Tooltip, { title: layoutMode === "vertical" ? "Top Menu" : "Sidebar", children: /* @__PURE__ */ jsx(
1107
+ Button,
1108
+ {
1109
+ icon: layoutMode === "vertical" ? /* @__PURE__ */ jsx(LayoutOutlined, {}) : /* @__PURE__ */ jsx(AppstoreOutlined, {}),
1110
+ onClick: () => {
1111
+ const next = layoutMode === "vertical" ? "horizontal" : "vertical";
1112
+ setLayoutMode(next);
1113
+ localStorage.setItem("layoutMode", next);
1114
+ },
1115
+ type: "text"
1116
+ }
1117
+ ) }),
1118
+ /* @__PURE__ */ jsx(Tooltip, { title: "Command Center (Ctrl+G)", children: /* @__PURE__ */ jsx(
1119
+ Button,
1120
+ {
1121
+ icon: /* @__PURE__ */ jsx(BorderInnerOutlined, {}),
1122
+ onClick: () => setPortalOpen(true),
1123
+ type: "text"
1124
+ }
1125
+ ) })
1126
+ ] }),
801
1127
  /* @__PURE__ */ jsx(Tooltip, { title: mode === "dark" ? "Light mode" : "Dark mode", children: /* @__PURE__ */ jsx(
802
1128
  Switch,
803
1129
  {
@@ -814,7 +1140,7 @@ var LayoutWrapper = ({
814
1140
  ] }) })
815
1141
  ] })
816
1142
  ] });
817
- const SiderToRender = layoutMode === "vertical" && !isMobile ? () => /* @__PURE__ */ jsx(CustomSider, { collapsed: siderCollapsed, logo, appTitle }) : () => null;
1143
+ const SiderToRender = layoutMode === "vertical" && !isMobile ? () => /* @__PURE__ */ jsx(CustomSider, { collapsed: siderCollapsed, logo, appTitle, navConfig }) : () => null;
818
1144
  return /* @__PURE__ */ jsxs(Fragment, { children: [
819
1145
  /* @__PURE__ */ jsx(
820
1146
  ThemedLayoutV2,
@@ -826,6 +1152,14 @@ var LayoutWrapper = ({
826
1152
  },
827
1153
  layoutMode
828
1154
  ),
1155
+ /* @__PURE__ */ jsx(
1156
+ CommandCenterPortal,
1157
+ {
1158
+ open: portalOpen,
1159
+ onClose: () => setPortalOpen(false),
1160
+ navConfig
1161
+ }
1162
+ ),
829
1163
  /* @__PURE__ */ jsx(
830
1164
  Drawer,
831
1165
  {
@@ -3662,7 +3996,7 @@ var extractButtonLabel = (node) => {
3662
3996
  }
3663
3997
  return null;
3664
3998
  }
3665
- if (React6.isValidElement(node)) {
3999
+ if (React8.isValidElement(node)) {
3666
4000
  return extractButtonLabel(node.props?.children);
3667
4001
  }
3668
4002
  return null;
@@ -3679,14 +4013,14 @@ var renderIconOnlyButtons = (nodes) => {
3679
4013
  const enhanceNode = (node, index) => {
3680
4014
  if (node === null || node === void 0 || typeof node === "boolean") return node;
3681
4015
  if (Array.isArray(node)) return node.map((child, childIndex) => enhanceNode(child, childIndex));
3682
- if (!React6.isValidElement(node)) return node;
4016
+ if (!React8.isValidElement(node)) return node;
3683
4017
  const componentName = node.type?.displayName || node.type?.name;
3684
4018
  if (componentName === "RefreshButton") return null;
3685
4019
  const fallbackLabel = componentName ? fallbackLabels[componentName] : null;
3686
4020
  const nodeProps = node.props;
3687
4021
  if (fallbackLabel) {
3688
4022
  const label = extractButtonLabel(nodeProps?.children) || fallbackLabel;
3689
- const element = React6.cloneElement(node, {
4023
+ const element = React8.cloneElement(node, {
3690
4024
  ...nodeProps,
3691
4025
  hideText: true,
3692
4026
  children: null
@@ -3697,7 +4031,7 @@ var renderIconOnlyButtons = (nodes) => {
3697
4031
  if (nodeProps?.icon) {
3698
4032
  const label = extractButtonLabel(nodeProps?.children);
3699
4033
  if (label) {
3700
- const element = React6.cloneElement(node, {
4034
+ const element = React8.cloneElement(node, {
3701
4035
  ...nodeProps,
3702
4036
  children: null
3703
4037
  });
@@ -3705,15 +4039,15 @@ var renderIconOnlyButtons = (nodes) => {
3705
4039
  }
3706
4040
  }
3707
4041
  if (nodeProps?.children) {
3708
- const mappedChildren = React6.Children.map(nodeProps.children, (child, childIndex) => enhanceNode(child, childIndex));
3709
- return React6.cloneElement(node, {
4042
+ const mappedChildren = React8.Children.map(nodeProps.children, (child, childIndex) => enhanceNode(child, childIndex));
4043
+ return React8.cloneElement(node, {
3710
4044
  ...nodeProps,
3711
4045
  children: mappedChildren
3712
4046
  });
3713
4047
  }
3714
4048
  return node;
3715
4049
  };
3716
- return React6.Children.map(nodes, (child, index) => enhanceNode(child, index));
4050
+ return React8.Children.map(nodes, (child, index) => enhanceNode(child, index));
3717
4051
  };
3718
4052
  var ResponsiveHeaderButtons = ({ children }) => {
3719
4053
  const screens = Grid.useBreakpoint();
@@ -3764,7 +4098,7 @@ var extractButtonLabel2 = (node) => {
3764
4098
  }
3765
4099
  return null;
3766
4100
  }
3767
- if (React6.isValidElement(node)) {
4101
+ if (React8.isValidElement(node)) {
3768
4102
  return extractButtonLabel2(node.props?.children);
3769
4103
  }
3770
4104
  return null;
@@ -3782,12 +4116,12 @@ var renderIconOnlyButtons2 = (nodes) => {
3782
4116
  const enhanceNode = (node, index) => {
3783
4117
  if (node === null || node === void 0 || typeof node === "boolean") return node;
3784
4118
  if (Array.isArray(node)) return node.map((child, childIndex) => enhanceNode(child, childIndex));
3785
- if (!React6.isValidElement(node)) return node;
4119
+ if (!React8.isValidElement(node)) return node;
3786
4120
  const componentName = node.type?.displayName || node.type?.name;
3787
4121
  const fallbackLabel = componentName ? fallbackLabels[componentName] : null;
3788
4122
  if (fallbackLabel) {
3789
4123
  const label = extractButtonLabel2(node.props?.children) || fallbackLabel;
3790
- const element = React6.cloneElement(node, {
4124
+ const element = React8.cloneElement(node, {
3791
4125
  ...node.props,
3792
4126
  hideText: true,
3793
4127
  children: null
@@ -3798,7 +4132,7 @@ var renderIconOnlyButtons2 = (nodes) => {
3798
4132
  if (node.props?.icon) {
3799
4133
  const label = extractButtonLabel2(node.props?.children);
3800
4134
  if (label) {
3801
- const element = React6.cloneElement(node, {
4135
+ const element = React8.cloneElement(node, {
3802
4136
  ...node.props,
3803
4137
  children: null
3804
4138
  });
@@ -3806,15 +4140,15 @@ var renderIconOnlyButtons2 = (nodes) => {
3806
4140
  }
3807
4141
  }
3808
4142
  if (node.props?.children) {
3809
- const mappedChildren = React6.Children.map(node.props.children, (child, childIndex) => enhanceNode(child, childIndex));
3810
- return React6.cloneElement(node, {
4143
+ const mappedChildren = React8.Children.map(node.props.children, (child, childIndex) => enhanceNode(child, childIndex));
4144
+ return React8.cloneElement(node, {
3811
4145
  ...node.props,
3812
4146
  children: mappedChildren
3813
4147
  });
3814
4148
  }
3815
4149
  return node;
3816
4150
  };
3817
- return React6.Children.map(nodes, (child, index) => enhanceNode(child, index));
4151
+ return React8.Children.map(nodes, (child, index) => enhanceNode(child, index));
3818
4152
  };
3819
4153
  var renderStandardShowHeaderButtons = ({
3820
4154
  listButtonProps,
@@ -3978,7 +4312,7 @@ var wrappedPageTitleStyle2 = {
3978
4312
  };
3979
4313
  var renderWrappedPageTitle = (title) => {
3980
4314
  if (title === null || title === void 0 || title === false) return title;
3981
- return React6.createElement("div", { style: wrappedPageTitleStyle2 }, title);
4315
+ return React8.createElement("div", { style: wrappedPageTitleStyle2 }, title);
3982
4316
  };
3983
4317
  var numberFormatter = new Intl.NumberFormat(void 0, { maximumFractionDigits: 0 });
3984
4318
  var decimalFormatter = new Intl.NumberFormat(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
@@ -6887,7 +7221,7 @@ var useShowActionsPreferences = (model, allModels, record, saveButtonProps) => {
6887
7221
  headerButtons
6888
7222
  };
6889
7223
  };
6890
- var PrimaryShowContext = React6.createContext(null);
7224
+ var PrimaryShowContext = React8.createContext(null);
6891
7225
  var ToneSharedStyles = () => /* @__PURE__ */ jsx("style", { children: `
6892
7226
  .jm-tone-scope .ant-form-item .ant-form-item-label > label {
6893
7227
  color: #475569 !important;
@@ -7331,7 +7665,7 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
7331
7665
  const resolvedResource = resourceName && allModels ? resolveResourcePath(resourceName, allModels) : resourceName;
7332
7666
  const referencedModel = resourceName ? findModelByName(allModels, resourceName) : void 0;
7333
7667
  const resolvedOptionValue = field.optionValue || referencedModel?.pkField || "eid";
7334
- const [loadAll, setLoadAll] = React6.useState(false);
7668
+ const [loadAll, setLoadAll] = React8.useState(false);
7335
7669
  const pageSize = loadAll ? 999999 : RELATION_SELECT_DEFAULT_PAGE_SIZE;
7336
7670
  const { selectProps, queryResult } = useSelect({
7337
7671
  resource: resolvedResource,
@@ -7348,8 +7682,8 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
7348
7682
  const loadedCount = filteredOptions?.length ?? 0;
7349
7683
  const isCapped = !loadAll && serverTotal > loadedCount && loadedCount > 0;
7350
7684
  const normalizeSearch = (val) => String(val ?? "").toLowerCase();
7351
- const selectedSet = React6.useMemo(() => new Set(Array.isArray(value) ? value : value !== void 0 && value !== null ? [value] : []), [value]);
7352
- const [searchValue, setSearchValue] = React6.useState("");
7685
+ const selectedSet = React8.useMemo(() => new Set(Array.isArray(value) ? value : value !== void 0 && value !== null ? [value] : []), [value]);
7686
+ const [searchValue, setSearchValue] = React8.useState("");
7353
7687
  return /* @__PURE__ */ jsxs("div", { children: [
7354
7688
  /* @__PURE__ */ jsx(
7355
7689
  Select,
@@ -11433,6 +11767,20 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
11433
11767
  const filteredRows = useMemo(() => {
11434
11768
  return applyFilterRules(applyGlobalSearch(rows || []));
11435
11769
  }, [applyFilterRules, applyGlobalSearch, rows]);
11770
+ const columnFilteredRows = useMemo(() => {
11771
+ const activeEntries = Object.entries(columnFiltersSelected).filter(([, values]) => values && values.length > 0);
11772
+ if (activeEntries.length === 0) return filteredRows;
11773
+ return filteredRows.filter(
11774
+ (row) => activeEntries.every(
11775
+ ([fieldKey, selectedValues]) => selectedValues.some((value) => {
11776
+ if (fieldKey === "eid" && row?._label) {
11777
+ return String(row._label) === String(value) || String(row.eid) === String(value);
11778
+ }
11779
+ return String(row?.[fieldKey]) === String(value);
11780
+ })
11781
+ )
11782
+ );
11783
+ }, [filteredRows, columnFiltersSelected]);
11436
11784
  useEffect(() => {
11437
11785
  setCurrentPage(1);
11438
11786
  }, [localSearch, filterRules]);
@@ -11867,7 +12215,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
11867
12215
  return parts.filter(Boolean).join(" \u2022 ");
11868
12216
  }, [categoryField1, categoryField2, relatedModel.fields, relatedModel.label, relatedModel.name]);
11869
12217
  const chartData = useMemo(() => {
11870
- const data = filteredRows || [];
12218
+ const data = columnFilteredRows || [];
11871
12219
  const cat1Field = categoryField1 ? relatedModel.fields.find((field) => field.key === categoryField1) : void 0;
11872
12220
  const cat2Field = categoryField2 ? relatedModel.fields.find((field) => field.key === categoryField2) : void 0;
11873
12221
  const groupMap = /* @__PURE__ */ new Map();
@@ -11972,7 +12320,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
11972
12320
  seriesLabels,
11973
12321
  filteredRawRows
11974
12322
  };
11975
- }, [filteredRows, categoryField1, categoryField2, relatedModel.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
12323
+ }, [columnFilteredRows, categoryField1, categoryField2, relatedModel.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
11976
12324
  const numericColumnMaxes = useMemo(() => {
11977
12325
  const maxes = {};
11978
12326
  const data = filteredRows || [];
@@ -12186,8 +12534,8 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12186
12534
  });
12187
12535
  }, [selectedColumnKeys]);
12188
12536
  const statsSummary = useMemo(() => {
12189
- return buildStatsSummary(filteredRows, displayFields, labelCache);
12190
- }, [filteredRows, displayFields, labelCache]);
12537
+ return buildStatsSummary(columnFilteredRows, displayFields, labelCache);
12538
+ }, [columnFilteredRows, displayFields, labelCache]);
12191
12539
  const isTotalsDetailsVariant = viewVariant === "totals-details";
12192
12540
  const getDefaultTotalsSummaryFn = useCallback((field) => {
12193
12541
  if (field.key === "eid") return "count";
@@ -13199,7 +13547,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13199
13547
  ] })
13200
13548
  ] })
13201
13549
  ] }),
13202
- analyzeOpen && filteredRows.length > 0 && analyzePrefsReady && /* @__PURE__ */ jsx("div", { style: analyzeContainerStyle, children: /* @__PURE__ */ jsx(
13550
+ analyzeOpen && columnFilteredRows.length > 0 && analyzePrefsReady && /* @__PURE__ */ jsx("div", { style: analyzeContainerStyle, children: /* @__PURE__ */ jsx(
13203
13551
  Card,
13204
13552
  {
13205
13553
  size: "small",
@@ -14807,6 +15155,55 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
14807
15155
  const baseRows = allRows || [];
14808
15156
  return applyFilterRules(applyGlobalSearch(baseRows));
14809
15157
  }, [allRows, applyFilterRules, applyGlobalSearch, isClientFiltering, tableProps.dataSource]);
15158
+ const columnFilteredDataSource = useMemo(() => {
15159
+ const activeEntries = Object.entries(columnFiltersSelected).filter(([, values]) => values && values.length > 0);
15160
+ if (activeEntries.length === 0) return filteredDataSource;
15161
+ return filteredDataSource.filter(
15162
+ (record) => activeEntries.every(([fieldKey, selectedValues]) => {
15163
+ const field = model.fields.find((f) => f.key === fieldKey);
15164
+ if (!field) return true;
15165
+ return selectedValues.some((value) => {
15166
+ const strValue = String(value);
15167
+ if (field.type === "number" && !field.reference && strValue.startsWith("__range__:")) {
15168
+ const parts = strValue.split(":");
15169
+ const lo = Number(parts[1]);
15170
+ const hi = Number(parts[2]);
15171
+ const recordVal = Number(record?.[field.key]);
15172
+ if (isNaN(recordVal)) return false;
15173
+ return recordVal >= lo && recordVal <= hi;
15174
+ }
15175
+ if ((field.type === "date" || field.type === "datetime") && strValue.startsWith("__daterange__:")) {
15176
+ const sub = strValue.substring("__daterange__:".length);
15177
+ const sepIdx = sub.indexOf(":");
15178
+ const lo = decodeURIComponent(sub.substring(0, sepIdx));
15179
+ const hi = decodeURIComponent(sub.substring(sepIdx + 1));
15180
+ const recordVal = String(record?.[field.key] ?? "").substring(0, 10);
15181
+ return recordVal >= lo && recordVal <= hi;
15182
+ }
15183
+ if (field.type === "string" && !field.reference && strValue.startsWith("__catrange__:")) {
15184
+ const sub = strValue.substring("__catrange__:".length);
15185
+ const sepIdx = sub.indexOf(":");
15186
+ const lo = decodeURIComponent(sub.substring(0, sepIdx));
15187
+ const hi = decodeURIComponent(sub.substring(sepIdx + 1));
15188
+ const recordVal = String(record?.[field.key] ?? "");
15189
+ return recordVal.localeCompare(lo) >= 0 && recordVal.localeCompare(hi) <= 0;
15190
+ }
15191
+ if (field.key === "eid" && strValue.startsWith("__catrange__:")) {
15192
+ const sub = strValue.substring("__catrange__:".length);
15193
+ const sepIdx = sub.indexOf(":");
15194
+ const lo = decodeURIComponent(sub.substring(0, sepIdx));
15195
+ const hi = decodeURIComponent(sub.substring(sepIdx + 1));
15196
+ const recordLabel = String(record?._label ?? "");
15197
+ return recordLabel.localeCompare(lo) >= 0 && recordLabel.localeCompare(hi) <= 0;
15198
+ }
15199
+ if (field.key === "eid" && record?._label) {
15200
+ return String(record._label) === strValue || String(record.eid) === strValue;
15201
+ }
15202
+ return String(record?.[field.key]) === strValue;
15203
+ });
15204
+ })
15205
+ );
15206
+ }, [filteredDataSource, columnFiltersSelected, model.fields]);
14810
15207
  useEffect(() => {
14811
15208
  setGalleryPage(1);
14812
15209
  }, [localSearch, filterRules, resolvedListViewType]);
@@ -15634,7 +16031,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
15634
16031
  return String(raw);
15635
16032
  }, [labelCache]);
15636
16033
  const chartData = useMemo(() => {
15637
- const data = allRows || [];
16034
+ const data = columnFilteredDataSource || [];
15638
16035
  const cat1Field = categoryField1 ? model.fields.find((field) => field.key === categoryField1) : void 0;
15639
16036
  const cat2Field = categoryField2 ? model.fields.find((field) => field.key === categoryField2) : void 0;
15640
16037
  const groupMap = /* @__PURE__ */ new Map();
@@ -15738,7 +16135,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
15738
16135
  seriesLabels,
15739
16136
  filteredRawRows
15740
16137
  };
15741
- }, [allRows, categoryField1, categoryField2, model.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
16138
+ }, [columnFilteredDataSource, categoryField1, categoryField2, model.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
15742
16139
  const chartSignature = useMemo(() => {
15743
16140
  return JSON.stringify({
15744
16141
  chartType,
@@ -15753,8 +16150,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
15753
16150
  });
15754
16151
  }, [chartType, summaryFn, categoryField1, categoryField2, rankingMode, rankingFieldKey, rankingN, chartData]);
15755
16152
  const statsSummary = useMemo(() => {
15756
- return buildStatsSummary(allRows, displayFields, labelCache);
15757
- }, [allRows, displayFields, labelCache]);
16153
+ return buildStatsSummary(columnFilteredDataSource, displayFields, labelCache);
16154
+ }, [columnFilteredDataSource, displayFields, labelCache]);
15758
16155
  const tdCategoricalBoxes = useMemo(() => {
15759
16156
  if (!isTotalsDetailsView) return [];
15760
16157
  return displayFields.filter((field) => field.type !== "number" || Boolean(field.reference)).map((field) => {
@@ -19499,7 +19896,7 @@ function usePinnedRecords() {
19499
19896
  setLoading(false);
19500
19897
  }
19501
19898
  }, []);
19502
- React6.useEffect(() => {
19899
+ React8.useEffect(() => {
19503
19900
  load();
19504
19901
  }, [load]);
19505
19902
  return { groups, loading, reload: load };
@@ -19837,6 +20234,6 @@ var authSystemModels = [
19837
20234
  }
19838
20235
  ];
19839
20236
 
19840
- export { API_URL3 as API_URL, AllModelsProvider, ColorModeContext, ColorModeContextProvider, CustomSider, DashboardPage, DynamicCreate, DynamicEdit, DynamicList, DynamicShow, ExecutableHtml, GlobalSearch, HierarchyView, HorizontalMenu, InlinePlotlyHtml, LayoutWrapper, LoginPage, ModelHeading, MultiPaneLayout, PaneNavigationContext, PinnedRecordsPanel, PrimaryShowContext, RecentActivityPanel, ReferenceField, ResourceContext, ShowFooterButtons, StandardList, StandardShow, ViewsGrid, accessControlProvider, authProvider, authSystemModels, authenticatedFetch, buildShowTabFormOptions, generateResources, getModelTone, httpClient, normalizeToneKey, renderRelationBlock, setColorSchemas, useAllModels, useKeyboardShortcuts, useMetadataModal, usePaneNavigation, useShowActionsPreferences, useShowEditableForm, useStandardShowTabs };
20237
+ export { API_URL3 as API_URL, AllModelsProvider, ColorModeContext, ColorModeContextProvider, CommandCenterPortal, CustomSider, DashboardPage, DynamicCreate, DynamicEdit, DynamicList, DynamicShow, ExecutableHtml, GlobalSearch, HierarchyView, HorizontalMenu, InlinePlotlyHtml, LayoutWrapper, LoginPage, ModelHeading, MultiPaneLayout, PaneNavigationContext, PinnedRecordsPanel, PrimaryShowContext, RecentActivityPanel, ReferenceField, ResourceContext, ShowFooterButtons, StandardList, StandardShow, ViewsGrid, accessControlProvider, authProvider, authSystemModels, authenticatedFetch, buildShowTabFormOptions, generateResources, getModelTone, getNavEntry, guessIcon, httpClient, normalizeToneKey, renderRelationBlock, resolveIcon, setColorSchemas, sortItemsByNavConfig, useAllModels, useKeyboardShortcuts, useMetadataModal, usePaneNavigation, useShowActionsPreferences, useShowEditableForm, useStandardShowTabs };
19841
20238
  //# sourceMappingURL=index.mjs.map
19842
20239
  //# sourceMappingURL=index.mjs.map