@juicemantics/veloiq-ui 0.2.1 → 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,
@@ -7711,6 +8045,7 @@ var renderInput = (field, allModels, model, currentId) => {
7711
8045
  };
7712
8046
  var _23 = window._ || ((text) => text);
7713
8047
  var { Title: Title2 } = Typography;
8048
+ var requiredMark = (field) => field.required ? /* @__PURE__ */ jsx("span", { style: { color: "#ff4d4f", marginLeft: 3 }, children: "*" }) : null;
7714
8049
  var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedValues }) => {
7715
8050
  const model = useRoleFilteredModel(modelProp);
7716
8051
  applyI18nLabelsToModel(model);
@@ -7966,7 +8301,10 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
7966
8301
  return /* @__PURE__ */ jsx(Form.Item, { name: field.key, hidden: true, rules: field.required ? [{ required: true }] : [], children: renderInput(field, allModels, model) }, `${field.key}-${index}`);
7967
8302
  }
7968
8303
  return /* @__PURE__ */ jsx("div", { style: { marginBottom: 4 }, children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: showLabel ? "200px 1fr" : "1fr", alignItems: "start", columnGap: 6 }, children: [
7969
- showLabel && /* @__PURE__ */ jsx("div", { style: { ...labelStyle, backgroundColor: labelBackground, padding: "2px 4px", borderRadius: 4 }, children: field.label }),
8304
+ showLabel && /* @__PURE__ */ jsxs("div", { style: { ...labelStyle, backgroundColor: labelBackground, padding: "2px 4px", borderRadius: 4 }, children: [
8305
+ field.label,
8306
+ requiredMark(field)
8307
+ ] }),
7970
8308
  /* @__PURE__ */ jsx("div", { style: { padding: "2px 4px", lineHeight: 1.15, background: valueBackground, borderRadius: 6, border: `1px solid ${token.colorBorder}`, maxWidth: "100%", overflowWrap: "anywhere", ...parseInlineStyle(item.html_format) }, children: /* @__PURE__ */ jsx(
7971
8309
  Form.Item,
7972
8310
  {
@@ -8035,7 +8373,10 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
8035
8373
  ...parseInlineStyle(item.html_format)
8036
8374
  };
8037
8375
  return /* @__PURE__ */ jsx("div", { style: { marginBottom: 4 }, children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: showLabel ? "200px 1fr" : "1fr", alignItems: "start", columnGap: 6 }, children: [
8038
- showLabel && /* @__PURE__ */ jsx("div", { style: { ...labelStyle, backgroundColor: labelBackground, padding: "2px 4px", borderRadius: 4 }, children: field.label }),
8376
+ showLabel && /* @__PURE__ */ jsxs("div", { style: { ...labelStyle, backgroundColor: labelBackground, padding: "2px 4px", borderRadius: 4 }, children: [
8377
+ field.label,
8378
+ requiredMark(field)
8379
+ ] }),
8039
8380
  /* @__PURE__ */ jsx("div", { style: readonlyValueStyle, children: renderFieldValue(field, createdRecord, allModels) })
8040
8381
  ] }) }, `${field.key}-${index}`);
8041
8382
  };
@@ -8064,7 +8405,10 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
8064
8405
  return /* @__PURE__ */ jsx(Form.Item, { name: field.key, hidden: true, rules: field.required ? [{ required: true }] : [], children: renderInput(field, allModels, model) }, field.key);
8065
8406
  }
8066
8407
  return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "200px 1fr", justifyContent: "start", alignItems: "start", columnGap: 6 }, children: [
8067
- /* @__PURE__ */ jsx("span", { style: labelStyle, children: field.label }),
8408
+ /* @__PURE__ */ jsxs("span", { style: labelStyle, children: [
8409
+ field.label,
8410
+ requiredMark(field)
8411
+ ] }),
8068
8412
  /* @__PURE__ */ jsx("div", { style: { padding: "2px 4px", lineHeight: 1.15, maxWidth: "100%", overflowWrap: "anywhere" }, children: /* @__PURE__ */ jsx(Form.Item, { name: field.key, rules: field.required ? [{ required: true }] : [], valuePropName: field.type === "boolean" ? "checked" : void 0, getValueProps: (val) => (field.type === "date" || field.type === "datetime") && val ? { value: dayjs8(val) } : field.type === "time" && val ? { value: dayjs8("1970-01-01T" + val) } : { value: val }, style: { margin: 0 }, children: renderInput(field, allModels, model) }) })
8069
8413
  ] }, field.key);
8070
8414
  }) }) })
@@ -8199,7 +8543,10 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
8199
8543
  return /* @__PURE__ */ jsx(Form.Item, { name: field.key, hidden: true, rules: field.required ? [{ required: true }] : [], children: isOtherKey && field.reference && hasReferenceModel(field.reference, allModels) ? /* @__PURE__ */ jsx(RelationSelect, { field, allModels, multiple: true }) : renderInput(field, allModels, model) }, field.key);
8200
8544
  }
8201
8545
  return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "200px 1fr", justifyContent: "start", alignItems: "start", columnGap: 6 }, children: [
8202
- /* @__PURE__ */ jsx("span", { style: labelStyle, children: field.label }),
8546
+ /* @__PURE__ */ jsxs("span", { style: labelStyle, children: [
8547
+ field.label,
8548
+ requiredMark(field)
8549
+ ] }),
8203
8550
  /* @__PURE__ */ jsx("div", { style: { padding: "2px 4px", lineHeight: 1.15, maxWidth: "100%", overflowWrap: "anywhere" }, children: /* @__PURE__ */ jsx(Form.Item, { name: field.key, rules: field.required ? [{ required: true }] : [], style: { margin: 0 }, children: isOtherKey && field.reference && hasReferenceModel(field.reference, allModels) ? /* @__PURE__ */ jsx(RelationSelect, { field, allModels, multiple: true }) : renderInput(field, allModels, model) }) })
8204
8551
  ] }, field.key);
8205
8552
  }) })
@@ -8295,6 +8642,7 @@ var NLSentenceBlock = ({ eid, title: titleProp, showLabel }) => {
8295
8642
  };
8296
8643
  var _24 = window._ || ((text) => text);
8297
8644
  var { Title: Title3 } = Typography;
8645
+ var requiredMark2 = (field) => field.required ? /* @__PURE__ */ jsx("span", { style: { color: "#ff4d4f", marginLeft: 3 }, children: "*" }) : null;
8298
8646
  var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons, journeyCallbacks, idOverride }) => {
8299
8647
  const model = useRoleFilteredModel(modelProp);
8300
8648
  applyI18nLabelsToModel(model);
@@ -8617,7 +8965,10 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
8617
8965
  gap: "4px 6px"
8618
8966
  },
8619
8967
  children: [
8620
- /* @__PURE__ */ jsx("span", { style: { ...labelStyle, flex: "0 0 200px" }, children: field.label }),
8968
+ /* @__PURE__ */ jsxs("span", { style: { ...labelStyle, flex: "0 0 200px" }, children: [
8969
+ field.label,
8970
+ requiredMark2(field)
8971
+ ] }),
8621
8972
  /* @__PURE__ */ jsx("div", { style: { flex: "1 0 200px", padding: "2px 4px", lineHeight: 1.15, overflowWrap: "anywhere", background: valueBackground, borderRadius: 6 }, children: /* @__PURE__ */ jsx(
8622
8973
  Form.Item,
8623
8974
  {
@@ -8762,7 +9113,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
8762
9113
  gap: 2
8763
9114
  },
8764
9115
  children: [
8765
- showLabel && /* @__PURE__ */ jsx(
9116
+ showLabel && /* @__PURE__ */ jsxs(
8766
9117
  "div",
8767
9118
  {
8768
9119
  style: {
@@ -8771,7 +9122,10 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
8771
9122
  padding: "2px 4px",
8772
9123
  borderRadius: 4
8773
9124
  },
8774
- children: field.label
9125
+ children: [
9126
+ field.label,
9127
+ requiredMark2(field)
9128
+ ]
8775
9129
  }
8776
9130
  ),
8777
9131
  /* @__PURE__ */ jsx("div", { style: readonlyValueStyle, children: renderFieldValue(field, record, allModels) })
@@ -8788,7 +9142,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
8788
9142
  gap: 2
8789
9143
  },
8790
9144
  children: [
8791
- showLabel && /* @__PURE__ */ jsx(
9145
+ showLabel && /* @__PURE__ */ jsxs(
8792
9146
  "div",
8793
9147
  {
8794
9148
  style: {
@@ -8797,7 +9151,10 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
8797
9151
  padding: "2px 4px",
8798
9152
  borderRadius: 4
8799
9153
  },
8800
- children: field.label
9154
+ children: [
9155
+ field.label,
9156
+ requiredMark2(field)
9157
+ ]
8801
9158
  }
8802
9159
  ),
8803
9160
  /* @__PURE__ */ jsx("div", { style: {
@@ -8922,7 +9279,10 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
8922
9279
  const showLabel = item.show_label !== false;
8923
9280
  const editable = isAttributeValueEditable(item, "edit");
8924
9281
  return /* @__PURE__ */ jsx("div", { style: { marginBottom: 4 }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: [
8925
- showLabel && /* @__PURE__ */ jsx("div", { style: { ...labelStyle, backgroundColor: labelBackground, padding: "2px 4px", borderRadius: 4 }, children: field.label }),
9282
+ showLabel && /* @__PURE__ */ jsxs("div", { style: { ...labelStyle, backgroundColor: labelBackground, padding: "2px 4px", borderRadius: 4 }, children: [
9283
+ field.label,
9284
+ requiredMark2(field)
9285
+ ] }),
8926
9286
  /* @__PURE__ */ jsx("div", { style: { padding: "2px 4px", lineHeight: 1.15, background: valueBackground, borderRadius: 6, border: `1px solid ${token.colorBorder}`, maxWidth: "100%", overflowWrap: "anywhere", ...parseInlineStyle(item.html_format) }, children: editable ? /* @__PURE__ */ jsx(
8927
9287
  Form.Item,
8928
9288
  {
@@ -9072,6 +9432,7 @@ var ReadAndEditReference = ({ value, onChange, field, allModels, model, currentI
9072
9432
  };
9073
9433
  var _26 = window._ || ((text) => text);
9074
9434
  var { Title: Title4 } = Typography;
9435
+ var requiredMark3 = (field) => field.required ? /* @__PURE__ */ jsx("span", { style: { color: "#ff4d4f", marginLeft: 3 }, children: "*" }) : null;
9075
9436
  function coerce(v) {
9076
9437
  if (v && typeof v === "object" && typeof v.valueOf === "function") return v.valueOf();
9077
9438
  return v;
@@ -9223,7 +9584,10 @@ var useStandardShowTabs = (model, record, allModels, actionsState, editForm, ove
9223
9584
  gap: "4px 6px"
9224
9585
  },
9225
9586
  children: [
9226
- /* @__PURE__ */ jsx("span", { style: { ...labelStyle, flex: "0 0 200px" }, children: field.label }),
9587
+ /* @__PURE__ */ jsxs("span", { style: { ...labelStyle, flex: "0 0 200px" }, children: [
9588
+ field.label,
9589
+ requiredMark3(field)
9590
+ ] }),
9227
9591
  /* @__PURE__ */ jsx(
9228
9592
  "div",
9229
9593
  {
@@ -9361,7 +9725,7 @@ var useStandardShowTabs = (model, record, allModels, actionsState, editForm, ove
9361
9725
  gap: 2
9362
9726
  },
9363
9727
  children: [
9364
- showLabel && /* @__PURE__ */ jsx(
9728
+ showLabel && /* @__PURE__ */ jsxs(
9365
9729
  "div",
9366
9730
  {
9367
9731
  style: {
@@ -9370,7 +9734,10 @@ var useStandardShowTabs = (model, record, allModels, actionsState, editForm, ove
9370
9734
  padding: "2px 4px",
9371
9735
  borderRadius: 4
9372
9736
  },
9373
- children: field.label
9737
+ children: [
9738
+ field.label,
9739
+ requiredMark3(field)
9740
+ ]
9374
9741
  }
9375
9742
  ),
9376
9743
  /* @__PURE__ */ jsx("div", { style: { ...valueStyle, border: `1px solid ${token.colorBorder}` }, children: editable || forceReadOnly ? renderShowEditableInput(field, forceReadOnly) : renderFieldValue(field, record, allModels) })
@@ -11400,6 +11767,20 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
11400
11767
  const filteredRows = useMemo(() => {
11401
11768
  return applyFilterRules(applyGlobalSearch(rows || []));
11402
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]);
11403
11784
  useEffect(() => {
11404
11785
  setCurrentPage(1);
11405
11786
  }, [localSearch, filterRules]);
@@ -11834,7 +12215,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
11834
12215
  return parts.filter(Boolean).join(" \u2022 ");
11835
12216
  }, [categoryField1, categoryField2, relatedModel.fields, relatedModel.label, relatedModel.name]);
11836
12217
  const chartData = useMemo(() => {
11837
- const data = filteredRows || [];
12218
+ const data = columnFilteredRows || [];
11838
12219
  const cat1Field = categoryField1 ? relatedModel.fields.find((field) => field.key === categoryField1) : void 0;
11839
12220
  const cat2Field = categoryField2 ? relatedModel.fields.find((field) => field.key === categoryField2) : void 0;
11840
12221
  const groupMap = /* @__PURE__ */ new Map();
@@ -11939,7 +12320,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
11939
12320
  seriesLabels,
11940
12321
  filteredRawRows
11941
12322
  };
11942
- }, [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]);
11943
12324
  const numericColumnMaxes = useMemo(() => {
11944
12325
  const maxes = {};
11945
12326
  const data = filteredRows || [];
@@ -12153,8 +12534,8 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12153
12534
  });
12154
12535
  }, [selectedColumnKeys]);
12155
12536
  const statsSummary = useMemo(() => {
12156
- return buildStatsSummary(filteredRows, displayFields, labelCache);
12157
- }, [filteredRows, displayFields, labelCache]);
12537
+ return buildStatsSummary(columnFilteredRows, displayFields, labelCache);
12538
+ }, [columnFilteredRows, displayFields, labelCache]);
12158
12539
  const isTotalsDetailsVariant = viewVariant === "totals-details";
12159
12540
  const getDefaultTotalsSummaryFn = useCallback((field) => {
12160
12541
  if (field.key === "eid") return "count";
@@ -13166,7 +13547,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13166
13547
  ] })
13167
13548
  ] })
13168
13549
  ] }),
13169
- 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(
13170
13551
  Card,
13171
13552
  {
13172
13553
  size: "small",
@@ -14774,6 +15155,55 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
14774
15155
  const baseRows = allRows || [];
14775
15156
  return applyFilterRules(applyGlobalSearch(baseRows));
14776
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]);
14777
15207
  useEffect(() => {
14778
15208
  setGalleryPage(1);
14779
15209
  }, [localSearch, filterRules, resolvedListViewType]);
@@ -15601,7 +16031,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
15601
16031
  return String(raw);
15602
16032
  }, [labelCache]);
15603
16033
  const chartData = useMemo(() => {
15604
- const data = allRows || [];
16034
+ const data = columnFilteredDataSource || [];
15605
16035
  const cat1Field = categoryField1 ? model.fields.find((field) => field.key === categoryField1) : void 0;
15606
16036
  const cat2Field = categoryField2 ? model.fields.find((field) => field.key === categoryField2) : void 0;
15607
16037
  const groupMap = /* @__PURE__ */ new Map();
@@ -15705,7 +16135,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
15705
16135
  seriesLabels,
15706
16136
  filteredRawRows
15707
16137
  };
15708
- }, [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]);
15709
16139
  const chartSignature = useMemo(() => {
15710
16140
  return JSON.stringify({
15711
16141
  chartType,
@@ -15720,8 +16150,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
15720
16150
  });
15721
16151
  }, [chartType, summaryFn, categoryField1, categoryField2, rankingMode, rankingFieldKey, rankingN, chartData]);
15722
16152
  const statsSummary = useMemo(() => {
15723
- return buildStatsSummary(allRows, displayFields, labelCache);
15724
- }, [allRows, displayFields, labelCache]);
16153
+ return buildStatsSummary(columnFilteredDataSource, displayFields, labelCache);
16154
+ }, [columnFilteredDataSource, displayFields, labelCache]);
15725
16155
  const tdCategoricalBoxes = useMemo(() => {
15726
16156
  if (!isTotalsDetailsView) return [];
15727
16157
  return displayFields.filter((field) => field.type !== "number" || Boolean(field.reference)).map((field) => {
@@ -19466,7 +19896,7 @@ function usePinnedRecords() {
19466
19896
  setLoading(false);
19467
19897
  }
19468
19898
  }, []);
19469
- React6.useEffect(() => {
19899
+ React8.useEffect(() => {
19470
19900
  load();
19471
19901
  }, [load]);
19472
19902
  return { groups, loading, reload: load };
@@ -19804,6 +20234,6 @@ var authSystemModels = [
19804
20234
  }
19805
20235
  ];
19806
20236
 
19807
- 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 };
19808
20238
  //# sourceMappingURL=index.mjs.map
19809
20239
  //# sourceMappingURL=index.mjs.map