@juicemantics/veloiq-ui 0.8.5 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React5 = require('react');
3
+ var React6 = require('react');
4
4
  var antd$1 = require('@refinedev/antd');
5
5
  var core = require('@refinedev/core');
6
6
  var antd = require('antd');
@@ -32,7 +32,7 @@ function _interopNamespace(e) {
32
32
  return Object.freeze(n);
33
33
  }
34
34
 
35
- var React5__default = /*#__PURE__*/_interopDefault(React5);
35
+ var React6__default = /*#__PURE__*/_interopDefault(React6);
36
36
  var AntDIcons2__namespace = /*#__PURE__*/_interopNamespace(AntDIcons2);
37
37
  var dayjs9__default = /*#__PURE__*/_interopDefault(dayjs9);
38
38
  var relativeTime2__default = /*#__PURE__*/_interopDefault(relativeTime2);
@@ -45,10 +45,8 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
45
45
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
46
46
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
47
47
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
48
- var ColorModeContext = React5.createContext({ mode: "light", setMode: () => {
48
+ var ColorModeContext = React6.createContext({ mode: "light", setMode: () => {
49
49
  }, schemaVersion: 0 });
50
-
51
- // src/utils/modelTone.ts
52
50
  var MODEL_TONES_LIGHT = [
53
51
  { solid: "#2563eb", soft: "#dbeafe", softer: "#eff6ff", text: "#1e3a8a", border: "#93c5fd", shadow: "rgba(37, 99, 235, 0.22)" },
54
52
  { solid: "#0f766e", soft: "#ccfbf1", softer: "#f0fdfa", text: "#115e59", border: "#5eead4", shadow: "rgba(15, 118, 110, 0.22)" },
@@ -165,6 +163,10 @@ var setColorSchemas = (schemas) => {
165
163
  const darkBgContent = `rgb(${shade(r, 0.06)}, ${shade(g, 0.06)}, ${shade(b, 0.06)})`;
166
164
  const darkBgElements = `rgb(${shade(r, 0.11)}, ${shade(g, 0.11)}, ${shade(b, 0.11)})`;
167
165
  const darkBgHover = `rgb(${shade(r, 0.16)}, ${shade(g, 0.16)}, ${shade(b, 0.16)})`;
166
+ const sidebarLightBg = hex;
167
+ const sidebarLightText = isDarkColor(hex) ? "#ffffff" : "#0f172a";
168
+ const sidebarDarkBg = lightBgElements;
169
+ const sidebarDarkText = "#0f172a";
168
170
  styleEl.innerHTML = `
169
171
  /* --- LIGHT MODE OVERRIDES --- */
170
172
  body.jm-light .ant-layout,
@@ -178,7 +180,31 @@ var setColorSchemas = (schemas) => {
178
180
  body.jm-light .ant-menu,
179
181
  body.jm-light .ant-menu-submenu,
180
182
  body.jm-light .ant-menu-submenu-title,
181
- body.jm-light .ant-layout-header,
183
+ body.jm-light .ant-layout-header {
184
+ background-color: ${sidebarLightBg} !important;
185
+ color: ${sidebarLightText} !important;
186
+ }
187
+ body.jm-light .ant-layout-sider *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input),
188
+ body.jm-light .ant-layout-header *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input) {
189
+ color: ${sidebarLightText} !important;
190
+ }
191
+ body.jm-light .ant-layout-sider .ant-menu-item-selected,
192
+ body.jm-light .ant-layout-sider .ant-menu-item-selected *,
193
+ body.jm-light .ant-layout-sider .ant-menu-item:hover,
194
+ body.jm-light .ant-layout-sider .ant-menu-item:hover *,
195
+ body.jm-light .ant-layout-header .ant-menu-item-selected,
196
+ body.jm-light .ant-layout-header .ant-menu-item-selected *,
197
+ body.jm-light .ant-layout-header .ant-menu-item:hover,
198
+ body.jm-light .ant-layout-header .ant-menu-item:hover * {
199
+ color: revert !important;
200
+ }
201
+ body.jm-light .ant-menu-submenu-popup {
202
+ background-color: ${sidebarLightBg} !important;
203
+ }
204
+ body.jm-light .ant-menu-submenu-popup .ant-menu-item:not(.ant-menu-item-selected),
205
+ body.jm-light .ant-menu-submenu-popup .ant-menu-submenu-title:not(.ant-menu-submenu-selected) {
206
+ color: ${sidebarLightText} !important;
207
+ }
182
208
  body.jm-light .ant-card,
183
209
  body.jm-light .ant-table-wrapper .ant-table,
184
210
  body.jm-light .ant-table-thead > tr > th,
@@ -208,7 +234,31 @@ var setColorSchemas = (schemas) => {
208
234
  body.jm-dark .ant-menu,
209
235
  body.jm-dark .ant-menu-submenu,
210
236
  body.jm-dark .ant-menu-submenu-title,
211
- body.jm-dark .ant-layout-header,
237
+ body.jm-dark .ant-layout-header {
238
+ background-color: ${sidebarDarkBg} !important;
239
+ color: ${sidebarDarkText} !important;
240
+ }
241
+ body.jm-dark .ant-layout-sider *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input),
242
+ body.jm-dark .ant-layout-header *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input) {
243
+ color: ${sidebarDarkText} !important;
244
+ }
245
+ body.jm-dark .ant-layout-sider .ant-menu-item-selected,
246
+ body.jm-dark .ant-layout-sider .ant-menu-item-selected *,
247
+ body.jm-dark .ant-layout-sider .ant-menu-item:hover,
248
+ body.jm-dark .ant-layout-sider .ant-menu-item:hover *,
249
+ body.jm-dark .ant-layout-header .ant-menu-item-selected,
250
+ body.jm-dark .ant-layout-header .ant-menu-item-selected *,
251
+ body.jm-dark .ant-layout-header .ant-menu-item:hover,
252
+ body.jm-dark .ant-layout-header .ant-menu-item:hover * {
253
+ color: revert !important;
254
+ }
255
+ body.jm-dark .ant-menu-submenu-popup {
256
+ background-color: ${sidebarDarkBg} !important;
257
+ }
258
+ body.jm-dark .ant-menu-submenu-popup .ant-menu-item:not(.ant-menu-item-selected),
259
+ body.jm-dark .ant-menu-submenu-popup .ant-menu-submenu-title:not(.ant-menu-submenu-selected) {
260
+ color: ${sidebarDarkText} !important;
261
+ }
212
262
  body.jm-dark .ant-card,
213
263
  body.jm-dark .ant-table-wrapper .ant-table,
214
264
  body.jm-dark .ant-table-thead > tr > th,
@@ -259,7 +309,7 @@ var getModelTone = (modelLike, darkMode) => {
259
309
  return tones[hashString(seed) % tones.length];
260
310
  };
261
311
  var useModelTone = (modelLike) => {
262
- const { mode, schemaVersion } = React5.useContext(ColorModeContext);
312
+ const { mode, schemaVersion } = React6.useContext(ColorModeContext);
263
313
  return getModelTone(modelLike, mode === "dark");
264
314
  };
265
315
  var getContrastingTextColor = (background) => isDarkColor(background) ? "#f8fafc" : "#0f172a";
@@ -308,7 +358,7 @@ function guessIcon(text, isModule = false) {
308
358
  function resolveIcon(iconName) {
309
359
  const registry = AntDIcons2__namespace;
310
360
  const IconCls = registry[iconName];
311
- return IconCls ? React5__default.default.createElement(IconCls) : React5__default.default.createElement(registry["TableOutlined"]);
361
+ return IconCls ? React6__default.default.createElement(IconCls) : React6__default.default.createElement(registry["TableOutlined"]);
312
362
  }
313
363
  function getNavEntry(navConfig, key) {
314
364
  return navConfig.find((e) => e.key === key);
@@ -339,8 +389,8 @@ var authenticatedFetch = (url, options = {}) => {
339
389
  var API_URL = "/api";
340
390
  var JOURNEY_ICON_NAME = "NodeIndexOutlined";
341
391
  function useJourneyMenuItems() {
342
- const [byModule, setByModule] = React5.useState({});
343
- React5.useEffect(() => {
392
+ const [byModule, setByModule] = React6.useState({});
393
+ React6.useEffect(() => {
344
394
  let cancelled = false;
345
395
  (async () => {
346
396
  var _a;
@@ -396,6 +446,7 @@ function injectJourneyMenuItems(items, byModule) {
396
446
  return walk(items);
397
447
  }
398
448
  var HorizontalMenu = ({ navConfig = [] }) => {
449
+ const { mode } = React6.useContext(ColorModeContext);
399
450
  const { menuItems, selectedKey } = core.useMenu();
400
451
  const go = core.useGo();
401
452
  const journeysByModule = useJourneyMenuItems();
@@ -421,7 +472,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
421
472
  const renderLabel = (item, depth, hasChildren) => {
422
473
  const label = String(item?.label || item?.name || item?.key || "");
423
474
  const isModule = depth === 0 || hasChildren;
424
- const tone = isModule ? getModelTone(`module:${item?.key || label}`) : getModelTone(resolveModelSeed(item));
475
+ isModule ? getModelTone(`module:${item?.key || label}`) : getModelTone(resolveModelSeed(item));
425
476
  return /* @__PURE__ */ jsxRuntime.jsx(
426
477
  "span",
427
478
  {
@@ -431,7 +482,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
431
482
  padding: isModule ? "2px 5px" : "1px 5px",
432
483
  borderRadius: 8,
433
484
  background: "transparent",
434
- color: tone.text,
485
+ color: "inherit",
435
486
  fontWeight: 400
436
487
  },
437
488
  children: label
@@ -457,6 +508,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
457
508
  antd.Menu,
458
509
  {
459
510
  mode: "horizontal",
511
+ theme: mode === "dark" ? "light" : "dark",
460
512
  selectedKeys: [selectedKey],
461
513
  items,
462
514
  style: {
@@ -469,7 +521,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
469
521
  };
470
522
  var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
471
523
  const { token } = antd.theme.useToken();
472
- const { mode } = React5.useContext(ColorModeContext);
524
+ const { mode } = React6.useContext(ColorModeContext);
473
525
  const { menuItems, selectedKey } = core.useMenu();
474
526
  const go = core.useGo();
475
527
  const journeysByModule = useJourneyMenuItems();
@@ -495,7 +547,7 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
495
547
  const renderLabel = (item, depth, hasChildren) => {
496
548
  const label = String(item?.label || item?.name || item?.key || "");
497
549
  const isModule = depth === 0 || hasChildren;
498
- const tone = isModule ? getModelTone(`module:${item?.key || label}`) : getModelTone(resolveModelSeed(item));
550
+ isModule ? getModelTone(`module:${item?.key || label}`) : getModelTone(resolveModelSeed(item));
499
551
  return /* @__PURE__ */ jsxRuntime.jsx(
500
552
  "span",
501
553
  {
@@ -505,7 +557,7 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
505
557
  padding: isModule ? "3px 8px" : "2px 8px",
506
558
  borderRadius: 8,
507
559
  background: "transparent",
508
- color: tone.text,
560
+ color: "inherit",
509
561
  fontWeight: 400
510
562
  },
511
563
  children: label
@@ -526,15 +578,15 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
526
578
  };
527
579
  });
528
580
  };
529
- const sortedMenuItems = React5.useMemo(
581
+ const sortedMenuItems = React6.useMemo(
530
582
  () => navConfig.length > 0 ? sortItemsByNavConfig(menuItems, navConfig) : menuItems,
531
583
  [menuItems, navConfig]
532
584
  );
533
- const withJourneys = React5.useMemo(
585
+ const withJourneys = React6.useMemo(
534
586
  () => injectJourneyMenuItems(sortedMenuItems, journeysByModule),
535
587
  [sortedMenuItems, journeysByModule]
536
588
  );
537
- const items = React5.useMemo(() => transformItems(withJourneys), [withJourneys, mode, navConfig]);
589
+ const items = React6.useMemo(() => transformItems(withJourneys), [withJourneys, mode, navConfig]);
538
590
  return /* @__PURE__ */ jsxRuntime.jsx(
539
591
  antd.Layout.Sider,
540
592
  {
@@ -611,30 +663,30 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
611
663
  }
612
664
  );
613
665
  };
614
- var AllModelsContext = React5.createContext([]);
666
+ var AllModelsContext = React6.createContext([]);
615
667
  var AllModelsProvider = ({
616
668
  models,
617
669
  children
618
670
  }) => /* @__PURE__ */ jsxRuntime.jsx(AllModelsContext.Provider, { value: models, children });
619
- var useAllModels = () => React5.useContext(AllModelsContext);
671
+ var useAllModels = () => React6.useContext(AllModelsContext);
620
672
 
621
673
  // src/hooks/useRecordSearch.ts
622
674
  var API_URL2 = "/api";
623
675
  function useRecordSearch() {
624
676
  const allSystemModels = useAllModels();
625
- const [searchConfig, setSearchConfig] = React5.useState(null);
626
- const [results, setResults] = React5.useState([]);
627
- const [searching, setSearching] = React5.useState(false);
628
- const debounceRef = React5.useRef(null);
629
- const abortRef = React5.useRef(null);
630
- React5.useEffect(() => {
677
+ const [searchConfig, setSearchConfig] = React6.useState(null);
678
+ const [results, setResults] = React6.useState([]);
679
+ const [searching, setSearching] = React6.useState(false);
680
+ const debounceRef = React6.useRef(null);
681
+ const abortRef = React6.useRef(null);
682
+ React6.useEffect(() => {
631
683
  authenticatedFetch(`${API_URL2}/config/search`).then((r) => {
632
684
  if (!r.ok) throw new Error("unavailable");
633
685
  return r.json();
634
686
  }).then((d) => setSearchConfig(d)).catch(() => {
635
687
  });
636
688
  }, []);
637
- const searchableModels = React5.useMemo(() => {
689
+ const searchableModels = React6.useMemo(() => {
638
690
  if (!searchConfig) return [];
639
691
  const entityTypesLower = searchConfig.entity_types.map((e) => e.toLowerCase());
640
692
  const preferredFields = searchConfig.attribute_types;
@@ -667,7 +719,7 @@ function useRecordSearch() {
667
719
  };
668
720
  }).filter((m) => m.searchFields.length > 0);
669
721
  }, [allSystemModels, searchConfig]);
670
- const search = React5.useCallback(
722
+ const search = React6.useCallback(
671
723
  (query) => {
672
724
  if (debounceRef.current) clearTimeout(debounceRef.current);
673
725
  if (abortRef.current) abortRef.current.abort();
@@ -728,7 +780,7 @@ function useRecordSearch() {
728
780
  },
729
781
  [searchableModels]
730
782
  );
731
- const clear = React5.useCallback(() => {
783
+ const clear = React6.useCallback(() => {
732
784
  if (debounceRef.current) clearTimeout(debounceRef.current);
733
785
  if (abortRef.current) abortRef.current.abort();
734
786
  setResults([]);
@@ -756,10 +808,11 @@ var flattenMenuItems = (items, parentLabel = "") => {
756
808
  var GlobalSearch = () => {
757
809
  const { menuItems } = core.useMenu();
758
810
  const navigate = reactRouterDom.useNavigate();
759
- const [searchText, setSearchText] = React5.useState("");
811
+ const [searchText, setSearchText] = React6.useState("");
760
812
  const { results: backendResults, searching, search, clear } = useRecordSearch();
761
- const searchableResources = React5.useMemo(() => flattenMenuItems(menuItems), [menuItems]);
762
- const resourceResults = React5.useMemo(() => {
813
+ const { token } = antd.theme.useToken();
814
+ const searchableResources = React6.useMemo(() => flattenMenuItems(menuItems), [menuItems]);
815
+ const resourceResults = React6.useMemo(() => {
763
816
  const q2 = searchText.toLowerCase().trim();
764
817
  if (!q2) return [];
765
818
  const matches = searchableResources.filter(
@@ -780,7 +833,7 @@ var GlobalSearch = () => {
780
833
  }
781
834
  ];
782
835
  }, [searchText, searchableResources]);
783
- const backendGroups = React5.useMemo(
836
+ const backendGroups = React6.useMemo(
784
837
  () => backendResults.map((result) => ({
785
838
  label: /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { type: "secondary", strong: true, style: { fontSize: 11 }, children: result.modelLabel }),
786
839
  options: result.records.map((record) => ({
@@ -791,14 +844,14 @@ var GlobalSearch = () => {
791
844
  })),
792
845
  [backendResults]
793
846
  );
794
- const onSearch = React5.useCallback(
847
+ const onSearch = React6.useCallback(
795
848
  (value) => {
796
849
  setSearchText(value);
797
850
  search(value);
798
851
  },
799
852
  [search]
800
853
  );
801
- const onSelect = React5.useCallback(
854
+ const onSelect = React6.useCallback(
802
855
  (value) => {
803
856
  const path = value.replace(/^(nav:|record:)/, "");
804
857
  navigate(path);
@@ -807,13 +860,13 @@ var GlobalSearch = () => {
807
860
  },
808
861
  [navigate, clear]
809
862
  );
810
- const options = React5.useMemo(
863
+ const options = React6.useMemo(
811
864
  () => [...resourceResults, ...backendGroups],
812
865
  [resourceResults, backendGroups]
813
866
  );
814
- const [focused, setFocused] = React5.useState(false);
815
- const inputRef = React5.useRef(null);
816
- React5.useEffect(() => {
867
+ const [focused, setFocused] = React6.useState(false);
868
+ const inputRef = React6.useRef(null);
869
+ React6.useEffect(() => {
817
870
  const handler = (e) => {
818
871
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "k") {
819
872
  e.preventDefault();
@@ -847,7 +900,7 @@ var GlobalSearch = () => {
847
900
  suffix: !focused ? /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { type: "secondary", style: { fontSize: 9 }, children: "\u2303K" }) : void 0,
848
901
  allowClear: true,
849
902
  size: "small",
850
- style: !focused ? { paddingInline: 2 } : void 0
903
+ style: !focused ? { paddingInline: 2, color: token.colorText } : { color: token.colorText }
851
904
  }
852
905
  )
853
906
  }
@@ -859,9 +912,9 @@ var API_URL3 = "/api";
859
912
 
860
913
  // src/pages/dashboard/hooks/useRecentActivity.ts
861
914
  function useRecentActivity(days) {
862
- const [data, setData] = React5.useState(null);
863
- const [loading, setLoading] = React5.useState(true);
864
- const load = React5.useCallback(async () => {
915
+ const [data, setData] = React6.useState(null);
916
+ const [loading, setLoading] = React6.useState(true);
917
+ const load = React6.useCallback(async () => {
865
918
  setLoading(true);
866
919
  try {
867
920
  const params = days !== void 0 ? `?days=${days}` : "";
@@ -872,7 +925,7 @@ function useRecentActivity(days) {
872
925
  setLoading(false);
873
926
  }
874
927
  }, [days]);
875
- React5.useEffect(() => {
928
+ React6.useEffect(() => {
876
929
  load();
877
930
  }, [load]);
878
931
  return { data, loading, reload: load };
@@ -903,9 +956,9 @@ function relativeTime(iso) {
903
956
  return d < 30 ? `${d}d ago` : new Date(iso).toLocaleDateString();
904
957
  }
905
958
  function usePinnedGroups() {
906
- const [groups, setGroups] = React5.useState([]);
907
- const [loading, setLoading] = React5.useState(false);
908
- const load = React5.useCallback(async () => {
959
+ const [groups, setGroups] = React6.useState([]);
960
+ const [loading, setLoading] = React6.useState(false);
961
+ const load = React6.useCallback(async () => {
909
962
  setLoading(true);
910
963
  try {
911
964
  const res = await authenticatedFetch(`${API_URL3}/dashboard/pinned-records`);
@@ -974,22 +1027,22 @@ var CommandCenterPortal = ({
974
1027
  }) => {
975
1028
  const { menuItems: rawMenuItems } = core.useMenu();
976
1029
  const journeysByModule = useJourneyMenuItems();
977
- const menuItems = React5.useMemo(
1030
+ const menuItems = React6.useMemo(
978
1031
  () => injectJourneyMenuItems(rawMenuItems, journeysByModule),
979
1032
  [rawMenuItems, journeysByModule]
980
1033
  );
981
1034
  const go = core.useGo();
982
- const searchRef = React5.useRef(null);
983
- const [query, setQuery] = React5.useState("");
984
- const [activeIdx, setActiveIdx] = React5.useState(-1);
985
- const [colW, setColW] = React5.useState([220, 220]);
986
- const colWRef = React5.useRef([220, 220]);
1035
+ const searchRef = React6.useRef(null);
1036
+ const [query, setQuery] = React6.useState("");
1037
+ const [activeIdx, setActiveIdx] = React6.useState(-1);
1038
+ const [colW, setColW] = React6.useState([220, 220]);
1039
+ const colWRef = React6.useRef([220, 220]);
987
1040
  colWRef.current = colW;
988
- const dragRef = React5.useRef(null);
1041
+ const dragRef = React6.useRef(null);
989
1042
  const { results: backendResults, searching, search, clear } = useRecordSearch();
990
1043
  const { groups: pinnedGroups, loading: pinnedLoading, load: loadPinned } = usePinnedGroups();
991
1044
  const { data: recentData, reload: reloadRecent } = useRecentActivity(30);
992
- React5.useEffect(() => {
1045
+ React6.useEffect(() => {
993
1046
  if (open) {
994
1047
  setQuery("");
995
1048
  setActiveIdx(-1);
@@ -1000,9 +1053,9 @@ var CommandCenterPortal = ({
1000
1053
  return () => clearTimeout(t);
1001
1054
  }
1002
1055
  }, [open, clear, loadPinned, reloadRecent]);
1003
- const navItemIdsRef = React5.useRef([]);
1004
- const activeIdxRef = React5.useRef(-1);
1005
- React5.useEffect(() => {
1056
+ const navItemIdsRef = React6.useRef([]);
1057
+ const activeIdxRef = React6.useRef(-1);
1058
+ React6.useEffect(() => {
1006
1059
  if (!open) return;
1007
1060
  const handler = (e) => {
1008
1061
  if (e.key === "Escape") {
@@ -1030,33 +1083,33 @@ var CommandCenterPortal = ({
1030
1083
  window.addEventListener("keydown", handler);
1031
1084
  return () => window.removeEventListener("keydown", handler);
1032
1085
  }, [open, onClose]);
1033
- const parsedCommand = React5.useMemo(() => parseCommand(query.toLowerCase().trim()), [query]);
1034
- React5.useEffect(() => {
1086
+ const parsedCommand = React6.useMemo(() => parseCommand(query.toLowerCase().trim()), [query]);
1087
+ React6.useEffect(() => {
1035
1088
  if (parsedCommand) {
1036
1089
  clear();
1037
1090
  } else {
1038
1091
  search(query.toLowerCase().trim());
1039
1092
  }
1040
1093
  }, [query, parsedCommand, search, clear]);
1041
- const allModelChildren = React5.useMemo(
1094
+ const allModelChildren = React6.useMemo(
1042
1095
  () => menuItems.flatMap(
1043
1096
  (m) => (m.children || []).filter((c) => !c.meta?.hide).map((c) => ({ ...c, moduleLabel: String(m.label || m.name || "") }))
1044
1097
  ),
1045
1098
  [menuItems]
1046
1099
  );
1047
- const commandSuggestions = React5.useMemo(() => {
1100
+ const commandSuggestions = React6.useMemo(() => {
1048
1101
  if (!parsedCommand) return [];
1049
1102
  const mq = parsedCommand.modelQuery;
1050
1103
  const children = mq ? allModelChildren.filter((c) => (c.label || "").toLowerCase().includes(mq) || (c.name || "").toLowerCase().includes(mq)) : allModelChildren;
1051
1104
  return (navConfig.length > 0 ? sortItemsByNavConfig(children, navConfig) : children).slice(0, 8);
1052
1105
  }, [parsedCommand, allModelChildren, navConfig]);
1053
- const searchPlaceholder = React5.useMemo(() => {
1106
+ const searchPlaceholder = React6.useMemo(() => {
1054
1107
  const labels = allModelChildren.slice(0, 2).map((c) => String(c.label || c.name || "").toLowerCase()).filter(Boolean);
1055
1108
  if (labels.length === 0) return `Search modules, models, records\u2026`;
1056
1109
  const [a, b] = labels;
1057
1110
  return b && b !== a ? `Search modules, models, records\u2026 or "list ${a}", "create ${b}"` : `Search modules, models, records\u2026 or "list ${a}", "create ${a}"`;
1058
1111
  }, [allModelChildren]);
1059
- const modules = React5.useMemo(() => {
1112
+ const modules = React6.useMemo(() => {
1060
1113
  const q2 = parsedCommand ? parsedCommand.modelQuery : query.toLowerCase().trim();
1061
1114
  const visibleModules = menuItems.filter((item) => item.children && item.children.length > 0).map((item) => ({ ...item, children: (item.children || []).filter((c) => !c.meta?.hide) })).filter((item) => item.children && item.children.length > 0);
1062
1115
  const sorted = navConfig.length > 0 ? sortItemsByNavConfig(visibleModules, navConfig) : visibleModules;
@@ -1070,7 +1123,7 @@ var CommandCenterPortal = ({
1070
1123
  return moduleMatch ? module : { ...module, children: filteredChildren };
1071
1124
  }).filter((m) => m !== null);
1072
1125
  }, [menuItems, query, parsedCommand, navConfig]);
1073
- const pinnedItems = React5.useMemo(
1126
+ const pinnedItems = React6.useMemo(
1074
1127
  () => pinnedGroups.flatMap((g) => g.records.map((r) => ({
1075
1128
  resource: g.resource,
1076
1129
  modelName: g.model_name,
@@ -1079,7 +1132,7 @@ var CommandCenterPortal = ({
1079
1132
  }))),
1080
1133
  [pinnedGroups]
1081
1134
  );
1082
- const recentItems = React5.useMemo(() => {
1135
+ const recentItems = React6.useMemo(() => {
1083
1136
  if (!recentData?.groups) return [];
1084
1137
  return recentData.groups.flatMap((g) => g.records.map((r) => ({
1085
1138
  resource: g.resource,
@@ -1090,7 +1143,7 @@ var CommandCenterPortal = ({
1090
1143
  isNew: Boolean(r.created_at && (!r.updated_at || r.updated_at === r.created_at))
1091
1144
  }))).sort((a, b) => b.timestamp.localeCompare(a.timestamp));
1092
1145
  }, [recentData]);
1093
- const navItemIds = React5.useMemo(() => {
1146
+ const navItemIds = React6.useMemo(() => {
1094
1147
  const ids = [];
1095
1148
  if (parsedCommand) {
1096
1149
  for (const child of commandSuggestions)
@@ -1111,10 +1164,10 @@ var CommandCenterPortal = ({
1111
1164
  }, [parsedCommand, commandSuggestions, query, pinnedItems, recentItems, backendResults, modules, navConfig]);
1112
1165
  navItemIdsRef.current = navItemIds;
1113
1166
  activeIdxRef.current = activeIdx;
1114
- React5.useEffect(() => {
1167
+ React6.useEffect(() => {
1115
1168
  setActiveIdx(-1);
1116
1169
  }, [navItemIds]);
1117
- React5.useEffect(() => {
1170
+ React6.useEffect(() => {
1118
1171
  if (activeIdx < 0) return;
1119
1172
  const id = navItemIds[activeIdx];
1120
1173
  if (id) document.querySelector(`[data-navid="${id}"]`)?.scrollIntoView({ block: "nearest", behavior: "smooth" });
@@ -1303,7 +1356,7 @@ var CommandCenterPortal = ({
1303
1356
  /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { style: SECTION_LABEL_STYLE, children: "Pinned" }),
1304
1357
  pinnedLoading && /* @__PURE__ */ jsxRuntime.jsx(antd.Spin, { size: "small", style: { marginLeft: "auto" } })
1305
1358
  ] }),
1306
- pinnedItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: pinnedItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1359
+ pinnedItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: pinnedItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1307
1360
  idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
1308
1361
  renderRow(
1309
1362
  `pin-${item.resource}-${item.id}`,
@@ -1326,7 +1379,7 @@ var CommandCenterPortal = ({
1326
1379
  /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.ClockCircleOutlined, { style: { color: "rgba(255,255,255,0.45)", fontSize: 12 } }),
1327
1380
  /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { style: SECTION_LABEL_STYLE, children: "Recent" })
1328
1381
  ] }),
1329
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: recentItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1382
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: recentItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1330
1383
  idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
1331
1384
  renderRow(
1332
1385
  `recent-${item.resource}-${item.id}`,
@@ -1355,7 +1408,7 @@ var CommandCenterPortal = ({
1355
1408
  const moduleLabel = String(module.label || module.name || "");
1356
1409
  const tone = getModelTone(moduleKey);
1357
1410
  const children = navConfig.length > 0 ? sortItemsByNavConfig(module.children || [], navConfig) : module.children || [];
1358
- return /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1411
+ return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1359
1412
  modIdx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "5px 0", borderColor: "rgba(255,255,255,0.06)" } }),
1360
1413
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, padding: "4px 8px 2px" }, children: [
1361
1414
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: tone.solid, fontSize: 12, display: "flex", alignItems: "center" }, children: getItemIcon(moduleKey, moduleLabel, true) }),
@@ -1366,7 +1419,7 @@ var CommandCenterPortal = ({
1366
1419
  const childLabel = String(child.label || child.name || "");
1367
1420
  const childTone = getModelTone(childKey);
1368
1421
  const childIcon = getItemIcon(childKey, childLabel, false, child.icon);
1369
- return /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1422
+ return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1370
1423
  idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
1371
1424
  /* @__PURE__ */ jsxRuntime.jsxs(
1372
1425
  "div",
@@ -1418,7 +1471,7 @@ var CommandCenterPortal = ({
1418
1471
  const moduleLabel = child.moduleLabel || "";
1419
1472
  const navId = `cmd-${childKey}`;
1420
1473
  const active = isActive(navId);
1421
- return /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1474
+ return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1422
1475
  idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.05)" } }),
1423
1476
  /* @__PURE__ */ jsxRuntime.jsxs(
1424
1477
  "div",
@@ -1462,13 +1515,13 @@ var CommandCenterPortal = ({
1462
1515
  ] }),
1463
1516
  backendResults.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px" }, children: backendResults.map((modelResult, modelIdx) => {
1464
1517
  const tone = getModelTone(modelResult.resource);
1465
- return /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1518
+ return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1466
1519
  modelIdx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "4px 0", borderColor: "rgba(255,255,255,0.05)" } }),
1467
1520
  /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { style: { color: "rgba(255,255,255,0.35)", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.07em", display: "block", padding: "4px 10px 2px" }, children: modelResult.modelLabel }),
1468
1521
  modelResult.records.map((record, recIdx) => {
1469
1522
  const navId = `record-${modelResult.resource}-${record.id}`;
1470
1523
  const active = isActive(navId);
1471
- return /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1524
+ return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1472
1525
  recIdx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
1473
1526
  /* @__PURE__ */ jsxRuntime.jsxs(
1474
1527
  "div",
@@ -1550,7 +1603,7 @@ var CommandCenterPortal = ({
1550
1603
  const childLabel = String(child.label || child.name || "");
1551
1604
  const childTone = getModelTone(childKey);
1552
1605
  const childIcon = getItemIcon(childKey, childLabel, false, child.icon);
1553
- return /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1606
+ return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
1554
1607
  idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.05)" } }),
1555
1608
  /* @__PURE__ */ jsxRuntime.jsxs(
1556
1609
  "div",
@@ -1584,8 +1637,8 @@ var CommandCenterPortal = ({
1584
1637
  }
1585
1638
  ) });
1586
1639
  };
1587
- var NavConfigContext = React5.createContext([]);
1588
- var useNavConfig = () => React5.useContext(NavConfigContext);
1640
+ var NavConfigContext = React6.createContext([]);
1641
+ var useNavConfig = () => React6.useContext(NavConfigContext);
1589
1642
  function useNavModules() {
1590
1643
  const navConfig = useNavConfig();
1591
1644
  return (navConfig || []).filter((e) => e.type === "module" && String(e.key || "").startsWith("module:")).map((e) => ({ value: String(e.key).slice("module:".length), label: e.label || String(e.key).slice("module:".length) }));
@@ -1630,24 +1683,24 @@ var LayoutWrapper = ({
1630
1683
  extraUserMenuItems = [],
1631
1684
  navConfig = []
1632
1685
  }) => {
1633
- const [layoutMode, setLayoutMode] = React5.useState(
1686
+ const [layoutMode, setLayoutMode] = React6.useState(
1634
1687
  () => localStorage.getItem("layoutMode") || "vertical"
1635
1688
  );
1636
1689
  const screens = antd.Grid.useBreakpoint();
1637
1690
  const isMobile = !screens.md;
1638
- const { mode, setMode } = React5.useContext(ColorModeContext);
1691
+ const { mode, setMode } = React6.useContext(ColorModeContext);
1639
1692
  const { token } = antd.theme.useToken();
1640
1693
  const { data: identity } = core.useGetIdentity();
1641
1694
  const { mutate: logout } = core.useLogout();
1642
1695
  core.useGo();
1643
1696
  const displayName = identity ? [identity.first_name, identity.last_name].filter(Boolean).join(" ") || identity.username || "User" : "User";
1644
- const [siderCollapsed, setSiderCollapsed] = React5.useState(() => localStorage.getItem("siderCollapsed") === "true");
1645
- const [pwdModalOpen, setPwdModalOpen] = React5.useState(false);
1646
- const [pwdLoading, setPwdLoading] = React5.useState(false);
1697
+ const [siderCollapsed, setSiderCollapsed] = React6.useState(() => localStorage.getItem("siderCollapsed") === "true");
1698
+ const [pwdModalOpen, setPwdModalOpen] = React6.useState(false);
1699
+ const [pwdLoading, setPwdLoading] = React6.useState(false);
1647
1700
  const [pwdForm] = antd.Form.useForm();
1648
- const [drawerOpen, setDrawerOpen] = React5.useState(false);
1649
- const [portalOpen, setPortalOpen] = React5.useState(false);
1650
- React5.useEffect(() => {
1701
+ const [drawerOpen, setDrawerOpen] = React6.useState(false);
1702
+ const [portalOpen, setPortalOpen] = React6.useState(false);
1703
+ React6.useEffect(() => {
1651
1704
  const handler = (e) => {
1652
1705
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "g") {
1653
1706
  e.preventDefault();
@@ -1833,8 +1886,8 @@ var LayoutWrapper = ({
1833
1886
  ] });
1834
1887
  };
1835
1888
  var PANE_TOOLBAR_HEIGHT = 28;
1836
- var PaneNavigationContext = React5.createContext(null);
1837
- var usePaneNavigation = () => React5.useContext(PaneNavigationContext);
1889
+ var PaneNavigationContext = React6.createContext(null);
1890
+ var usePaneNavigation = () => React6.useContext(PaneNavigationContext);
1838
1891
  function gt(e, t) {
1839
1892
  const n = getComputedStyle(e), o = parseFloat(n.fontSize);
1840
1893
  return t * o;
@@ -3350,19 +3403,19 @@ function Vt(e) {
3350
3403
  };
3351
3404
  }
3352
3405
  function Bt() {
3353
- const [e, t] = React5.useState({}), n = React5.useCallback(() => t({}), []);
3406
+ const [e, t] = React6.useState({}), n = React6.useCallback(() => t({}), []);
3354
3407
  return [e, n];
3355
3408
  }
3356
3409
  function Le(e) {
3357
- const t = React5.useId();
3410
+ const t = React6.useId();
3358
3411
  return `${e ?? t}`;
3359
3412
  }
3360
- var q = typeof window < "u" ? React5.useLayoutEffect : React5.useEffect;
3413
+ var q = typeof window < "u" ? React6.useLayoutEffect : React6.useEffect;
3361
3414
  function se(e) {
3362
- const t = React5.useRef(e);
3415
+ const t = React6.useRef(e);
3363
3416
  return q(() => {
3364
3417
  t.current = e;
3365
- }, [e]), React5.useCallback(
3418
+ }, [e]), React6.useCallback(
3366
3419
  (...n) => t.current?.(...n),
3367
3420
  [t]
3368
3421
  );
@@ -3385,19 +3438,19 @@ function Ce(...e) {
3385
3438
  });
3386
3439
  }
3387
3440
  function Re(e) {
3388
- const t = React5.useRef({ ...e });
3441
+ const t = React6.useRef({ ...e });
3389
3442
  return q(() => {
3390
3443
  for (const n in e)
3391
3444
  t.current[n] = e[n];
3392
3445
  }, [e]), t.current;
3393
3446
  }
3394
- var lt = React5.createContext(null);
3447
+ var lt = React6.createContext(null);
3395
3448
  function Wt(e, t) {
3396
- const n = React5.useRef({
3449
+ const n = React6.useRef({
3397
3450
  getLayout: () => ({}),
3398
3451
  setLayout: Ft
3399
3452
  });
3400
- React5.useImperativeHandle(t, () => n.current, []), q(() => {
3453
+ React6.useImperativeHandle(t, () => n.current, []), q(() => {
3401
3454
  Object.assign(
3402
3455
  n.current,
3403
3456
  nt({ groupId: e })
@@ -3423,14 +3476,14 @@ function Ut({
3423
3476
  style: d,
3424
3477
  ...S
3425
3478
  }) {
3426
- const z = React5.useRef({
3479
+ const z = React6.useRef({
3427
3480
  onLayoutChange: {},
3428
3481
  onLayoutChanged: {}
3429
3482
  }), c = se((x) => {
3430
3483
  W(z.current.onLayoutChange, x) || (z.current.onLayoutChange = x, s?.(x));
3431
3484
  }), p = se((x) => {
3432
3485
  W(z.current.onLayoutChanged, x) || (z.current.onLayoutChanged = x, l?.(x));
3433
- }), m = Le(a), v = React5.useRef(null), [b, y] = Bt(), g = React5.useRef({
3486
+ }), m = Le(a), v = React6.useRef(null), [b, y] = Bt(), g = React6.useRef({
3434
3487
  lastExpandedPanelSizes: {},
3435
3488
  layouts: {},
3436
3489
  panels: [],
@@ -3464,7 +3517,7 @@ function Ut({
3464
3517
  ), w = Re({
3465
3518
  defaultLayout: n,
3466
3519
  disableCursor: o
3467
- }), G = React5.useMemo(
3520
+ }), G = React6.useMemo(
3468
3521
  () => ({
3469
3522
  get disableCursor() {
3470
3523
  return !!w.disableCursor;
@@ -3516,7 +3569,7 @@ function Ut({
3516
3569
  }
3517
3570
  }),
3518
3571
  [M, m, y, u, w]
3519
- ), N = React5.useRef(null);
3572
+ ), N = React6.useRef(null);
3520
3573
  return q(() => {
3521
3574
  const x = v.current;
3522
3575
  if (x === null)
@@ -3582,7 +3635,7 @@ function Ut({
3582
3635
  u,
3583
3636
  b,
3584
3637
  w
3585
- ]), React5.useEffect(() => {
3638
+ ]), React6.useEffect(() => {
3586
3639
  const x = N.current;
3587
3640
  x && (x.mutableState.defaultLayout = n, x.mutableState.disableCursor = !!o);
3588
3641
  }), /* @__PURE__ */ jsxRuntime.jsx(lt.Provider, { value: G, children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -3614,14 +3667,14 @@ function Ut({
3614
3667
  }
3615
3668
  Ut.displayName = "Group";
3616
3669
  function Me() {
3617
- const e = React5.useContext(lt);
3670
+ const e = React6.useContext(lt);
3618
3671
  return C(
3619
3672
  e,
3620
3673
  "Group Context not found; did you render a Panel or Separator outside of a Group?"
3621
3674
  ), e;
3622
3675
  }
3623
3676
  function qt(e, t) {
3624
- const { id: n } = Me(), o = React5.useRef({
3677
+ const { id: n } = Me(), o = React6.useRef({
3625
3678
  collapse: ye,
3626
3679
  expand: ye,
3627
3680
  getSize: () => ({
@@ -3631,7 +3684,7 @@ function qt(e, t) {
3631
3684
  isCollapsed: () => false,
3632
3685
  resize: ye
3633
3686
  });
3634
- React5.useImperativeHandle(t, () => o.current, []), q(() => {
3687
+ React6.useImperativeHandle(t, () => o.current, []), q(() => {
3635
3688
  Object.assign(
3636
3689
  o.current,
3637
3690
  tt({ groupId: n, panelId: e })
@@ -3657,7 +3710,7 @@ function Yt({
3657
3710
  }) {
3658
3711
  const c = !!s, p = Le(s), m = Re({
3659
3712
  disabled: r
3660
- }), v = React5.useRef(null), b = Ce(v, f), {
3713
+ }), v = React6.useRef(null), b = Ce(v, f), {
3661
3714
  getPanelStyles: y,
3662
3715
  id: g,
3663
3716
  orientation: P,
@@ -3705,14 +3758,14 @@ function Yt({
3705
3758
  N,
3706
3759
  M,
3707
3760
  m
3708
- ]), React5.useEffect(() => {
3761
+ ]), React6.useEffect(() => {
3709
3762
  w(p, { disabled: r });
3710
3763
  }, [r, p, w]), qt(p, d);
3711
3764
  const x = () => {
3712
3765
  const R = y(g, p);
3713
3766
  if (R)
3714
3767
  return JSON.stringify(R);
3715
- }, L = React5.useSyncExternalStore(
3768
+ }, L = React6.useSyncExternalStore(
3716
3769
  (R) => ze(g, R),
3717
3770
  x,
3718
3771
  x
@@ -3826,7 +3879,7 @@ function Qt({
3826
3879
  const s = Le(r), l = Re({
3827
3880
  disabled: n,
3828
3881
  disableDoubleClick: o
3829
- }), [u, h] = React5.useState({}), [d, S] = React5.useState("inactive"), [z, c] = React5.useState(false), p = React5.useRef(null), m = Ce(p, i), {
3882
+ }), [u, h] = React6.useState({}), [d, S] = React6.useState("inactive"), [z, c] = React6.useState(false), p = React6.useRef(null), m = Ce(p, i), {
3830
3883
  disableCursor: v,
3831
3884
  id: b,
3832
3885
  orientation: y,
@@ -3870,7 +3923,7 @@ function Qt({
3870
3923
  k(), R(), L();
3871
3924
  };
3872
3925
  }
3873
- }, [b, s, g, l]), React5.useEffect(() => {
3926
+ }, [b, s, g, l]), React6.useEffect(() => {
3874
3927
  P(s, { disabled: n, disableDoubleClick: o });
3875
3928
  }, [n, o, s, P]);
3876
3929
  let w;
@@ -3924,10 +3977,10 @@ Qt.displayName = "Separator";
3924
3977
  var _3 = window._ || ((text) => text);
3925
3978
  var NARROW_BREAKPOINT = 768;
3926
3979
  var useIsNarrow = (breakpoint = NARROW_BREAKPOINT) => {
3927
- const [narrow, setNarrow] = React5.useState(
3980
+ const [narrow, setNarrow] = React6.useState(
3928
3981
  () => typeof window !== "undefined" ? window.innerWidth < breakpoint : false
3929
3982
  );
3930
- React5.useEffect(() => {
3983
+ React6.useEffect(() => {
3931
3984
  const handler = () => setNarrow(window.innerWidth < breakpoint);
3932
3985
  window.addEventListener("resize", handler);
3933
3986
  return () => window.removeEventListener("resize", handler);
@@ -3950,8 +4003,8 @@ var ActionsButtonStack = ({ direction, children }) => /* @__PURE__ */ jsxRuntime
3950
4003
  var VerticalActionsLayout = ({ position, onBarMount, children }) => {
3951
4004
  const { token } = antd.theme.useToken();
3952
4005
  const narrow = useIsNarrow();
3953
- const [drawerOpen, setDrawerOpen] = React5.useState(false);
3954
- const mountRef = React5.useCallback(
4006
+ const [drawerOpen, setDrawerOpen] = React6.useState(false);
4007
+ const mountRef = React6.useCallback(
3955
4008
  (el) => onBarMount(el),
3956
4009
  [onBarMount]
3957
4010
  );
@@ -4280,9 +4333,9 @@ var splitRelations = (relations = []) => {
4280
4333
  };
4281
4334
  var useViewConfigurations = (modelName, viewType) => {
4282
4335
  const apiUrl = core.useApiUrl();
4283
- const [rows, setRows] = React5.useState([]);
4284
- const [loading, setLoading] = React5.useState(!!modelName);
4285
- React5.useEffect(() => {
4336
+ const [rows, setRows] = React6.useState([]);
4337
+ const [loading, setLoading] = React6.useState(!!modelName);
4338
+ React6.useEffect(() => {
4286
4339
  if (!modelName) {
4287
4340
  setLoading(false);
4288
4341
  return;
@@ -4318,9 +4371,9 @@ var normalizeActionsPosition = (raw) => {
4318
4371
  };
4319
4372
  var useViewSettings = () => {
4320
4373
  const apiUrl = core.useApiUrl();
4321
- const [settings, setSettings] = React5.useState(null);
4322
- const [loading, setLoading] = React5.useState(true);
4323
- React5.useEffect(() => {
4374
+ const [settings, setSettings] = React6.useState(null);
4375
+ const [loading, setLoading] = React6.useState(true);
4376
+ React6.useEffect(() => {
4324
4377
  let cancelled = false;
4325
4378
  const fetchSettings = async () => {
4326
4379
  try {
@@ -4675,7 +4728,7 @@ var extractButtonLabel = (node) => {
4675
4728
  }
4676
4729
  return null;
4677
4730
  }
4678
- if (React5__default.default.isValidElement(node)) {
4731
+ if (React6__default.default.isValidElement(node)) {
4679
4732
  return extractButtonLabel(node.props?.children);
4680
4733
  }
4681
4734
  return null;
@@ -4692,14 +4745,14 @@ var renderIconOnlyButtons = (nodes) => {
4692
4745
  const enhanceNode = (node, index) => {
4693
4746
  if (node === null || node === void 0 || typeof node === "boolean") return node;
4694
4747
  if (Array.isArray(node)) return node.map((child, childIndex) => enhanceNode(child, childIndex));
4695
- if (!React5__default.default.isValidElement(node)) return node;
4748
+ if (!React6__default.default.isValidElement(node)) return node;
4696
4749
  const componentName = node.type?.displayName || node.type?.name;
4697
4750
  if (componentName === "RefreshButton") return null;
4698
4751
  const fallbackLabel = componentName ? fallbackLabels[componentName] : null;
4699
4752
  const nodeProps = node.props;
4700
4753
  if (fallbackLabel) {
4701
4754
  const label = extractButtonLabel(nodeProps?.children) || fallbackLabel;
4702
- const element = React5__default.default.cloneElement(node, {
4755
+ const element = React6__default.default.cloneElement(node, {
4703
4756
  ...nodeProps,
4704
4757
  hideText: true,
4705
4758
  children: null
@@ -4710,7 +4763,7 @@ var renderIconOnlyButtons = (nodes) => {
4710
4763
  if (nodeProps?.icon) {
4711
4764
  const label = extractButtonLabel(nodeProps?.children);
4712
4765
  if (label) {
4713
- const element = React5__default.default.cloneElement(node, {
4766
+ const element = React6__default.default.cloneElement(node, {
4714
4767
  ...nodeProps,
4715
4768
  children: null
4716
4769
  });
@@ -4718,15 +4771,15 @@ var renderIconOnlyButtons = (nodes) => {
4718
4771
  }
4719
4772
  }
4720
4773
  if (nodeProps?.children) {
4721
- const mappedChildren = React5__default.default.Children.map(nodeProps.children, (child, childIndex) => enhanceNode(child, childIndex));
4722
- return React5__default.default.cloneElement(node, {
4774
+ const mappedChildren = React6__default.default.Children.map(nodeProps.children, (child, childIndex) => enhanceNode(child, childIndex));
4775
+ return React6__default.default.cloneElement(node, {
4723
4776
  ...nodeProps,
4724
4777
  children: mappedChildren
4725
4778
  });
4726
4779
  }
4727
4780
  return node;
4728
4781
  };
4729
- return React5__default.default.Children.map(nodes, (child, index) => enhanceNode(child, index));
4782
+ return React6__default.default.Children.map(nodes, (child, index) => enhanceNode(child, index));
4730
4783
  };
4731
4784
  var ResponsiveHeaderButtons = ({ children }) => {
4732
4785
  const screens = antd.Grid.useBreakpoint();
@@ -4777,7 +4830,7 @@ var extractButtonLabel2 = (node) => {
4777
4830
  }
4778
4831
  return null;
4779
4832
  }
4780
- if (React5__default.default.isValidElement(node)) {
4833
+ if (React6__default.default.isValidElement(node)) {
4781
4834
  return extractButtonLabel2(node.props?.children);
4782
4835
  }
4783
4836
  return null;
@@ -4795,12 +4848,12 @@ var renderIconOnlyButtons2 = (nodes) => {
4795
4848
  const enhanceNode = (node, index) => {
4796
4849
  if (node === null || node === void 0 || typeof node === "boolean") return node;
4797
4850
  if (Array.isArray(node)) return node.map((child, childIndex) => enhanceNode(child, childIndex));
4798
- if (!React5__default.default.isValidElement(node)) return node;
4851
+ if (!React6__default.default.isValidElement(node)) return node;
4799
4852
  const componentName = node.type?.displayName || node.type?.name;
4800
4853
  const fallbackLabel = componentName ? fallbackLabels[componentName] : null;
4801
4854
  if (fallbackLabel) {
4802
4855
  const label = extractButtonLabel2(node.props?.children) || fallbackLabel;
4803
- const element = React5__default.default.cloneElement(node, {
4856
+ const element = React6__default.default.cloneElement(node, {
4804
4857
  ...node.props,
4805
4858
  hideText: true,
4806
4859
  children: null
@@ -4811,7 +4864,7 @@ var renderIconOnlyButtons2 = (nodes) => {
4811
4864
  if (node.props?.icon) {
4812
4865
  const label = extractButtonLabel2(node.props?.children);
4813
4866
  if (label) {
4814
- const element = React5__default.default.cloneElement(node, {
4867
+ const element = React6__default.default.cloneElement(node, {
4815
4868
  ...node.props,
4816
4869
  children: null
4817
4870
  });
@@ -4819,15 +4872,15 @@ var renderIconOnlyButtons2 = (nodes) => {
4819
4872
  }
4820
4873
  }
4821
4874
  if (node.props?.children) {
4822
- const mappedChildren = React5__default.default.Children.map(node.props.children, (child, childIndex) => enhanceNode(child, childIndex));
4823
- return React5__default.default.cloneElement(node, {
4875
+ const mappedChildren = React6__default.default.Children.map(node.props.children, (child, childIndex) => enhanceNode(child, childIndex));
4876
+ return React6__default.default.cloneElement(node, {
4824
4877
  ...node.props,
4825
4878
  children: mappedChildren
4826
4879
  });
4827
4880
  }
4828
4881
  return node;
4829
4882
  };
4830
- return React5__default.default.Children.map(nodes, (child, index) => enhanceNode(child, index));
4883
+ return React6__default.default.Children.map(nodes, (child, index) => enhanceNode(child, index));
4831
4884
  };
4832
4885
  var renderStandardShowHeaderButtons = ({
4833
4886
  listButtonProps,
@@ -4848,8 +4901,8 @@ var useActionsWrapping = (headerButtons) => {
4848
4901
  const isInMultiPane = Boolean(paneNav);
4849
4902
  const isDetailPane = Boolean(paneNav && paneNav.paneIndex > 0);
4850
4903
  const actionsPosition = viewSettings?.generalActionsButtonPosition || "top-right";
4851
- const [verticalBarEl, setVerticalBarEl] = React5.useState(null);
4852
- const [topRightEl, setTopRightEl] = React5.useState(null);
4904
+ const [verticalBarEl, setVerticalBarEl] = React6.useState(null);
4905
+ const [topRightEl, setTopRightEl] = React6.useState(null);
4853
4906
  const wrappedHeaderButtons = (ctx) => {
4854
4907
  const raw = typeof headerButtons === "function" ? headerButtons(ctx) : headerButtons;
4855
4908
  if (actionsPosition === "top-right") {
@@ -4955,7 +5008,7 @@ var StandardCreate = ({ headerButtons, ...props }) => {
4955
5008
  ] });
4956
5009
  };
4957
5010
  function useKeyboardShortcuts(shortcuts) {
4958
- React5.useEffect(() => {
5011
+ React6.useEffect(() => {
4959
5012
  const handler = (e) => {
4960
5013
  for (const shortcut of shortcuts) {
4961
5014
  const keyMatch = e.key.toLowerCase() === shortcut.key.toLowerCase();
@@ -4991,7 +5044,7 @@ var wrappedPageTitleStyle2 = {
4991
5044
  };
4992
5045
  var renderWrappedPageTitle = (title) => {
4993
5046
  if (title === null || title === void 0 || title === false) return title;
4994
- return React5__default.default.createElement("div", { style: wrappedPageTitleStyle2 }, title);
5047
+ return React6__default.default.createElement("div", { style: wrappedPageTitleStyle2 }, title);
4995
5048
  };
4996
5049
  var numberFormatter = new Intl.NumberFormat(void 0, { maximumFractionDigits: 0 });
4997
5050
  var decimalFormatter = new Intl.NumberFormat(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
@@ -5107,6 +5160,39 @@ var getSortPriority = (columnSort, fieldKey) => {
5107
5160
  const index = columnSort.findIndex((item) => item.fieldKey === fieldKey);
5108
5161
  return index === -1 ? 1 : columnSort.length - index + 1;
5109
5162
  };
5163
+ var _TOKEN_KEY = "jm_access_token";
5164
+ function useAuthenticatedFileUrl(rawUrl) {
5165
+ const [src, setSrc] = React6.useState("");
5166
+ React6.useEffect(() => {
5167
+ if (!rawUrl) {
5168
+ setSrc("");
5169
+ return;
5170
+ }
5171
+ if (!rawUrl.includes("/api/file/")) {
5172
+ setSrc(rawUrl);
5173
+ return;
5174
+ }
5175
+ const token = localStorage.getItem(_TOKEN_KEY) || "";
5176
+ const controller = new AbortController();
5177
+ let objectUrl = "";
5178
+ fetch(rawUrl, {
5179
+ headers: token ? { Authorization: `Bearer ${token}` } : {},
5180
+ signal: controller.signal
5181
+ }).then((r) => r.ok ? r.blob() : Promise.reject()).then((blob) => {
5182
+ objectUrl = URL.createObjectURL(blob);
5183
+ setSrc(objectUrl);
5184
+ }).catch(() => setSrc(""));
5185
+ return () => {
5186
+ controller.abort();
5187
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
5188
+ };
5189
+ }, [rawUrl]);
5190
+ return src;
5191
+ }
5192
+ var AuthenticatedImage = ({ url, alt, style }) => {
5193
+ const src = useAuthenticatedFileUrl(url);
5194
+ return src ? /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: alt ?? "", style }) : null;
5195
+ };
5110
5196
  var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "bmp", "webp", "svg", "tif", "tiff"]);
5111
5197
  var isImageRecord = (record) => {
5112
5198
  if (record?.avatar_url || record?.image_url || record?.photo_url) return true;
@@ -5164,7 +5250,7 @@ var renderSharedGalleryCard = ({
5164
5250
  style: { width: imageWidth, display: "grid", gap: 6, cursor: onClick ? "pointer" : "default" },
5165
5251
  onClick,
5166
5252
  children: [
5167
- contentUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: contentUrl, alt: label, style: imageStyle }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...imageStyle, display: "flex", alignItems: "center", justifyContent: "center", color: "#8c8c8c" }, children: /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.FileTextOutlined, { style: { fontSize: 24 } }) }),
5253
+ contentUrl ? /* @__PURE__ */ jsxRuntime.jsx(AuthenticatedImage, { url: contentUrl, alt: label, style: imageStyle }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...imageStyle, display: "flex", alignItems: "center", justifyContent: "center", color: "#8c8c8c" }, children: /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.FileTextOutlined, { style: { fontSize: 24 } }) }),
5168
5254
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: textColor, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: label })
5169
5255
  ]
5170
5256
  },
@@ -5538,7 +5624,7 @@ var ReferenceField = ({ id, resource, onLabel }) => {
5538
5624
  const go = core.useGo();
5539
5625
  const paneNav = usePaneNavigation();
5540
5626
  const { token } = antd.theme.useToken();
5541
- React5.useEffect(() => {
5627
+ React6.useEffect(() => {
5542
5628
  if (onLabel && !isLoading && label !== void 0 && label !== null) {
5543
5629
  onLabel(String(label));
5544
5630
  }
@@ -5565,8 +5651,8 @@ var ReferenceField = ({ id, resource, onLabel }) => {
5565
5651
  };
5566
5652
  dayjs9__default.default.extend(relativeTime2__default.default);
5567
5653
  var _8 = window._ || ((text) => text);
5568
- var ReactMarkdown = React5.lazy(() => import('react-markdown').then((m) => ({ default: m.default })));
5569
- var QRCodeSVG = React5.lazy(() => import('qrcode.react').then((m) => ({ default: m.QRCodeSVG })));
5654
+ var ReactMarkdown = React6.lazy(() => import('react-markdown').then((m) => ({ default: m.default })));
5655
+ var QRCodeSVG = React6.lazy(() => import('qrcode.react').then((m) => ({ default: m.QRCodeSVG })));
5570
5656
  function formatDuration(totalSeconds) {
5571
5657
  const h = Math.floor(totalSeconds / 3600);
5572
5658
  const m = Math.floor(totalSeconds % 3600 / 60);
@@ -5602,7 +5688,7 @@ var renderFieldViewTypeReadOnly = (token, value, inTable) => {
5602
5688
  }
5603
5689
  );
5604
5690
  case "read-only-markdown":
5605
- return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 200 } }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown, { children: str }) });
5691
+ return /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 200 } }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown, { children: str }) });
5606
5692
  case "read-only-json": {
5607
5693
  let formatted = str;
5608
5694
  try {
@@ -5649,7 +5735,7 @@ var renderFieldViewTypeReadOnly = (token, value, inTable) => {
5649
5735
  case "read-only-image-url":
5650
5736
  return /* @__PURE__ */ jsxRuntime.jsx("a", { href: str, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: str, alt: "", style: { maxWidth: "100%", maxHeight: 200, objectFit: "contain", borderRadius: 4, display: "block" } }) });
5651
5737
  case "read-only-qrcode":
5652
- return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 128 } }), children: /* @__PURE__ */ jsxRuntime.jsx(QRCodeSVG, { value: str, size: 128 }) });
5738
+ return /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 128 } }), children: /* @__PURE__ */ jsxRuntime.jsx(QRCodeSVG, { value: str, size: 128 }) });
5653
5739
  case "read-only-relative": {
5654
5740
  const parsed = dayjs9__default.default(str);
5655
5741
  if (!parsed.isValid()) return str || "-";
@@ -5723,23 +5809,23 @@ var CrosstabTable = ({
5723
5809
  editable
5724
5810
  }) => {
5725
5811
  const { token } = antd.theme.useToken();
5726
- const modelField = React5.useCallback(
5812
+ const modelField = React6.useCallback(
5727
5813
  (key) => key ? allFields.find((field) => field.key === key) : void 0,
5728
5814
  [allFields]
5729
5815
  );
5730
5816
  const activeSeriesKeys = cellFieldKeys.length > 0 ? cellFieldKeys : [COUNT_KEY];
5731
- const seriesLabel = React5.useCallback(
5817
+ const seriesLabel = React6.useCallback(
5732
5818
  (seriesKey) => {
5733
5819
  if (seriesKey === COUNT_KEY) return _9("Count");
5734
5820
  return cellFieldLabels?.[seriesKey] || modelField(seriesKey)?.label || seriesKey;
5735
5821
  },
5736
5822
  [cellFieldLabels, modelField]
5737
5823
  );
5738
- const recordId = React5.useCallback(
5824
+ const recordId = React6.useCallback(
5739
5825
  (record) => record?.[editable?.pkField || "eid"] ?? record?.eid ?? record?.id,
5740
5826
  [editable?.pkField]
5741
5827
  );
5742
- const effectiveValue = React5.useCallback(
5828
+ const effectiveValue = React6.useCallback(
5743
5829
  (record, fieldKey) => {
5744
5830
  if (fieldKey === COUNT_KEY) return 1;
5745
5831
  const staged = editable?.getStagedValue?.(recordId(record), fieldKey);
@@ -5750,7 +5836,7 @@ var CrosstabTable = ({
5750
5836
  },
5751
5837
  [editable, recordId]
5752
5838
  );
5753
- const summarize = React5.useCallback(
5839
+ const summarize = React6.useCallback(
5754
5840
  (values) => {
5755
5841
  if (values.length === 0) return 0;
5756
5842
  switch (summaryFn) {
@@ -5778,7 +5864,7 @@ var CrosstabTable = ({
5778
5864
  const rowFieldDef = modelField(rowField);
5779
5865
  const hasColDimension = Boolean(colField);
5780
5866
  const hasRowDimension = Boolean(rowField);
5781
- const pivot = React5.useMemo(() => {
5867
+ const pivot = React6.useMemo(() => {
5782
5868
  const rowLabels2 = [];
5783
5869
  const colLabels2 = [];
5784
5870
  const cellRecords2 = /* @__PURE__ */ new Map();
@@ -5798,32 +5884,32 @@ var CrosstabTable = ({
5798
5884
  return { rowLabels: rowLabels2, colLabels: colLabels2, cellRecords: cellRecords2 };
5799
5885
  }, [rows, rowFieldDef, colFieldDef, hasColDimension, formatCategoryValue, activeSeriesKeys]);
5800
5886
  const { rowLabels, colLabels, cellRecords } = pivot;
5801
- const isAggregatedField = React5.useCallback((seriesKey) => {
5887
+ const isAggregatedField = React6.useCallback((seriesKey) => {
5802
5888
  if (seriesKey === COUNT_KEY) return true;
5803
5889
  const field = modelField(seriesKey);
5804
5890
  return Boolean(field && field.type === "number" && !field.reference);
5805
5891
  }, [modelField]);
5806
- const cellAllRecords = React5.useCallback(
5892
+ const cellAllRecords = React6.useCallback(
5807
5893
  (rowLabel, colLabel, seriesKey) => {
5808
5894
  return cellRecords.get(`${rowLabel}::${colLabel}`)?.get(seriesKey) || [];
5809
5895
  },
5810
5896
  [cellRecords]
5811
5897
  );
5812
- const contributingRecords = React5.useCallback(
5898
+ const contributingRecords = React6.useCallback(
5813
5899
  (rowLabel, colLabel, seriesKey) => {
5814
5900
  const records = cellRecords.get(`${rowLabel}::${colLabel}`)?.get(seriesKey) || [];
5815
5901
  return records.filter((rec) => effectiveValue(rec, seriesKey) !== null);
5816
5902
  },
5817
5903
  [cellRecords, effectiveValue]
5818
5904
  );
5819
- const cellAggregate = React5.useCallback(
5905
+ const cellAggregate = React6.useCallback(
5820
5906
  (rowLabel, colLabel, seriesKey) => {
5821
5907
  const values = contributingRecords(rowLabel, colLabel, seriesKey).map((rec) => effectiveValue(rec, seriesKey));
5822
5908
  return values.length > 0 ? summarize(values) : null;
5823
5909
  },
5824
5910
  [contributingRecords, effectiveValue, summarize]
5825
5911
  );
5826
- const seriesMaxes = React5.useMemo(() => {
5912
+ const seriesMaxes = React6.useMemo(() => {
5827
5913
  return activeSeriesKeys.reduce((acc, seriesKey) => {
5828
5914
  let maxForSeries = 0;
5829
5915
  rowLabels.forEach((rowLabel) => {
@@ -5836,10 +5922,10 @@ var CrosstabTable = ({
5836
5922
  return acc;
5837
5923
  }, {});
5838
5924
  }, [activeSeriesKeys, rowLabels, colLabels, cellAggregate]);
5839
- const inputRefs = React5.useRef(/* @__PURE__ */ new Map());
5925
+ const inputRefs = React6.useRef(/* @__PURE__ */ new Map());
5840
5926
  const cellAddr = (r, c) => `${r}:${c}`;
5841
5927
  const editableColumns = colLabels.length * activeSeriesKeys.length;
5842
- const focusCell = React5.useCallback((r, c) => {
5928
+ const focusCell = React6.useCallback((r, c) => {
5843
5929
  if (r < 0 || c < 0 || r >= rowLabels.length || c >= editableColumns) return;
5844
5930
  const el = inputRefs.current.get(cellAddr(r, c));
5845
5931
  if (el) {
@@ -5847,7 +5933,7 @@ var CrosstabTable = ({
5847
5933
  el.select?.();
5848
5934
  }
5849
5935
  }, [rowLabels.length, editableColumns]);
5850
- const isSeriesEditable = React5.useCallback(
5936
+ const isSeriesEditable = React6.useCallback(
5851
5937
  (rowLabel, colLabel, seriesKey) => {
5852
5938
  if (!editable || seriesKey === COUNT_KEY || !isAggregatedField(seriesKey)) return false;
5853
5939
  const n = contributingRecords(rowLabel, colLabel, seriesKey).length;
@@ -5857,7 +5943,7 @@ var CrosstabTable = ({
5857
5943
  },
5858
5944
  [editable, contributingRecords, summaryFn, isAggregatedField]
5859
5945
  );
5860
- const computeProration = React5.useCallback(
5946
+ const computeProration = React6.useCallback(
5861
5947
  (records, seriesKey, newAggregate) => {
5862
5948
  const round2 = (v) => Math.round((v + Number.EPSILON) * 100) / 100;
5863
5949
  const n = records.length;
@@ -5889,7 +5975,7 @@ var CrosstabTable = ({
5889
5975
  },
5890
5976
  [recordId, effectiveValue, summaryFn]
5891
5977
  );
5892
- const commitCellEdit = React5.useCallback(
5978
+ const commitCellEdit = React6.useCallback(
5893
5979
  (rowLabel, colLabel, seriesKey, newAggregate) => {
5894
5980
  if (!editable || newAggregate === null || Number.isNaN(newAggregate)) return;
5895
5981
  const records = contributingRecords(rowLabel, colLabel, seriesKey);
@@ -6109,6 +6195,8 @@ var AnalysisChart = ({
6109
6195
  };
6110
6196
  const primarySeriesKey = seriesKeys[0] || "__count__";
6111
6197
  const secondarySeriesKey = seriesKeys[1];
6198
+ const resolveNumericField = (fields, n) => fields[Math.min(n, fields.length - 1)] ?? { key: "__count__", label: _10("Count") };
6199
+ const resolveCategoryField = (field1, field2) => field2 ?? field1;
6112
6200
  const getNumericValue = (record, key) => {
6113
6201
  if (key === "__count__") return 1;
6114
6202
  const value = Number(record?.[key]);
@@ -6525,11 +6613,11 @@ var AnalysisChart = ({
6525
6613
  ] });
6526
6614
  };
6527
6615
  const renderScatter = (isBubble) => {
6528
- if (numericFields.length < 2) {
6529
- return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Scatter needs at least two numeric fields." });
6616
+ if (numericFields.length === 0) {
6617
+ return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Scatter needs at least one numeric field." });
6530
6618
  }
6531
- const xField = numericFields[0];
6532
- const yField = numericFields[1];
6619
+ const xField = resolveNumericField(numericFields, 0);
6620
+ const yField = resolveNumericField(numericFields, 1);
6533
6621
  const points = rawRows.map((row) => {
6534
6622
  const x = getNumericValue(row, xField.key);
6535
6623
  const y = getNumericValue(row, yField.key);
@@ -6807,11 +6895,12 @@ var AnalysisChart = ({
6807
6895
  ] });
6808
6896
  };
6809
6897
  const renderHeatmap = () => {
6810
- if (!categoryField1 || !categoryField2) {
6811
- return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Heatmap needs two category fields." });
6898
+ if (!categoryField1) {
6899
+ return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Heatmap needs a category field." });
6812
6900
  }
6901
+ const effectiveCat2 = resolveCategoryField(categoryField1, categoryField2);
6813
6902
  const cat1Field = modelField(categoryField1);
6814
- const cat2Field = modelField(categoryField2);
6903
+ const cat2Field = modelField(effectiveCat2);
6815
6904
  const rowLabels = [];
6816
6905
  const colLabels = [];
6817
6906
  const grid = /* @__PURE__ */ new Map();
@@ -6889,43 +6978,45 @@ var AnalysisChart = ({
6889
6978
  ] });
6890
6979
  };
6891
6980
  const renderCrosstab = () => {
6892
- if (!categoryField1 || !categoryField2) {
6893
- return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Crosstab needs two category fields." });
6981
+ if (!categoryField1) {
6982
+ return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Crosstab needs a category field." });
6894
6983
  }
6984
+ const effectiveCat2 = resolveCategoryField(categoryField1, categoryField2);
6895
6985
  const cat1Field = modelField(categoryField1);
6896
- const cat2Field = modelField(categoryField2);
6986
+ const cat2Field = modelField(effectiveCat2);
6897
6987
  return /* @__PURE__ */ jsxRuntime.jsx(
6898
6988
  CrosstabTable,
6899
6989
  {
6900
6990
  rows: rawRows,
6901
6991
  rowField: categoryField1,
6902
- colField: categoryField2,
6992
+ colField: effectiveCat2 ?? categoryField1,
6903
6993
  cellFieldKeys: seriesKeys,
6904
6994
  cellFieldLabels: seriesLabels,
6905
6995
  allFields,
6906
6996
  summaryFn,
6907
6997
  formatCategoryValue,
6908
6998
  numericBarColor,
6909
- caption: `${_10("Crosstab")}: ${cat1Field?.label || categoryField1} \xD7 ${cat2Field?.label || categoryField2} (${summaryFn})`
6999
+ caption: `${_10("Crosstab")}: ${cat1Field?.label || categoryField1} \xD7 ${cat2Field?.label || effectiveCat2} (${summaryFn})`
6910
7000
  }
6911
7001
  );
6912
7002
  };
6913
7003
  const renderRadar = () => {
6914
- if (seriesKeys.length < 3) {
6915
- return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Radar needs at least three series." });
7004
+ if (seriesKeys.length === 0) {
7005
+ return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Radar needs at least one series." });
6916
7006
  }
7007
+ const effectiveSeriesKeys = seriesKeys.length >= 3 ? seriesKeys : Array.from({ length: 3 }, (_43, i) => seriesKeys[i % seriesKeys.length]);
6917
7008
  const centerX = paddingLeft + chartWidth / 2;
6918
7009
  const centerY = paddingTop + chartHeight / 2;
6919
7010
  const radius = Math.min(chartWidth, chartHeight) * 0.35;
6920
- const maxBySeries = seriesKeys.reduce((acc, key) => {
7011
+ const maxBySeries = effectiveSeriesKeys.reduce((acc, key) => {
6921
7012
  acc[key] = Math.max(...data.map((group) => group.values[key] || 0), 1);
6922
7013
  return acc;
6923
7014
  }, {});
6924
- const angleStep = Math.PI * 2 / seriesKeys.length;
7015
+ const angleStep = Math.PI * 2 / effectiveSeriesKeys.length;
6925
7016
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
6926
7017
  renderTitle(),
6927
7018
  renderCaption("Radar chart"),
6928
- seriesKeys.map((seriesKey, index) => {
7019
+ effectiveSeriesKeys.map((seriesKey, index) => {
6929
7020
  const angle = -Math.PI / 2 + index * angleStep;
6930
7021
  const x = centerX + radius * Math.cos(angle);
6931
7022
  const y = centerY + radius * Math.sin(angle);
@@ -6935,7 +7026,7 @@ var AnalysisChart = ({
6935
7026
  ] }, `radar-axis-${seriesKey}`);
6936
7027
  }),
6937
7028
  data.map((group, groupIndex) => {
6938
- const points = seriesKeys.map((seriesKey, index) => {
7029
+ const points = effectiveSeriesKeys.map((seriesKey, index) => {
6939
7030
  const value = group.values[seriesKey] || 0;
6940
7031
  const ratio = value / Math.max(1, maxBySeries[seriesKey]);
6941
7032
  const angle = -Math.PI / 2 + index * angleStep;
@@ -6960,13 +7051,74 @@ var AnalysisChart = ({
6960
7051
  })
6961
7052
  ] });
6962
7053
  };
6963
- const renderCombo = () => {
6964
- if (!secondarySeriesKey) {
6965
- return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Combo needs at least two series selected." });
7054
+ const render3D = () => {
7055
+ if (numericFields.length === 0) {
7056
+ return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "3D scatter needs at least one numeric field." });
6966
7057
  }
7058
+ const xField = resolveNumericField(numericFields, 0);
7059
+ const yField = resolveNumericField(numericFields, 1);
7060
+ const zField = resolveNumericField(numericFields, 2);
7061
+ const points = rawRows.map((row) => {
7062
+ const x = getNumericValue(row, xField.key);
7063
+ const y = getNumericValue(row, yField.key);
7064
+ const z = getNumericValue(row, zField.key);
7065
+ if (x === null || y === null || z === null) return null;
7066
+ return { x, y, z };
7067
+ }).filter((p) => !!p);
7068
+ if (points.length === 0) return renderNoChartDataMessage();
7069
+ const xs = points.map((p) => p.x);
7070
+ const ys = points.map((p) => p.y);
7071
+ const zs = points.map((p) => p.z);
7072
+ const xMin = Math.min(...xs), xMax = Math.max(...xs);
7073
+ const yMin = Math.min(...ys), yMax = Math.max(...ys);
7074
+ const zMin = Math.min(...zs), zMax = Math.max(...zs);
7075
+ const norm = (v, lo, hi) => hi === lo ? 0.5 : (v - lo) / (hi - lo);
7076
+ const isoScale = Math.min(chartWidth, chartHeight) * 0.38;
7077
+ const cx = paddingLeft + chartWidth * 0.5;
7078
+ const cy = paddingTop + chartHeight * 0.55;
7079
+ const cos30 = Math.cos(Math.PI / 6);
7080
+ const sin30 = Math.sin(Math.PI / 6);
7081
+ const project = (nx, ny, nz) => ({
7082
+ sx: cx + (nx - nz) * cos30 * isoScale,
7083
+ sy: cy - ny * isoScale + (nx + nz) * sin30 * isoScale
7084
+ });
7085
+ const axisEnd = (nx, ny, nz) => project(nx, ny, nz);
7086
+ const origin = project(0, 0, 0);
7087
+ const xTip = axisEnd(1, 0, 0);
7088
+ const yTip = axisEnd(0, 1, 0);
7089
+ const zTip = axisEnd(0, 0, 1);
7090
+ const projected = points.map(
7091
+ (p) => project(norm(p.x, xMin, xMax), norm(p.y, yMin, yMax), norm(p.z, zMin, zMax))
7092
+ );
7093
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
7094
+ renderTitle(),
7095
+ renderCaption(`3D: ${xField.label} \xD7 ${yField.label} \xD7 ${zField.label}`),
7096
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: origin.sx, y1: origin.sy, x2: xTip.sx, y2: xTip.sy, stroke: colors[0], strokeWidth: 1.5, opacity: 0.6 }),
7097
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: origin.sx, y1: origin.sy, x2: yTip.sx, y2: yTip.sy, stroke: colors[1], strokeWidth: 1.5, opacity: 0.6 }),
7098
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: origin.sx, y1: origin.sy, x2: zTip.sx, y2: zTip.sy, stroke: colors[2], strokeWidth: 1.5, opacity: 0.6 }),
7099
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: xTip.sx + 4, y: xTip.sy + 4, fontSize: "11", fill: colors[0], children: xField.label }),
7100
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: yTip.sx + 4, y: yTip.sy, fontSize: "11", fill: colors[1], children: yField.label }),
7101
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: zTip.sx + 4, y: zTip.sy + 4, fontSize: "11", fill: colors[2], children: zField.label }),
7102
+ projected.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(
7103
+ "circle",
7104
+ {
7105
+ className: "chart-item chart-point",
7106
+ style: { "--delay": `${i * 8}ms` },
7107
+ cx: p.sx,
7108
+ cy: p.sy,
7109
+ r: 4,
7110
+ fill: colors[0],
7111
+ opacity: 0.7
7112
+ },
7113
+ `3d-${i}`
7114
+ ))
7115
+ ] });
7116
+ };
7117
+ const renderCombo = () => {
7118
+ const effectiveSecondaryKey = secondarySeriesKey ?? primarySeriesKey;
6967
7119
  const valuesCombo = data.flatMap((group) => [
6968
7120
  group.values[primarySeriesKey] || 0,
6969
- group.values[secondarySeriesKey] || 0
7121
+ group.values[effectiveSecondaryKey] || 0
6970
7122
  ]);
6971
7123
  const maxCombo = Math.max(...valuesCombo, 1);
6972
7124
  const minCombo = Math.min(...valuesCombo, 0);
@@ -6975,7 +7127,7 @@ var AnalysisChart = ({
6975
7127
  const barWidth2 = groupWidth2 * 0.6;
6976
7128
  const points = data.map((group, index) => {
6977
7129
  const x = paddingLeft + index * groupWidth2 + groupWidth2 / 2;
6978
- const y = scaleYCombo(group.values[secondarySeriesKey] || 0);
7130
+ const y = scaleYCombo(group.values[effectiveSecondaryKey] || 0);
6979
7131
  return `${x},${y}`;
6980
7132
  }).join(" ");
6981
7133
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
@@ -6983,7 +7135,7 @@ var AnalysisChart = ({
6983
7135
  renderLegendItems(
6984
7136
  [
6985
7137
  { label: seriesLabels[primarySeriesKey] || primarySeriesKey, color: colors[0] },
6986
- { label: seriesLabels[secondarySeriesKey] || secondarySeriesKey, color: colors[2] }
7138
+ { label: seriesLabels[effectiveSecondaryKey] || effectiveSecondaryKey, color: colors[2] }
6987
7139
  ],
6988
7140
  8
6989
7141
  ),
@@ -7034,13 +7186,14 @@ var AnalysisChart = ({
7034
7186
  chartType === "histogram" && renderHistogram(),
7035
7187
  chartType === "scatter" && renderScatter(false),
7036
7188
  chartType === "bubble" && renderScatter(true),
7037
- chartType === "box" && renderBoxPlot(),
7189
+ (chartType === "box" || chartType === "boxplot") && renderBoxPlot(),
7038
7190
  chartType === "waterfall" && renderWaterfall(),
7039
7191
  chartType === "heatmap" && renderHeatmap(),
7040
7192
  chartType === "crosstab" && renderCrosstab(),
7041
7193
  chartType === "radar" && renderRadar(),
7042
7194
  chartType === "combo" && renderCombo(),
7043
- chartType !== "histogram" && chartType !== "scatter" && chartType !== "bubble" && chartType !== "box" && chartType !== "waterfall" && chartType !== "heatmap" && chartType !== "crosstab" && chartType !== "radar" && chartType !== "combo" && /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
7195
+ chartType === "3d" && render3D(),
7196
+ (chartType === "bar" || chartType === "line" || chartType === "area" || chartType === "stacked" || chartType === "bar-horizontal" || chartType === "stacked-horizontal" || chartType === "area-horizontal") && /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
7044
7197
  renderTitle(),
7045
7198
  renderLegendItems(
7046
7199
  seriesKeys.map((seriesKey, index) => ({
@@ -7278,25 +7431,25 @@ var ExecutableHtml = ({
7278
7431
  inheritTabRowBackground = false,
7279
7432
  fontSizeOverride
7280
7433
  }) => {
7281
- const htmlRef = React5.useRef(null);
7282
- const iframeRef = React5.useRef(null);
7283
- const observerRef = React5.useRef(null);
7284
- const appendedChunksRef = React5.useRef(0);
7285
- const scriptIdRef = React5.useRef(0);
7286
- const syncHeightTimerRef = React5.useRef(null);
7287
- const lastSetHeightRef = React5.useRef(0);
7288
- const [fontFamily, setFontFamily] = React5.useState("Arial, sans-serif");
7289
- const [fontSize, setFontSize] = React5.useState("14px");
7290
- const [lineHeight, setLineHeight] = React5.useState("1.5715");
7291
- const [tabRowBackground, setTabRowBackground] = React5.useState("#fafafa");
7292
- const { mode: colorMode } = React5.useContext(ColorModeContext);
7434
+ const htmlRef = React6.useRef(null);
7435
+ const iframeRef = React6.useRef(null);
7436
+ const observerRef = React6.useRef(null);
7437
+ const appendedChunksRef = React6.useRef(0);
7438
+ const scriptIdRef = React6.useRef(0);
7439
+ const syncHeightTimerRef = React6.useRef(null);
7440
+ const lastSetHeightRef = React6.useRef(0);
7441
+ const [fontFamily, setFontFamily] = React6.useState("Arial, sans-serif");
7442
+ const [fontSize, setFontSize] = React6.useState("14px");
7443
+ const [lineHeight, setLineHeight] = React6.useState("1.5715");
7444
+ const [tabRowBackground, setTabRowBackground] = React6.useState("#fafafa");
7445
+ const { mode: colorMode } = React6.useContext(ColorModeContext);
7293
7446
  const isDark = colorMode === "dark";
7294
- React5.useRef(performance.now());
7295
- const instanceId = React5.useRef(Math.random().toString(36).slice(2, 6));
7296
- const htmlRefForEffect = React5.useRef(html);
7447
+ React6.useRef(performance.now());
7448
+ const instanceId = React6.useRef(Math.random().toString(36).slice(2, 6));
7449
+ const htmlRefForEffect = React6.useRef(html);
7297
7450
  htmlRefForEffect.current = html;
7298
7451
  traceLog("ExecutableHtml", `[${instanceId.current}] mount mode=${mode} title=${title} htmlLen=${(html || "").length}`);
7299
- const executeScriptNodesSequentially = React5.useCallback(async (doc, scriptNodes, isCancelled) => {
7452
+ const executeScriptNodesSequentially = React6.useCallback(async (doc, scriptNodes, isCancelled) => {
7300
7453
  for (const oldScript of scriptNodes) {
7301
7454
  if (isCancelled?.()) return;
7302
7455
  const newScript = doc.createElement("script");
@@ -7318,7 +7471,7 @@ var ExecutableHtml = ({
7318
7471
  });
7319
7472
  }
7320
7473
  }, []);
7321
- React5.useEffect(() => {
7474
+ React6.useEffect(() => {
7322
7475
  if (mode !== "inline") return;
7323
7476
  const container = htmlRef.current;
7324
7477
  if (!container || !html) return;
@@ -7329,7 +7482,7 @@ var ExecutableHtml = ({
7329
7482
  cancelled = true;
7330
7483
  };
7331
7484
  }, [html, mode, executeScriptNodesSequentially]);
7332
- React5.useEffect(() => {
7485
+ React6.useEffect(() => {
7333
7486
  if (mode !== "iframe") return;
7334
7487
  if (!inheritTypography && !inheritTabRowBackground) return;
7335
7488
  if (typeof window === "undefined") return;
@@ -7355,7 +7508,7 @@ var ExecutableHtml = ({
7355
7508
  if (resolvedBg) setTabRowBackground(resolvedBg);
7356
7509
  }
7357
7510
  }, [inheritTabRowBackground, inheritTypography, mode]);
7358
- const htmlShell = React5.useMemo(() => `<!doctype html>
7511
+ const htmlShell = React6.useMemo(() => `<!doctype html>
7359
7512
  <html>
7360
7513
  <head>
7361
7514
  <meta charset="utf-8" />
@@ -7386,7 +7539,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
7386
7539
  </head>
7387
7540
  <body></body>
7388
7541
  </html>`, [fontFamily, fontSize, lineHeight, tabRowBackground, isDark]);
7389
- const syncHeight = React5.useCallback(() => {
7542
+ const syncHeight = React6.useCallback(() => {
7390
7543
  if (syncHeightTimerRef.current) clearTimeout(syncHeightTimerRef.current);
7391
7544
  syncHeightTimerRef.current = setTimeout(() => {
7392
7545
  syncHeightTimerRef.current = null;
@@ -7404,7 +7557,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
7404
7557
  iframe.style.height = `${nextHeight}px`;
7405
7558
  }, 100);
7406
7559
  }, [minHeight]);
7407
- const appendHtmlChunk = React5.useCallback(async (chunk) => {
7560
+ const appendHtmlChunk = React6.useCallback(async (chunk) => {
7408
7561
  const doc = iframeRef.current?.contentDocument;
7409
7562
  if (!doc || !doc.body || !chunk) return false;
7410
7563
  const host = doc.createElement("div");
@@ -7425,7 +7578,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
7425
7578
  syncHeight();
7426
7579
  return true;
7427
7580
  }, [syncHeight, executeScriptNodesSequentially]);
7428
- React5.useEffect(() => {
7581
+ React6.useEffect(() => {
7429
7582
  if (mode !== "iframe") return;
7430
7583
  const iframe = iframeRef.current;
7431
7584
  if (!iframe) return;
@@ -7468,7 +7621,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
7468
7621
  iframe.removeEventListener("load", onLoad);
7469
7622
  };
7470
7623
  }, [htmlShell, resetToken, appendHtmlChunk, syncHeight, mode]);
7471
- React5.useEffect(() => {
7624
+ React6.useEffect(() => {
7472
7625
  if (mode !== "iframe") return;
7473
7626
  if (!htmlChunks || htmlChunks.length <= appendedChunksRef.current) return;
7474
7627
  const nextChunks = htmlChunks.slice(appendedChunksRef.current);
@@ -7480,13 +7633,20 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
7480
7633
  appendedChunksRef.current += appendedCount;
7481
7634
  })();
7482
7635
  }, [htmlChunks, appendHtmlChunk, mode]);
7483
- React5.useEffect(() => {
7636
+ React6.useEffect(() => {
7484
7637
  return () => {
7485
7638
  if (observerRef.current) observerRef.current.disconnect();
7486
7639
  observerRef.current = null;
7487
7640
  if (syncHeightTimerRef.current) clearTimeout(syncHeightTimerRef.current);
7488
7641
  };
7489
7642
  }, []);
7643
+ const inlineHtml = React6.useMemo(
7644
+ () => (html || "").replace(
7645
+ /<script\b[^>]*\bsrc=["']?[^"'>]*cdn\.plot\.ly[^"'>]*["']?[^>]*><\/script>/gi,
7646
+ ""
7647
+ ),
7648
+ [html]
7649
+ );
7490
7650
  if (mode === "iframe") {
7491
7651
  return /* @__PURE__ */ jsxRuntime.jsx(
7492
7652
  "iframe",
@@ -7497,7 +7657,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
7497
7657
  }
7498
7658
  );
7499
7659
  }
7500
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: htmlRef, dangerouslySetInnerHTML: { __html: html || "" }, style });
7660
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: htmlRef, dangerouslySetInnerHTML: { __html: inlineHtml }, style });
7501
7661
  };
7502
7662
 
7503
7663
  // src/components/DynamicResource/relations/helpers.ts
@@ -7564,23 +7724,23 @@ var MetadataModal = ({ model, allModels, open, onClose }) => {
7564
7724
  const apiUrl = core.useApiUrl();
7565
7725
  const tone = useModelTone(model);
7566
7726
  const modelLabel = getModelLabel(model);
7567
- const [nestedModel, setNestedModel] = React5.useState(null);
7568
- const [activeTab, setActiveTab] = React5.useState("fields");
7569
- const [graphHtml, setGraphHtml] = React5.useState(null);
7570
- const [graphLoading, setGraphLoading] = React5.useState(false);
7571
- const [graphError, setGraphError] = React5.useState(null);
7572
- React5.useEffect(() => {
7727
+ const [nestedModel, setNestedModel] = React6.useState(null);
7728
+ const [activeTab, setActiveTab] = React6.useState("fields");
7729
+ const [graphHtml, setGraphHtml] = React6.useState(null);
7730
+ const [graphLoading, setGraphLoading] = React6.useState(false);
7731
+ const [graphError, setGraphError] = React6.useState(null);
7732
+ React6.useEffect(() => {
7573
7733
  setGraphHtml(null);
7574
7734
  setGraphError(null);
7575
7735
  }, [model.name]);
7576
- const findRelatedModel = React5.useCallback((name) => {
7736
+ const findRelatedModel = React6.useCallback((name) => {
7577
7737
  if (!name || !allModels) return void 0;
7578
7738
  const lower = name.toLowerCase();
7579
7739
  return allModels.find(
7580
7740
  (m) => (m.name || "").toLowerCase() === lower || (m.resource || "").toLowerCase() === lower
7581
7741
  );
7582
7742
  }, [allModels]);
7583
- const loadGraph = React5.useCallback(async () => {
7743
+ const loadGraph = React6.useCallback(async () => {
7584
7744
  if (graphHtml !== null || graphLoading) return;
7585
7745
  setGraphLoading(true);
7586
7746
  setGraphError(null);
@@ -7616,13 +7776,13 @@ var MetadataModal = ({ model, allModels, open, onClose }) => {
7616
7776
  setGraphLoading(false);
7617
7777
  }
7618
7778
  }, [apiUrl, model, modelLabel, graphHtml, graphLoading, findRelatedModel]);
7619
- React5.useEffect(() => {
7779
+ React6.useEffect(() => {
7620
7780
  if (activeTab === "knowledge_graph") {
7621
7781
  loadGraph();
7622
7782
  }
7623
7783
  }, [activeTab, loadGraph]);
7624
7784
  const navigate = reactRouterDom.useNavigate();
7625
- React5.useEffect(() => {
7785
+ React6.useEffect(() => {
7626
7786
  const handler = (e) => {
7627
7787
  if (e.data?.action === "metadata_graph_navigate" && e.data?.url) {
7628
7788
  onClose();
@@ -7862,7 +8022,7 @@ var MetadataModal = ({ model, allModels, open, onClose }) => {
7862
8022
  };
7863
8023
  var _13 = window._ || ((text) => text);
7864
8024
  var useMetadataModal = (model, allModels) => {
7865
- const [metadataOpen, setMetadataOpen] = React5.useState(false);
8025
+ const [metadataOpen, setMetadataOpen] = React6.useState(false);
7866
8026
  const metadataButton = /* @__PURE__ */ jsxRuntime.jsx(antd.Tooltip, { title: _13("Metadata"), children: /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { size: "small", icon: /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.InfoCircleOutlined, {}), onClick: () => setMetadataOpen(true) }) });
7867
8027
  const metadataModal = /* @__PURE__ */ jsxRuntime.jsx(MetadataModal, { model, allModels, open: metadataOpen, onClose: () => setMetadataOpen(false) });
7868
8028
  return { metadataButton, metadataModal };
@@ -7882,7 +8042,7 @@ var useShowEditableForm = (resource, id) => {
7882
8042
  });
7883
8043
  const record = queryResult?.data?.data;
7884
8044
  const recordId = record?.eid ?? record?.id ?? id;
7885
- useKeyboardShortcuts(React5.useMemo(() => [
8045
+ useKeyboardShortcuts(React6.useMemo(() => [
7886
8046
  { key: "s", ctrl: true, handler: () => formProps?.form?.submit() },
7887
8047
  { key: "Escape", handler: () => navigate(-1) }
7888
8048
  ], [formProps?.form, navigate]));
@@ -7950,7 +8110,7 @@ var renderModelHeading = ({
7950
8110
  paddingLeft: 10,
7951
8111
  paddingRight: 10
7952
8112
  },
7953
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minWidth: 0, fontSize: 16, fontWeight: 700, color: tone.solid, padding: "2px 8px" }, children: title })
8113
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minWidth: 0, fontSize: 18, fontWeight: 700, color: tone.solid, padding: "2px 8px" }, children: title })
7954
8114
  }
7955
8115
  );
7956
8116
  };
@@ -8091,14 +8251,14 @@ var RelationsExplorer = ({ model, record, allModels, isActive = true }) => {
8091
8251
  const apiUrl = core.useApiUrl();
8092
8252
  const go = core.useGo();
8093
8253
  const paneNav = usePaneNavigation();
8094
- const [reverseTreeData, setReverseTreeData] = React5.useState([]);
8095
- const [forwardTreeData, setForwardTreeData] = React5.useState([]);
8096
- const [loading, setLoading] = React5.useState(true);
8254
+ const [reverseTreeData, setReverseTreeData] = React6.useState([]);
8255
+ const [forwardTreeData, setForwardTreeData] = React6.useState([]);
8256
+ const [loading, setLoading] = React6.useState(true);
8097
8257
  const isReverse = (rel) => {
8098
8258
  if (rel.relationName && rel.relationName.endsWith("_reverse")) return true;
8099
8259
  return !rel.otherResource;
8100
8260
  };
8101
- React5.useEffect(() => {
8261
+ React6.useEffect(() => {
8102
8262
  if (!isActive) {
8103
8263
  setLoading(false);
8104
8264
  return;
@@ -8268,9 +8428,9 @@ var RelationsExplorer = ({ model, record, allModels, isActive = true }) => {
8268
8428
  ] });
8269
8429
  };
8270
8430
  function usePinRecord(resource, recordId) {
8271
- const [pinned, setPinned] = React5.useState(null);
8272
- const [loading, setLoading] = React5.useState(false);
8273
- React5.useEffect(() => {
8431
+ const [pinned, setPinned] = React6.useState(null);
8432
+ const [loading, setLoading] = React6.useState(false);
8433
+ React6.useEffect(() => {
8274
8434
  if (!resource || recordId === void 0 || recordId === null || recordId === "") return;
8275
8435
  let cancelled = false;
8276
8436
  authenticatedFetch(
@@ -8284,7 +8444,7 @@ function usePinRecord(resource, recordId) {
8284
8444
  cancelled = true;
8285
8445
  };
8286
8446
  }, [resource, recordId]);
8287
- const pin = React5.useCallback(async () => {
8447
+ const pin = React6.useCallback(async () => {
8288
8448
  if (!resource || recordId === void 0) return;
8289
8449
  setLoading(true);
8290
8450
  try {
@@ -8298,7 +8458,7 @@ function usePinRecord(resource, recordId) {
8298
8458
  setLoading(false);
8299
8459
  }
8300
8460
  }, [resource, recordId]);
8301
- const unpin = React5.useCallback(async () => {
8461
+ const unpin = React6.useCallback(async () => {
8302
8462
  if (!resource || recordId === void 0) return;
8303
8463
  setLoading(true);
8304
8464
  try {
@@ -8311,7 +8471,7 @@ function usePinRecord(resource, recordId) {
8311
8471
  setLoading(false);
8312
8472
  }
8313
8473
  }, [resource, recordId]);
8314
- const toggle = React5.useCallback(() => pinned ? unpin() : pin(), [pinned, pin, unpin]);
8474
+ const toggle = React6.useCallback(() => pinned ? unpin() : pin(), [pinned, pin, unpin]);
8315
8475
  return { pinned, loading, pin, unpin, toggle };
8316
8476
  }
8317
8477
  async function unpinRecords(resource, recordIds) {
@@ -8327,17 +8487,17 @@ async function unpinRecords(resource, recordIds) {
8327
8487
  var _17 = window._ || ((text) => text);
8328
8488
  var useShowActionsPreferences = (model, allModels, record, saveButtonProps, configureLayoutButtonRef, saveLayoutRef) => {
8329
8489
  const apiUrl = core.useApiUrl();
8330
- const allModelsList = React5.useMemo(() => allModels || [], [allModels]);
8331
- const [showRelationActions, setShowRelationActions] = React5.useState(DEFAULT_SHOW_RELATION_ROW_ACTIONS);
8332
- const [showRelationCreate, setShowRelationCreate] = React5.useState(DEFAULT_RELATION_CREATE_ACTIONS);
8333
- const [isSavingActionsPrefs, setIsSavingActionsPrefs] = React5.useState(false);
8334
- const actionsPrefsTouchedRef = React5.useRef(false);
8335
- const actionsPrefsLoadedRef = React5.useRef(false);
8336
- const actionsPrefsResourceRef = React5.useRef(null);
8337
- const markActionsPrefsTouched = React5.useCallback(() => {
8490
+ const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
8491
+ const [showRelationActions, setShowRelationActions] = React6.useState(DEFAULT_SHOW_RELATION_ROW_ACTIONS);
8492
+ const [showRelationCreate, setShowRelationCreate] = React6.useState(DEFAULT_RELATION_CREATE_ACTIONS);
8493
+ const [isSavingActionsPrefs, setIsSavingActionsPrefs] = React6.useState(false);
8494
+ const actionsPrefsTouchedRef = React6.useRef(false);
8495
+ const actionsPrefsLoadedRef = React6.useRef(false);
8496
+ const actionsPrefsResourceRef = React6.useRef(null);
8497
+ const markActionsPrefsTouched = React6.useCallback(() => {
8338
8498
  actionsPrefsTouchedRef.current = true;
8339
8499
  }, []);
8340
- const saveActionsPreferences = React5.useCallback(async () => {
8500
+ const saveActionsPreferences = React6.useCallback(async () => {
8341
8501
  const resourceKey = resolveResourcePath(model.resource || model.name, allModelsList);
8342
8502
  const preferences = {
8343
8503
  showActions: showRelationActions,
@@ -8360,7 +8520,7 @@ var useShowActionsPreferences = (model, allModels, record, saveButtonProps, conf
8360
8520
  setIsSavingActionsPrefs(false);
8361
8521
  }
8362
8522
  }, [apiUrl, allModelsList, model.name, model.resource, showRelationActions, showRelationCreate]);
8363
- React5.useEffect(() => {
8523
+ React6.useEffect(() => {
8364
8524
  const resourceKey = resolveResourcePath(model.resource || model.name, allModelsList);
8365
8525
  if (actionsPrefsResourceRef.current !== resourceKey) {
8366
8526
  actionsPrefsLoadedRef.current = false;
@@ -8445,7 +8605,7 @@ var useShowActionsPreferences = (model, allModels, record, saveButtonProps, conf
8445
8605
  const resource = model.resource || model.name;
8446
8606
  const { pinned, loading: pinLoading, toggle: togglePin } = usePinRecord(resource, recordId);
8447
8607
  const { metadataButton, metadataModal } = useMetadataModal(model, allModels);
8448
- const [exploreOpen, setExploreOpen] = React5.useState(false);
8608
+ const [exploreOpen, setExploreOpen] = React6.useState(false);
8449
8609
  const headerButtons = ({ defaultButtons }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8450
8610
  metadataButton,
8451
8611
  metadataModal,
@@ -8482,7 +8642,7 @@ var useShowActionsPreferences = (model, allModels, record, saveButtonProps, conf
8482
8642
  headerButtons
8483
8643
  };
8484
8644
  };
8485
- var PrimaryShowContext = React5__default.default.createContext(null);
8645
+ var PrimaryShowContext = React6__default.default.createContext(null);
8486
8646
 
8487
8647
  // src/components/DynamicResource/utils/columnFilters.ts
8488
8648
  var truncateLabel = (s) => s.length > 15 ? s.substring(0, 15) + "\u2026" : s;
@@ -8705,19 +8865,19 @@ function filterFieldsByRole(fields, userRoles) {
8705
8865
  });
8706
8866
  }
8707
8867
  function useRoleFilteredModel(model) {
8708
- const userRoles = React5.useMemo(() => getCurrentUserRoles(), []);
8709
- return React5.useMemo(() => {
8868
+ const userRoles = React6.useMemo(() => getCurrentUserRoles(), []);
8869
+ return React6.useMemo(() => {
8710
8870
  const filtered = filterFieldsByRole(model.fields, userRoles);
8711
8871
  if (filtered.length === model.fields.length) return model;
8712
8872
  return { ...model, fields: filtered };
8713
8873
  }, [model, userRoles]);
8714
8874
  }
8715
8875
  var _19 = window._ || ((text) => text);
8716
- var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
8876
+ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded, beforeTabs }) => {
8717
8877
  const model = useRoleFilteredModel(modelProp);
8718
8878
  applyI18nLabelsToModel(model);
8719
8879
  applyI18nLabelsToModels(allModels);
8720
- const allModelsList = React5.useMemo(() => allModels || [], [allModels]);
8880
+ const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
8721
8881
  const modelTone = useModelTone(model);
8722
8882
  const modelDisplayLabel = asDisplayText(model.label, asDisplayText(model.name, "Record"));
8723
8883
  const { id: routeId } = reactRouterDom.useParams();
@@ -8725,9 +8885,9 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
8725
8885
  const { formProps, saveButtonProps, record, recordId } = useShowEditableForm(model.resource || model.name, id);
8726
8886
  const { formProps: showFormProps, effectiveFields } = buildShowTabFormOptions(formProps, model, allModels);
8727
8887
  const pageTitle = record?._label ? asDisplayText(record._label, `${_19("Show")} ${modelDisplayLabel}`) : `${_19("Show")} ${modelDisplayLabel}`;
8728
- const saveLayoutRef = React5.useRef(() => {
8888
+ const saveLayoutRef = React6.useRef(() => {
8729
8889
  });
8730
- const configureLayoutButtonRef = React5.useRef(null);
8890
+ const configureLayoutButtonRef = React6.useRef(null);
8731
8891
  const wrappedSaveButtonProps = saveButtonProps ? {
8732
8892
  ...saveButtonProps,
8733
8893
  onClick: (e) => {
@@ -8738,7 +8898,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
8738
8898
  const { data: canLayoutData } = core.useCan({ resource: "veloiq_layout", action: "configure_layout" });
8739
8899
  const canConfigureLayout = canLayoutData?.can !== false;
8740
8900
  const { actionsState, headerButtons } = useShowActionsPreferences(model, allModels, record, wrappedSaveButtonProps, configureLayoutButtonRef, saveLayoutRef);
8741
- const [activeTabKey, setActiveTabKey] = React5.useState("details");
8901
+ const [activeTabKey, setActiveTabKey] = React6.useState("details");
8742
8902
  const { tabs: items, layoutConfig } = useStandardShowTabs(
8743
8903
  model,
8744
8904
  record,
@@ -8759,12 +8919,12 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
8759
8919
  }
8760
8920
  )
8761
8921
  ] }) : null;
8762
- React5.useEffect(() => {
8922
+ React6.useEffect(() => {
8763
8923
  if (!items.find((item) => item.key === activeTabKey)) {
8764
8924
  setActiveTabKey(items[0]?.key || "details");
8765
8925
  }
8766
8926
  }, [activeTabKey, items]);
8767
- const lazyItems = React5.useMemo(
8927
+ const lazyItems = React6.useMemo(
8768
8928
  () => items.map((item) => ({
8769
8929
  ...item,
8770
8930
  children: item.key === activeTabKey ? item.children : null
@@ -8775,6 +8935,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
8775
8935
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "jm-tone-scope", style: toneScopeStyle(modelTone), children: [
8776
8936
  /* @__PURE__ */ jsxRuntime.jsx(ToneSharedStyles, {}),
8777
8937
  !record ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: /* @__PURE__ */ jsxRuntime.jsx(antd.Spin, {}) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8938
+ beforeTabs,
8778
8939
  /* @__PURE__ */ jsxRuntime.jsx(antd.Tabs, { activeKey: activeTabKey, onChange: setActiveTabKey, items: lazyItems, destroyInactiveTabPane: true }),
8779
8940
  /* @__PURE__ */ jsxRuntime.jsx(
8780
8941
  ShowFooterButtons,
@@ -8802,6 +8963,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
8802
8963
  })),
8803
8964
  headerButtons,
8804
8965
  children: [
8966
+ beforeTabs,
8805
8967
  /* @__PURE__ */ jsxRuntime.jsx(antd.Tabs, { activeKey: activeTabKey, onChange: setActiveTabKey, items: lazyItems, destroyInactiveTabPane: true }),
8806
8968
  /* @__PURE__ */ jsxRuntime.jsx(
8807
8969
  ShowFooterButtons,
@@ -8825,7 +8987,7 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
8825
8987
  const resolvedResource = resourceName && allModels ? resolveResourcePath(resourceName, allModels) : resourceName;
8826
8988
  const referencedModel = resourceName ? findModelByName(allModels, resourceName) : void 0;
8827
8989
  const resolvedOptionValue = field.optionValue || referencedModel?.pkField || "eid";
8828
- const [loadAll, setLoadAll] = React5__default.default.useState(false);
8990
+ const [loadAll, setLoadAll] = React6__default.default.useState(false);
8829
8991
  const pageSize = loadAll ? 999999 : RELATION_SELECT_DEFAULT_PAGE_SIZE;
8830
8992
  const { selectProps, queryResult } = antd$1.useSelect({
8831
8993
  resource: resolvedResource,
@@ -8842,8 +9004,8 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
8842
9004
  const loadedCount = filteredOptions?.length ?? 0;
8843
9005
  const isCapped = !loadAll && serverTotal > loadedCount && loadedCount > 0;
8844
9006
  const normalizeSearch = (val) => String(val ?? "").toLowerCase();
8845
- const selectedSet = React5__default.default.useMemo(() => new Set(Array.isArray(value) ? value : value !== void 0 && value !== null ? [value] : []), [value]);
8846
- const [searchValue, setSearchValue] = React5__default.default.useState("");
9007
+ const selectedSet = React6__default.default.useMemo(() => new Set(Array.isArray(value) ? value : value !== void 0 && value !== null ? [value] : []), [value]);
9008
+ const [searchValue, setSearchValue] = React6__default.default.useState("");
8847
9009
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8848
9010
  /* @__PURE__ */ jsxRuntime.jsx(
8849
9011
  antd.Select,
@@ -8890,8 +9052,8 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
8890
9052
  var _21 = window._ || ((text) => text);
8891
9053
  var FileUploadInput = ({ value: _value, onChange: _onChange }) => {
8892
9054
  const form = antd.Form.useFormInstance();
8893
- const [uploading, setUploading] = React5.useState(false);
8894
- const [fileName, setFileName] = React5.useState(null);
9055
+ const [uploading, setUploading] = React6.useState(false);
9056
+ const [fileName, setFileName] = React6.useState(null);
8895
9057
  const currentDataName = antd.Form.useWatch("data_name", form);
8896
9058
  const handleUpload = async (file) => {
8897
9059
  const recordId = form.getFieldValue("eid") ?? form.getFieldValue("id");
@@ -8957,9 +9119,9 @@ var AsyncSelectInput = ({
8957
9119
  onChange
8958
9120
  }) => {
8959
9121
  const apiUrl = core.useApiUrl();
8960
- const [options, setOptions] = React5.useState([]);
8961
- const [loading, setLoading] = React5.useState(false);
8962
- React5.useEffect(() => {
9122
+ const [options, setOptions] = React6.useState([]);
9123
+ const [loading, setLoading] = React6.useState(false);
9124
+ React6.useEffect(() => {
8963
9125
  let cancelled = false;
8964
9126
  setLoading(true);
8965
9127
  const fetchOptions = async () => {
@@ -9016,9 +9178,9 @@ var AsyncSelectInput = ({
9016
9178
  );
9017
9179
  };
9018
9180
  var _23 = window._ || ((text) => text);
9019
- var ReactMarkdown2 = React5.lazy(() => import('react-markdown').then((m) => ({ default: m.default })));
9181
+ var ReactMarkdown2 = React6.lazy(() => import('react-markdown').then((m) => ({ default: m.default })));
9020
9182
  var MarkdownEditor = ({ value = "", onChange }) => {
9021
- const [activeTab, setActiveTab] = React5.useState("edit");
9183
+ const [activeTab, setActiveTab] = React6.useState("edit");
9022
9184
  return /* @__PURE__ */ jsxRuntime.jsx(
9023
9185
  antd.Tabs,
9024
9186
  {
@@ -9043,14 +9205,14 @@ var MarkdownEditor = ({ value = "", onChange }) => {
9043
9205
  {
9044
9206
  key: "preview",
9045
9207
  label: _23("Preview"),
9046
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: 60, padding: "4px 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 200 } }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown2, { children: value }) }) })
9208
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: 60, padding: "4px 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 200 } }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown2, { children: value }) }) })
9047
9209
  }
9048
9210
  ]
9049
9211
  }
9050
9212
  );
9051
9213
  };
9052
9214
  var JsonEditor = ({ value = "", onChange }) => {
9053
- const [error, setError] = React5.useState(null);
9215
+ const [error, setError] = React6.useState(null);
9054
9216
  const handleChange = (e) => {
9055
9217
  const raw = e.target.value;
9056
9218
  onChange?.(raw);
@@ -9217,7 +9379,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9217
9379
  const { token } = antd.theme.useToken();
9218
9380
  const modelTone = useModelTone(model);
9219
9381
  const { settings: viewSettings, loading: viewSettingsLoading } = useViewSettings();
9220
- const allModelsList = React5.useMemo(() => allModels || [], [allModels]);
9382
+ const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
9221
9383
  const { rows: editConfigRows, loading: editConfigLoading } = useViewConfigurations(model.name, "AutomaticEntityForm");
9222
9384
  const { rows: fallbackConfigRows, loading: fallbackConfigLoading } = useViewConfigurations(model.name, "PrimaryView");
9223
9385
  const valueBackground = isDarkColor2(token.colorBgBase || token.colorBgContainer) ? token.colorFillQuaternary : "#F9FFFF";
@@ -9231,12 +9393,12 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9231
9393
  const relateOtherKey = searchParams.get("relate_other_key");
9232
9394
  const relateTargetId = searchParams.get("relate_target_id");
9233
9395
  const canAutoRelate = Boolean(relateResource && relateTargetKey && relateOtherKey && relateTargetId);
9234
- const [createdRecord, setCreatedRecord] = React5.useState(null);
9235
- const [showRelationActions, setShowRelationActions] = React5.useState(DEFAULT_EDIT_RELATION_ROW_ACTIONS);
9236
- const [showRelationCreate, setShowRelationCreate] = React5.useState(DEFAULT_RELATION_CREATE_ACTIONS);
9237
- const [activeTabKey, setActiveTabKey] = React5.useState("main_data");
9396
+ const [createdRecord, setCreatedRecord] = React6.useState(null);
9397
+ const [showRelationActions, setShowRelationActions] = React6.useState(DEFAULT_EDIT_RELATION_ROW_ACTIONS);
9398
+ const [showRelationCreate, setShowRelationCreate] = React6.useState(DEFAULT_RELATION_CREATE_ACTIONS);
9399
+ const [activeTabKey, setActiveTabKey] = React6.useState("main_data");
9238
9400
  const isPostCreate = createdRecord !== null;
9239
- const relationViewTypeDefaults = React5.useMemo(
9401
+ const relationViewTypeDefaults = React6.useMemo(
9240
9402
  () => ({
9241
9403
  show: normalizeRelationViewType(viewSettings?.showViewType || "") || "totals-details",
9242
9404
  edit: normalizeRelationViewType(viewSettings?.editViewType || "") || "editable-table"
@@ -9244,11 +9406,11 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9244
9406
  [viewSettings?.showViewType, viewSettings?.editViewType]
9245
9407
  );
9246
9408
  const modelDisplayLabel = asDisplayText(model.label, asDisplayText(model.name, "Record"));
9247
- const isLinkModel = React5.useMemo(() => {
9409
+ const isLinkModel = React6.useMemo(() => {
9248
9410
  const fieldKeys = model.fields.map((f) => f.key);
9249
9411
  return fieldKeys.includes("eid_from") && fieldKeys.includes("eid_to") && searchParams.has("eid_from");
9250
9412
  }, [model.fields, searchParams]);
9251
- const [serverDefaults, setServerDefaults] = React5.useState({});
9413
+ const [serverDefaults, setServerDefaults] = React6.useState({});
9252
9414
  const { formProps, saveButtonProps } = antd$1.useForm({
9253
9415
  resource: formResource,
9254
9416
  redirect: false,
@@ -9297,14 +9459,14 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9297
9459
  type: "success"
9298
9460
  })
9299
9461
  });
9300
- useKeyboardShortcuts(React5.useMemo(() => [
9462
+ useKeyboardShortcuts(React6.useMemo(() => [
9301
9463
  { key: "s", ctrl: true, handler: () => {
9302
9464
  if (!isPostCreate) formProps?.form?.submit();
9303
9465
  } },
9304
9466
  { key: "Escape", handler: () => journeyCallbacks?.onCancel ? journeyCallbacks.onCancel() : navigate(-1) }
9305
9467
  ], [formProps?.form, navigate, isPostCreate, journeyCallbacks]));
9306
- const effectiveFields = React5.useMemo(() => applyRelationFieldOverrides(model, allModelsList), [model, allModelsList]);
9307
- const fieldByKey = React5.useMemo(
9468
+ const effectiveFields = React6.useMemo(() => applyRelationFieldOverrides(model, allModelsList), [model, allModelsList]);
9469
+ const fieldByKey = React6.useMemo(
9308
9470
  () => new Map(effectiveFields.map((field) => [field.key, field])),
9309
9471
  [effectiveFields]
9310
9472
  );
@@ -9316,7 +9478,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9316
9478
  if (["false", "0", "no", "n", "off"].includes(normalized)) return false;
9317
9479
  return value;
9318
9480
  };
9319
- const normalizeFieldValue = React5.useCallback((field, rawValue) => {
9481
+ const normalizeFieldValue = React6.useCallback((field, rawValue) => {
9320
9482
  if (rawValue === void 0 || rawValue === null || rawValue === "") return rawValue;
9321
9483
  if (field.type === "number") {
9322
9484
  const parsed = Number(rawValue);
@@ -9325,7 +9487,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9325
9487
  if (field.type === "boolean") return parseBooleanValue(rawValue);
9326
9488
  return rawValue;
9327
9489
  }, []);
9328
- React5.useEffect(() => {
9490
+ React6.useEffect(() => {
9329
9491
  let cancelled = false;
9330
9492
  const loadDefaults = async () => {
9331
9493
  try {
@@ -9348,7 +9510,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9348
9510
  cancelled = true;
9349
9511
  };
9350
9512
  }, [apiUrl, effectiveFields, formResource, normalizeFieldValue]);
9351
- const { initialValues, hiddenFields } = React5.useMemo(() => {
9513
+ const { initialValues, hiddenFields } = React6.useMemo(() => {
9352
9514
  const defaults = {};
9353
9515
  const fromQuery = {};
9354
9516
  const hidden = [];
@@ -9389,13 +9551,13 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9389
9551
  const configLoading = editConfigLoading || fallbackConfigLoading || viewSettingsLoading;
9390
9552
  const hasConfig = configRows.length > 0;
9391
9553
  const configSections = groupConfigRowsBySection(configRows);
9392
- const { embedded, tabbed } = React5.useMemo(() => splitRelations(model.relations), [model.relations]);
9393
- const allRelations = React5.useMemo(() => [...embedded, ...tabbed], [embedded, tabbed]);
9394
- const configuredRelationKeys = React5.useMemo(() => buildConfiguredRelationKeys(configRows), [configRows]);
9395
- const configuredResolvedRelationKeys = React5.useMemo(() => buildConfiguredResolvedRelationKeys(model.relations, configRows), [model.relations, configRows]);
9396
- const configuredRelationDisplayKeys = React5.useMemo(() => buildConfiguredRelationDisplayKeys(model.relations, configRows), [model.relations, configRows]);
9554
+ const { embedded, tabbed } = React6.useMemo(() => splitRelations(model.relations), [model.relations]);
9555
+ const allRelations = React6.useMemo(() => [...embedded, ...tabbed], [embedded, tabbed]);
9556
+ const configuredRelationKeys = React6.useMemo(() => buildConfiguredRelationKeys(configRows), [configRows]);
9557
+ const configuredResolvedRelationKeys = React6.useMemo(() => buildConfiguredResolvedRelationKeys(model.relations, configRows), [model.relations, configRows]);
9558
+ const configuredRelationDisplayKeys = React6.useMemo(() => buildConfiguredRelationDisplayKeys(model.relations, configRows), [model.relations, configRows]);
9397
9559
  const hasConfiguredDetailRelations = configuredResolvedRelationKeys.size > 0 || configuredRelationKeys.size > 0;
9398
- React5.useEffect(() => {
9560
+ React6.useEffect(() => {
9399
9561
  const formInstance = formProps?.form;
9400
9562
  if (!formInstance) return;
9401
9563
  const untouchedDefaults = Object.fromEntries(
@@ -9404,7 +9566,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9404
9566
  if (Object.keys(untouchedDefaults).length === 0) return;
9405
9567
  formInstance.setFieldsValue(untouchedDefaults);
9406
9568
  }, [formProps, initialValues]);
9407
- const handleDone = React5.useCallback(() => {
9569
+ const handleDone = React6.useCallback(() => {
9408
9570
  const createdId = getRecordId(createdRecord, model.fields);
9409
9571
  if (returnTo) {
9410
9572
  navigate(returnTo);
@@ -9414,7 +9576,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9414
9576
  navigate(-1);
9415
9577
  }
9416
9578
  }, [createdRecord, returnTo, navigate, formResource]);
9417
- const handleGoToEdit = React5.useCallback(() => {
9579
+ const handleGoToEdit = React6.useCallback(() => {
9418
9580
  const createdId = getRecordId(createdRecord, model.fields);
9419
9581
  if (createdId != null) {
9420
9582
  go({ to: { resource: model.resource || model.name, action: "edit", id: createdId } });
@@ -9426,7 +9588,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
9426
9588
  /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { size: "small", type: "primary", icon: /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.CheckCircleOutlined, {}), onClick: handleDone, children: _24("Done") })
9427
9589
  ] });
9428
9590
  const addTabsForNonConfiguredRelations = viewSettings?.addTabsForNonConfiguredRelations !== false;
9429
- const relationTabEntries = React5.useMemo(() => {
9591
+ const relationTabEntries = React6.useMemo(() => {
9430
9592
  if (!allModels) return [];
9431
9593
  const groups = /* @__PURE__ */ new Map();
9432
9594
  allRelations.forEach((rel) => {
@@ -9767,7 +9929,7 @@ var nextGridPosition = (cells) => {
9767
9929
  };
9768
9930
  var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
9769
9931
  const [form] = antd.Form.useForm();
9770
- React5.useEffect(() => {
9932
+ React6.useEffect(() => {
9771
9933
  if (!cell || !tabId) return;
9772
9934
  const tab = config.tabs.find((t) => t.id === tabId);
9773
9935
  form.setFieldsValue({
@@ -9779,7 +9941,9 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
9779
9941
  min_width: cell.min_width ?? "",
9780
9942
  max_width: cell.max_width ?? "",
9781
9943
  min_height: cell.min_height ?? "",
9782
- max_height: cell.max_height ?? ""
9944
+ max_height: cell.max_height ?? "",
9945
+ chart_url: cell.chart_url ?? "",
9946
+ chart_title: cell.chart_title ?? ""
9783
9947
  });
9784
9948
  }, [cell, tabId, config, form]);
9785
9949
  const handleSave = () => {
@@ -9795,7 +9959,9 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
9795
9959
  min_width: values.min_width || null,
9796
9960
  max_width: values.max_width || null,
9797
9961
  min_height: values.min_height || null,
9798
- max_height: values.max_height || null
9962
+ max_height: values.max_height || null,
9963
+ chart_url: values.chart_url || void 0,
9964
+ chart_title: values.chart_title || void 0
9799
9965
  };
9800
9966
  const currentTab = config.tabs.find((t) => t.id === tabId);
9801
9967
  const nameUnchanged = currentTab?.name.trim().toLowerCase() === newTabName.toLowerCase();
@@ -9842,7 +10008,7 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
9842
10008
  return /* @__PURE__ */ jsxRuntime.jsx(
9843
10009
  antd.Drawer,
9844
10010
  {
9845
- title: cell?.source_type !== "model" ? `Configure section: ${cell?.section_name ?? cell?.model ?? ""}` : `Configure cell: ${cell?.model ?? ""}`,
10011
+ title: cell?.source_type === "plotly_chart" ? `Configure chart: ${cell?.chart_title ?? cell?.model ?? ""}` : cell?.source_type !== "model" ? `Configure section: ${cell?.section_name ?? cell?.model ?? ""}` : `Configure cell: ${cell?.model ?? ""}`,
9846
10012
  placement: "right",
9847
10013
  width: 380,
9848
10014
  open,
@@ -9870,6 +10036,11 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
9870
10036
  /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { orientation: "left", children: "View" }),
9871
10037
  /* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "view_type", label: "View type", children: /* @__PURE__ */ jsxRuntime.jsx(antd.Select, { options: VIEW_TYPE_OPTIONS }) })
9872
10038
  ] }),
10039
+ cell?.source_type === "plotly_chart" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10040
+ /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { orientation: "left", children: "Chart" }),
10041
+ /* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "chart_title", label: "Chart title", children: /* @__PURE__ */ jsxRuntime.jsx(antd.Input, { placeholder: "e.g. Confidence by Month" }) }),
10042
+ /* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "chart_url", label: "Chart URL", children: /* @__PURE__ */ jsxRuntime.jsx(antd.Input, { placeholder: "/api/nl-answers-confidence-by-month-chart" }) })
10043
+ ] }),
9873
10044
  /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { orientation: "left", children: "Size" }),
9874
10045
  /* @__PURE__ */ jsxRuntime.jsxs(antd.Space, { wrap: true, children: [
9875
10046
  /* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "min_width", label: "Min width", style: { marginBottom: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(antd.Input, { placeholder: "e.g. 320px", style: { width: 130 } }) }),
@@ -9904,7 +10075,7 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
9904
10075
  };
9905
10076
  var SectionCell = ({ cell, isConfiguring, isMaximized, isMinimized, onConfigure, onMaximize, onMinimize, onMove, onResize, children }) => {
9906
10077
  const { token } = antd.theme.useToken();
9907
- const cellRef = React5.useRef(null);
10078
+ const cellRef = React6.useRef(null);
9908
10079
  const cellStyle = {
9909
10080
  position: "relative",
9910
10081
  border: `1px solid ${token.colorBorderSecondary}`,
@@ -9933,7 +10104,7 @@ var SectionCell = ({ cell, isConfiguring, isMaximized, isMinimized, onConfigure,
9933
10104
  minHeight: 32,
9934
10105
  position: "relative"
9935
10106
  };
9936
- const startResize = React5.useCallback((e, dir) => {
10107
+ const startResize = React6.useCallback((e, dir) => {
9937
10108
  e.preventDefault();
9938
10109
  e.stopPropagation();
9939
10110
  const el = cellRef.current;
@@ -10013,20 +10184,20 @@ var SectionCell = ({ cell, isConfiguring, isMaximized, isMinimized, onConfigure,
10013
10184
  ] });
10014
10185
  };
10015
10186
  var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isConfiguring = false }) => {
10016
- const [maximizedCellId, setMaximizedCellId] = React5.useState(null);
10017
- const [minimizedCellIds, setMinimizedCellIds] = React5.useState(/* @__PURE__ */ new Set());
10018
- const [drawerCellId, setDrawerCellId] = React5.useState(null);
10019
- const handleMaximize = React5.useCallback((cellId) => {
10187
+ const [maximizedCellId, setMaximizedCellId] = React6.useState(null);
10188
+ const [minimizedCellIds, setMinimizedCellIds] = React6.useState(/* @__PURE__ */ new Set());
10189
+ const [drawerCellId, setDrawerCellId] = React6.useState(null);
10190
+ const handleMaximize = React6.useCallback((cellId) => {
10020
10191
  setMaximizedCellId((prev) => prev === cellId ? null : cellId);
10021
10192
  }, []);
10022
- const handleMinimize = React5.useCallback((cellId) => {
10193
+ const handleMinimize = React6.useCallback((cellId) => {
10023
10194
  setMinimizedCellIds((prev) => {
10024
10195
  const next = new Set(prev);
10025
10196
  next.has(cellId) ? next.delete(cellId) : next.add(cellId);
10026
10197
  return next;
10027
10198
  });
10028
10199
  }, []);
10029
- const handleMove = React5.useCallback((cellId, direction) => {
10200
+ const handleMove = React6.useCallback((cellId, direction) => {
10030
10201
  const nextTabs = config.tabs.map((tab) => {
10031
10202
  if (tab.id !== tabId) return tab;
10032
10203
  const cell = tab.cells.find((c) => c.id === cellId);
@@ -10049,7 +10220,7 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
10049
10220
  });
10050
10221
  onConfigChange({ ...config, tabs: nextTabs });
10051
10222
  }, [config, tabId, onConfigChange]);
10052
- const handleResize = React5.useCallback((cellId, minWidth, minHeight) => {
10223
+ const handleResize = React6.useCallback((cellId, minWidth, minHeight) => {
10053
10224
  const nextTabs = config.tabs.map((tab) => {
10054
10225
  if (tab.id !== tabId) return tab;
10055
10226
  return {
@@ -10066,14 +10237,21 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
10066
10237
  });
10067
10238
  onConfigChange({ ...config, tabs: nextTabs });
10068
10239
  }, [config, tabId, onConfigChange]);
10069
- const numCols = React5.useMemo(() => {
10240
+ const numCols = React6.useMemo(() => {
10070
10241
  if (!cells.length) return 1;
10071
10242
  return Math.max(...cells.map((c) => c.col)) + 1;
10072
10243
  }, [cells]);
10073
- const numRows = React5.useMemo(() => {
10244
+ const numRows = React6.useMemo(() => {
10074
10245
  if (!cells.length) return 1;
10075
10246
  return Math.max(...cells.map((c) => c.row)) + 1;
10076
10247
  }, [cells]);
10248
+ const soloRows = React6.useMemo(() => {
10249
+ const counts = /* @__PURE__ */ new Map();
10250
+ for (const c of cells) counts.set(c.row, (counts.get(c.row) ?? 0) + 1);
10251
+ const solo = /* @__PURE__ */ new Set();
10252
+ for (const [row, count] of counts) if (count === 1) solo.add(row);
10253
+ return solo;
10254
+ }, [cells]);
10077
10255
  const visibleCells = maximizedCellId ? cells.filter((c) => c.id === maximizedCellId) : cells;
10078
10256
  const gridStyle = {
10079
10257
  display: "grid",
@@ -10092,7 +10270,7 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
10092
10270
  "div",
10093
10271
  {
10094
10272
  style: {
10095
- gridColumn: maximizedCellId ? "1 / -1" : `${cell.col + 1}`,
10273
+ gridColumn: maximizedCellId || soloRows.has(cell.row) ? "1 / -1" : `${cell.col + 1}`,
10096
10274
  gridRow: maximizedCellId ? "1 / -1" : `${cell.row + 1}`
10097
10275
  },
10098
10276
  children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -10144,8 +10322,8 @@ function parseInlineStyle2(cssText) {
10144
10322
  }
10145
10323
  var _25 = window._ || ((text) => text);
10146
10324
  var ReadAndEditReference = ({ value, onChange, field, allModels, model, currentId }) => {
10147
- const [editing, setEditing] = React5.useState(false);
10148
- const [draft, setDraft] = React5.useState(void 0);
10325
+ const [editing, setEditing] = React6.useState(false);
10326
+ const [draft, setDraft] = React6.useState(void 0);
10149
10327
  const form = antd.Form.useFormInstance();
10150
10328
  const resource = field.referencePath ? field.referencePath : field.reference ? resolveResourcePath(field.reference, allModels) : "";
10151
10329
  const modelResource = model ? resolveResourcePath(model.resource || model.name, allModels) : void 0;
@@ -10194,11 +10372,11 @@ var ReadAndEditReference = ({ value, onChange, field, allModels, model, currentI
10194
10372
  var NLSentenceBlock = ({ eid, title: titleProp, showLabel }) => {
10195
10373
  const { token } = antd.theme.useToken();
10196
10374
  const apiUrl = core.useApiUrl();
10197
- const [html, setHtml] = React5.useState(null);
10198
- const [loading, setLoading] = React5.useState(true);
10199
- const [error, setError] = React5.useState(null);
10200
- const [fetchedTitle, setFetchedTitle] = React5.useState(null);
10201
- React5.useEffect(() => {
10375
+ const [html, setHtml] = React6.useState(null);
10376
+ const [loading, setLoading] = React6.useState(true);
10377
+ const [error, setError] = React6.useState(null);
10378
+ const [fetchedTitle, setFetchedTitle] = React6.useState(null);
10379
+ React6.useEffect(() => {
10202
10380
  let cancelled = false;
10203
10381
  setLoading(true);
10204
10382
  setHtml(null);
@@ -10379,7 +10557,6 @@ var SectionCellContent = ({
10379
10557
  borderRadius: 6,
10380
10558
  overflowWrap: "anywhere",
10381
10559
  maxWidth: "100%",
10382
- border: `1px solid ${token.colorBorder}`,
10383
10560
  ...parseInlineStyle(item.html_format)
10384
10561
  };
10385
10562
  const relationLabelStyle = {
@@ -10414,7 +10591,6 @@ var SectionCellContent = ({
10414
10591
  lineHeight: 1.15,
10415
10592
  background: valueBackground,
10416
10593
  borderRadius: 6,
10417
- border: `1px solid ${token.colorBorder}`,
10418
10594
  maxWidth: "100%",
10419
10595
  overflowWrap: "anywhere",
10420
10596
  textAlign: field.type === "number" && !field.reference ? "right" : "left",
@@ -10515,10 +10691,10 @@ function buildConfig(configRows, overrides) {
10515
10691
  function usePageSectionsConfig(configRows, resourceKey, mode) {
10516
10692
  const apiUrl = core.useApiUrl();
10517
10693
  const preferenceType = mode === "show" ? "ShowLayoutGrid" : "EditLayoutGrid";
10518
- const [overrides, setOverrides] = React5.useState({});
10519
- const [loading, setLoading] = React5.useState(true);
10520
- const loadedKeyRef = React5.useRef(null);
10521
- React5.useEffect(() => {
10694
+ const [overrides, setOverrides] = React6.useState({});
10695
+ const [loading, setLoading] = React6.useState(true);
10696
+ const loadedKeyRef = React6.useRef(null);
10697
+ React6.useEffect(() => {
10522
10698
  if (!resourceKey) {
10523
10699
  setLoading(false);
10524
10700
  return;
@@ -10537,17 +10713,17 @@ function usePageSectionsConfig(configRows, resourceKey, mode) {
10537
10713
  }).catch(() => {
10538
10714
  }).finally(() => setLoading(false));
10539
10715
  }, [apiUrl, resourceKey, preferenceType]);
10540
- const savedConfig = React5.useMemo(
10716
+ const savedConfig = React6.useMemo(
10541
10717
  () => buildConfig(configRows, overrides),
10542
10718
  [configRows, overrides]
10543
10719
  );
10544
- const [isConfiguring, setIsConfiguring] = React5.useState(false);
10545
- const [pendingConfig, setPendingConfig] = React5.useState(null);
10546
- const config = React5.useMemo(
10720
+ const [isConfiguring, setIsConfiguring] = React6.useState(false);
10721
+ const [pendingConfig, setPendingConfig] = React6.useState(null);
10722
+ const config = React6.useMemo(
10547
10723
  () => isConfiguring && pendingConfig ? pendingConfig : savedConfig,
10548
10724
  [isConfiguring, pendingConfig, savedConfig]
10549
10725
  );
10550
- const save = React5.useCallback((nextConfig) => {
10726
+ const save = React6.useCallback((nextConfig) => {
10551
10727
  const allCells = nextConfig.tabs.flatMap((t) => t.cells);
10552
10728
  const nextOverrides = {};
10553
10729
  const cells = allCells.map((c) => {
@@ -10572,24 +10748,24 @@ function usePageSectionsConfig(configRows, resourceKey, mode) {
10572
10748
  }).catch(() => {
10573
10749
  });
10574
10750
  }, [apiUrl, resourceKey, preferenceType]);
10575
- const getSectionRows = React5.useCallback((sectionId) => {
10751
+ const getSectionRows = React6.useCallback((sectionId) => {
10576
10752
  return configRows.filter((r) => (r.section_id || r.section || DETAILS_TAB_NAME) === sectionId);
10577
10753
  }, [configRows]);
10578
- const enterConfigMode = React5.useCallback(() => {
10754
+ const enterConfigMode = React6.useCallback(() => {
10579
10755
  setPendingConfig(savedConfig);
10580
10756
  setIsConfiguring(true);
10581
10757
  }, [savedConfig]);
10582
- const cancelLayout = React5.useCallback(() => {
10758
+ const cancelLayout = React6.useCallback(() => {
10583
10759
  setPendingConfig(null);
10584
10760
  setIsConfiguring(false);
10585
10761
  }, []);
10586
- const saveLayout = React5.useCallback(() => {
10762
+ const saveLayout = React6.useCallback(() => {
10587
10763
  const toSave = pendingConfig ?? savedConfig;
10588
10764
  save(toSave);
10589
10765
  setPendingConfig(null);
10590
10766
  setIsConfiguring(false);
10591
10767
  }, [pendingConfig, savedConfig, save]);
10592
- const onLayoutChange = React5.useCallback((next) => {
10768
+ const onLayoutChange = React6.useCallback((next) => {
10593
10769
  if (isConfiguring) setPendingConfig(next);
10594
10770
  }, [isConfiguring]);
10595
10771
  return { config, loading, save, getSectionRows, isConfiguring, enterConfigMode, saveLayout, cancelLayout, onLayoutChange };
@@ -10608,7 +10784,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
10608
10784
  const { token } = antd.theme.useToken();
10609
10785
  const modelTone = useModelTone(model);
10610
10786
  const { settings: viewSettings, loading: viewSettingsLoading } = useViewSettings();
10611
- const relationViewTypeDefaults = React5.useMemo(
10787
+ const relationViewTypeDefaults = React6.useMemo(
10612
10788
  () => ({
10613
10789
  show: normalizeRelationViewType(viewSettings?.showViewType || "") || "totals-details",
10614
10790
  edit: normalizeRelationViewType(viewSettings?.editViewType || "") || "editable-table"
@@ -10616,7 +10792,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
10616
10792
  [viewSettings?.showViewType, viewSettings?.editViewType]
10617
10793
  );
10618
10794
  const apiUrl = core.useApiUrl();
10619
- const allModelsList = React5.useMemo(() => allModels || [], [allModels]);
10795
+ const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
10620
10796
  const { rows: editConfigRows, loading: editConfigLoading } = useViewConfigurations(model.name, "AutomaticEntityForm");
10621
10797
  const { rows: fallbackConfigRows, loading: fallbackConfigLoading } = useViewConfigurations(model.name, "PrimaryView");
10622
10798
  const valueBackground = isDarkColor2(token.colorBgBase || token.colorBgContainer) ? token.colorFillQuaternary : "#F9FFFF";
@@ -10647,7 +10823,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
10647
10823
  })
10648
10824
  });
10649
10825
  const record = queryResult?.data?.data;
10650
- const editFormProps = React5.useMemo(() => {
10826
+ const editFormProps = React6.useMemo(() => {
10651
10827
  if (!isFileModel(model)) return formProps;
10652
10828
  const originalOnFinish = formProps.onFinish;
10653
10829
  return {
@@ -10658,24 +10834,24 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
10658
10834
  }
10659
10835
  };
10660
10836
  }, [formProps, model]);
10661
- useKeyboardShortcuts(React5.useMemo(() => [
10837
+ useKeyboardShortcuts(React6.useMemo(() => [
10662
10838
  { key: "s", ctrl: true, handler: () => formProps?.form?.submit() },
10663
10839
  { key: "Escape", handler: () => journeyCallbacks?.onCancel ? journeyCallbacks.onCancel() : navigate(-1) }
10664
10840
  ], [formProps?.form, navigate, journeyCallbacks]));
10665
10841
  const pageTitle = record?._label ? asDisplayText(record._label, `${_27("Edit")} ${modelDisplayLabel}`) : `${_27("Edit")} ${modelDisplayLabel}`;
10666
10842
  const recordId = getRecordId(record, model.fields);
10667
- const effectiveFields = React5.useMemo(() => applyRelationFieldOverrides(model, allModelsList), [model, allModelsList]);
10843
+ const effectiveFields = React6.useMemo(() => applyRelationFieldOverrides(model, allModelsList), [model, allModelsList]);
10668
10844
  const { metadataButton: editMetadataButton, metadataModal: editMetadataModal } = useMetadataModal(model, allModels);
10669
- const [showRelationActions, setShowRelationActions] = React5.useState(DEFAULT_EDIT_RELATION_ROW_ACTIONS);
10670
- const [showRelationCreate, setShowRelationCreate] = React5.useState(DEFAULT_RELATION_CREATE_ACTIONS);
10671
- const [isSavingActionsPrefs, setIsSavingActionsPrefs] = React5.useState(false);
10672
- const actionsPrefsTouchedRef = React5.useRef(false);
10673
- const actionsPrefsLoadedRef = React5.useRef(false);
10674
- const actionsPrefsResourceRef = React5.useRef(null);
10675
- const markActionsPrefsTouched = React5.useCallback(() => {
10845
+ const [showRelationActions, setShowRelationActions] = React6.useState(DEFAULT_EDIT_RELATION_ROW_ACTIONS);
10846
+ const [showRelationCreate, setShowRelationCreate] = React6.useState(DEFAULT_RELATION_CREATE_ACTIONS);
10847
+ const [isSavingActionsPrefs, setIsSavingActionsPrefs] = React6.useState(false);
10848
+ const actionsPrefsTouchedRef = React6.useRef(false);
10849
+ const actionsPrefsLoadedRef = React6.useRef(false);
10850
+ const actionsPrefsResourceRef = React6.useRef(null);
10851
+ const markActionsPrefsTouched = React6.useCallback(() => {
10676
10852
  actionsPrefsTouchedRef.current = true;
10677
10853
  }, []);
10678
- const saveActionsPreferences = React5.useCallback(async () => {
10854
+ const saveActionsPreferences = React6.useCallback(async () => {
10679
10855
  const resourceKey2 = resolveResourcePath(model.resource || model.name, allModelsList);
10680
10856
  const preferences = {
10681
10857
  showActions: showRelationActions,
@@ -10699,8 +10875,8 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
10699
10875
  setIsSavingActionsPrefs(false);
10700
10876
  }
10701
10877
  }, [apiUrl, allModelsList, model.name, model.resource, showRelationActions, showRelationCreate]);
10702
- const [isDuplicating, setIsDuplicating] = React5.useState(false);
10703
- const duplicateRecord = React5.useCallback(async (withRelations) => {
10878
+ const [isDuplicating, setIsDuplicating] = React6.useState(false);
10879
+ const duplicateRecord = React6.useCallback(async (withRelations) => {
10704
10880
  if (!record) return;
10705
10881
  setIsDuplicating(true);
10706
10882
  try {
@@ -10768,7 +10944,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
10768
10944
  setIsDuplicating(false);
10769
10945
  }
10770
10946
  }, [record, model, allModelsList, apiUrl, go]);
10771
- React5.useEffect(() => {
10947
+ React6.useEffect(() => {
10772
10948
  const resourceKey2 = resolveResourcePath(model.resource || model.name, allModelsList);
10773
10949
  if (actionsPrefsResourceRef.current !== resourceKey2) {
10774
10950
  actionsPrefsLoadedRef.current = false;
@@ -11048,13 +11224,13 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
11048
11224
  });
11049
11225
  items.push(...customConfigTabs);
11050
11226
  items.push(...relationTabs);
11051
- const [activeTabKey, setActiveTabKey] = React5.useState("main_data");
11052
- React5.useEffect(() => {
11227
+ const [activeTabKey, setActiveTabKey] = React6.useState("main_data");
11228
+ React6.useEffect(() => {
11053
11229
  if (!items.find((item) => item.key === activeTabKey)) {
11054
11230
  setActiveTabKey(items[0]?.key || "main_data");
11055
11231
  }
11056
11232
  }, [activeTabKey, items]);
11057
- const lazyItems = React5.useMemo(
11233
+ const lazyItems = React6.useMemo(
11058
11234
  () => items.map((item) => ({
11059
11235
  ...item,
11060
11236
  children: item.key === activeTabKey ? item.children : null
@@ -11151,7 +11327,7 @@ var useStandardShowTabs = (model, record, allModels, actionsState, editForm, ove
11151
11327
  const { token } = antd.theme.useToken();
11152
11328
  const { settings: viewSettings, loading: viewSettingsLoading } = useViewSettings();
11153
11329
  const modelTone = useModelTone(model);
11154
- const relationViewTypeDefaults = React5.useMemo(
11330
+ const relationViewTypeDefaults = React6.useMemo(
11155
11331
  () => ({
11156
11332
  show: normalizeRelationViewType(viewSettings?.showViewType || "") || "totals-details",
11157
11333
  edit: normalizeRelationViewType(viewSettings?.editViewType || "") || "editable-table"
@@ -11460,11 +11636,11 @@ var useRelatedInlineItems = ({
11460
11636
  pageSize = INLINE_DEFAULT_PAGE_SIZE
11461
11637
  }) => {
11462
11638
  const apiUrl = core.useApiUrl();
11463
- const [items, setItems] = React5.useState([]);
11464
- const [loading, setLoading] = React5.useState(false);
11465
- const [error, setError] = React5.useState(null);
11466
- const [total, setTotal] = React5.useState(0);
11467
- React5.useEffect(() => {
11639
+ const [items, setItems] = React6.useState([]);
11640
+ const [loading, setLoading] = React6.useState(false);
11641
+ const [error, setError] = React6.useState(null);
11642
+ const [total, setTotal] = React6.useState(0);
11643
+ React6.useEffect(() => {
11468
11644
  const recordId = record?.eid ?? record?.id;
11469
11645
  if (!recordId || !rel.resource || !rel.targetKey) {
11470
11646
  setItems([]);
@@ -11605,10 +11781,10 @@ var useRelatedGalleryRecords = ({
11605
11781
  allModels
11606
11782
  }) => {
11607
11783
  const apiUrl = core.useApiUrl();
11608
- const [records, setRecords] = React5.useState([]);
11609
- const [loading, setLoading] = React5.useState(false);
11610
- const [error, setError] = React5.useState(null);
11611
- React5.useEffect(() => {
11784
+ const [records, setRecords] = React6.useState([]);
11785
+ const [loading, setLoading] = React6.useState(false);
11786
+ const [error, setError] = React6.useState(null);
11787
+ React6.useEffect(() => {
11612
11788
  const recordId = record?.eid ?? record?.id;
11613
11789
  if (!recordId || !rel.resource || !rel.targetKey) {
11614
11790
  setRecords([]);
@@ -11706,10 +11882,10 @@ var RelatedObjectsInlineValues = ({ rel, record, viewType, allowedRelatedIds, al
11706
11882
  const go = core.useGo();
11707
11883
  const paneNav = usePaneNavigation();
11708
11884
  const { token } = antd.theme.useToken();
11709
- const [page, setPage] = React5.useState(1);
11710
- const [pageSize, setPageSize] = React5.useState(INLINE_DEFAULT_PAGE_SIZE);
11885
+ const [page, setPage] = React6.useState(1);
11886
+ const [pageSize, setPageSize] = React6.useState(INLINE_DEFAULT_PAGE_SIZE);
11711
11887
  const { items, loading, error, total } = useRelatedInlineItems({ rel, record, allowedRelatedIds, allModels, page, pageSize });
11712
- const handlePageChange = React5.useCallback((newPage, newPageSize) => {
11888
+ const handlePageChange = React6.useCallback((newPage, newPageSize) => {
11713
11889
  if (newPageSize && newPageSize !== pageSize) {
11714
11890
  setPageSize(newPageSize);
11715
11891
  setPage(1);
@@ -11771,17 +11947,17 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
11771
11947
  const { token } = antd.theme.useToken();
11772
11948
  const { records, loading, error } = useRelatedGalleryRecords({ rel, record, allModels });
11773
11949
  const resource = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
11774
- const dateFieldOptions = React5.useMemo(() => getCalendarDateFieldOptions(relatedModel.fields), [relatedModel.fields]);
11775
- const [calendarMode, setCalendarMode] = React5.useState("month");
11776
- const [calendarDateField, setCalendarDateField] = React5.useState(() => dateFieldOptions[0]?.key || "");
11777
- const [calendarAnchorDate, setCalendarAnchorDate] = React5.useState(() => dayjs9__default.default().startOf("month"));
11778
- const dateFieldKeySet = React5.useMemo(() => new Set(dateFieldOptions.map((field) => field.key)), [dateFieldOptions]);
11779
- React5.useEffect(() => {
11950
+ const dateFieldOptions = React6.useMemo(() => getCalendarDateFieldOptions(relatedModel.fields), [relatedModel.fields]);
11951
+ const [calendarMode, setCalendarMode] = React6.useState("month");
11952
+ const [calendarDateField, setCalendarDateField] = React6.useState(() => dateFieldOptions[0]?.key || "");
11953
+ const [calendarAnchorDate, setCalendarAnchorDate] = React6.useState(() => dayjs9__default.default().startOf("month"));
11954
+ const dateFieldKeySet = React6.useMemo(() => new Set(dateFieldOptions.map((field) => field.key)), [dateFieldOptions]);
11955
+ React6.useEffect(() => {
11780
11956
  if (calendarDateField && dateFieldKeySet.has(calendarDateField)) return;
11781
11957
  const fallback = dateFieldOptions[0]?.key || "";
11782
11958
  if (fallback !== calendarDateField) setCalendarDateField(fallback);
11783
11959
  }, [calendarDateField, dateFieldKeySet, dateFieldOptions]);
11784
- const calendarEntries = React5.useMemo(() => {
11960
+ const calendarEntries = React6.useMemo(() => {
11785
11961
  if (!calendarDateField) return [];
11786
11962
  const entries = [];
11787
11963
  records.forEach((item) => {
@@ -11797,7 +11973,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
11797
11973
  });
11798
11974
  return entries;
11799
11975
  }, [calendarDateField, records]);
11800
- const earliestDateTs = React5.useMemo(() => {
11976
+ const earliestDateTs = React6.useMemo(() => {
11801
11977
  if (calendarEntries.length === 0) return null;
11802
11978
  let earliest = calendarEntries[0].date.valueOf();
11803
11979
  for (let index = 1; index < calendarEntries.length; index += 1) {
@@ -11806,8 +11982,8 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
11806
11982
  }
11807
11983
  return earliest;
11808
11984
  }, [calendarEntries]);
11809
- const initSignatureRef = React5.useRef("");
11810
- React5.useEffect(() => {
11985
+ const initSignatureRef = React6.useRef("");
11986
+ React6.useEffect(() => {
11811
11987
  const signature = `${calendarDateField}|${calendarMode}|${earliestDateTs ?? "none"}`;
11812
11988
  if (initSignatureRef.current === signature) return;
11813
11989
  initSignatureRef.current = signature;
@@ -11817,7 +11993,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
11817
11993
  }
11818
11994
  setCalendarAnchorDate(dayjs9__default.default(earliestDateTs).startOf(calendarMode));
11819
11995
  }, [calendarDateField, calendarMode, earliestDateTs]);
11820
- const entriesByDate = React5.useMemo(() => {
11996
+ const entriesByDate = React6.useMemo(() => {
11821
11997
  const grouped = /* @__PURE__ */ new Map();
11822
11998
  calendarEntries.forEach((entry) => {
11823
11999
  const key = entry.date.format("YYYY-MM-DD");
@@ -11827,7 +12003,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
11827
12003
  });
11828
12004
  return grouped;
11829
12005
  }, [calendarEntries]);
11830
- const rangeDays = React5.useMemo(() => {
12006
+ const rangeDays = React6.useMemo(() => {
11831
12007
  const current = calendarAnchorDate.startOf(calendarMode);
11832
12008
  if (calendarMode === "week") {
11833
12009
  const start2 = current.startOf("week");
@@ -11838,7 +12014,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
11838
12014
  const totalDays = end.diff(start, "day") + 1;
11839
12015
  return Array.from({ length: totalDays }, (_unused, offset) => start.add(offset, "day"));
11840
12016
  }, [calendarAnchorDate, calendarMode]);
11841
- const periodLabel = React5.useMemo(() => {
12017
+ const periodLabel = React6.useMemo(() => {
11842
12018
  if (calendarMode === "week") {
11843
12019
  const weekStart = calendarAnchorDate.startOf("week");
11844
12020
  const weekEnd = weekStart.endOf("week");
@@ -11998,9 +12174,9 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
11998
12174
  ] });
11999
12175
  };
12000
12176
  var RelatedObjectPrimaryCard = ({ record, model, allModels, customPageName }) => {
12001
- const allModelsList = React5.useMemo(() => allModels || [], [allModels]);
12177
+ const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
12002
12178
  const tone = useModelTone(model);
12003
- const PrimaryShowRenderer = React5.useContext(PrimaryShowContext);
12179
+ const PrimaryShowRenderer = React6.useContext(PrimaryShowContext);
12004
12180
  const label = getRecordDisplayLabel(record);
12005
12181
  const id = record?.eid ?? record?.id;
12006
12182
  const resource = resolveResourcePath(model.resource || model.name, allModelsList);
@@ -12090,22 +12266,22 @@ var RelatedObjectsEditableList = ({ rel, record, allModels }) => {
12090
12266
  const location = reactRouterDom.useLocation();
12091
12267
  const apiUrl = core.useApiUrl();
12092
12268
  const { token } = antd.theme.useToken();
12093
- const [page, setPage] = React5.useState(1);
12094
- const [pageSize, setPageSize] = React5.useState(INLINE_DEFAULT_PAGE_SIZE);
12269
+ const [page, setPage] = React6.useState(1);
12270
+ const [pageSize, setPageSize] = React6.useState(INLINE_DEFAULT_PAGE_SIZE);
12095
12271
  const { items: fetchedItems, loading, error, total } = useRelatedInlineItems({ rel, record, allModels, page, pageSize });
12096
- const [localItems, setLocalItems] = React5.useState(null);
12097
- React5.useEffect(() => {
12272
+ const [localItems, setLocalItems] = React6.useState(null);
12273
+ React6.useEffect(() => {
12098
12274
  setLocalItems(null);
12099
12275
  }, [fetchedItems]);
12100
12276
  const items = localItems ?? fetchedItems;
12101
- const [editing, setEditing] = React5.useState(false);
12102
- const [saving, setSaving] = React5.useState(false);
12103
- const [allOptions, setAllOptions] = React5.useState([]);
12104
- const [optionsLoading, setOptionsLoading] = React5.useState(false);
12105
- const [selectedIds, setSelectedIds] = React5.useState(/* @__PURE__ */ new Set());
12106
- const [baselineIds, setBaselineIds] = React5.useState(/* @__PURE__ */ new Set());
12107
- const [searchText, setSearchText] = React5.useState("");
12108
- React5.useEffect(() => {
12277
+ const [editing, setEditing] = React6.useState(false);
12278
+ const [saving, setSaving] = React6.useState(false);
12279
+ const [allOptions, setAllOptions] = React6.useState([]);
12280
+ const [optionsLoading, setOptionsLoading] = React6.useState(false);
12281
+ const [selectedIds, setSelectedIds] = React6.useState(/* @__PURE__ */ new Set());
12282
+ const [baselineIds, setBaselineIds] = React6.useState(/* @__PURE__ */ new Set());
12283
+ const [searchText, setSearchText] = React6.useState("");
12284
+ React6.useEffect(() => {
12109
12285
  if (!editing) return;
12110
12286
  const snapshot = new Set(items.map((item) => Number(item.id)));
12111
12287
  setBaselineIds(snapshot);
@@ -12139,7 +12315,7 @@ var RelatedObjectsEditableList = ({ rel, record, allModels }) => {
12139
12315
  cancelled = true;
12140
12316
  };
12141
12317
  }, [editing]);
12142
- const handleSave = React5.useCallback(async () => {
12318
+ const handleSave = React6.useCallback(async () => {
12143
12319
  if (!rel.otherKey || !rel.targetKey) return;
12144
12320
  const recordId = record?.eid ?? record?.id;
12145
12321
  if (recordId === void 0 || recordId === null) return;
@@ -12215,12 +12391,12 @@ var RelatedObjectsEditableList = ({ rel, record, allModels }) => {
12215
12391
  setSaving(false);
12216
12392
  }
12217
12393
  }, [apiUrl, allModels, allOptions, rel, record, selectedIds, baselineIds]);
12218
- const handleCancel = React5.useCallback(() => {
12394
+ const handleCancel = React6.useCallback(() => {
12219
12395
  setEditing(false);
12220
12396
  setSelectedIds(new Set(baselineIds));
12221
12397
  setSearchText("");
12222
12398
  }, [baselineIds]);
12223
- const handleCreateNewAndRelate = React5.useCallback(() => {
12399
+ const handleCreateNewAndRelate = React6.useCallback(() => {
12224
12400
  const otherKey = rel.otherKey;
12225
12401
  if (!otherKey || !rel.targetKey) return;
12226
12402
  const recordId = record?.eid ?? record?.id;
@@ -12376,17 +12552,17 @@ var _33 = window._ || ((text) => text);
12376
12552
  var RelatedObjectsEditableCsv = ({ rel, record, allModels }) => {
12377
12553
  const apiUrl = core.useApiUrl();
12378
12554
  const { items: fetchedItems, loading, error } = useRelatedInlineItems({ rel, record, allModels });
12379
- const [saving, setSaving] = React5.useState(false);
12380
- const [allOptions, setAllOptions] = React5.useState([]);
12381
- const [optionsLoading, setOptionsLoading] = React5.useState(false);
12382
- const [selectedIds, setSelectedIds] = React5.useState([]);
12383
- const [baselineIds, setBaselineIds] = React5.useState(/* @__PURE__ */ new Set());
12384
- React5.useEffect(() => {
12555
+ const [saving, setSaving] = React6.useState(false);
12556
+ const [allOptions, setAllOptions] = React6.useState([]);
12557
+ const [optionsLoading, setOptionsLoading] = React6.useState(false);
12558
+ const [selectedIds, setSelectedIds] = React6.useState([]);
12559
+ const [baselineIds, setBaselineIds] = React6.useState(/* @__PURE__ */ new Set());
12560
+ React6.useEffect(() => {
12385
12561
  const ids = fetchedItems.map((item) => Number(item.id));
12386
12562
  setSelectedIds(ids);
12387
12563
  setBaselineIds(new Set(ids));
12388
12564
  }, [fetchedItems]);
12389
- React5.useEffect(() => {
12565
+ React6.useEffect(() => {
12390
12566
  if (!rel.otherResource) return;
12391
12567
  let cancelled = false;
12392
12568
  const fetchOptions = async () => {
@@ -12413,7 +12589,7 @@ var RelatedObjectsEditableCsv = ({ rel, record, allModels }) => {
12413
12589
  cancelled = true;
12414
12590
  };
12415
12591
  }, [apiUrl, rel.otherResource]);
12416
- const handleChange = React5.useCallback(async (newIds) => {
12592
+ const handleChange = React6.useCallback(async (newIds) => {
12417
12593
  if (!rel.otherKey || !rel.targetKey) return;
12418
12594
  const recordId = record?.eid ?? record?.id;
12419
12595
  if (recordId === void 0 || recordId === null) return;
@@ -12475,15 +12651,15 @@ var { Title: Title4 } = antd.Typography;
12475
12651
  var PolymorphicRelatedObjectsTable = ({ rel, record, relationModel, parentModel, allModels, showActions = false, showCreate = false, allowInlineEdit = false, layoutPreferenceType, viewVariant = "default", viewMode = "table" }) => {
12476
12652
  const recordId = record?.[parentModel?.pkField ?? "eid"] ?? record?.eid ?? record?.id;
12477
12653
  const apiUrl = core.useApiUrl();
12478
- const [loading, setLoading] = React5.useState(false);
12479
- const [error, setError] = React5.useState(null);
12480
- const [groupedIds, setGroupedIds] = React5.useState(/* @__PURE__ */ new Map());
12481
- const [unresolvedIds, setUnresolvedIds] = React5.useState([]);
12482
- const polyInfo = React5.useMemo(
12654
+ const [loading, setLoading] = React6.useState(false);
12655
+ const [error, setError] = React6.useState(null);
12656
+ const [groupedIds, setGroupedIds] = React6.useState(/* @__PURE__ */ new Map());
12657
+ const [unresolvedIds, setUnresolvedIds] = React6.useState([]);
12658
+ const polyInfo = React6.useMemo(
12483
12659
  () => getPolymorphicReferenceInfo(rel, relationModel, allModels),
12484
12660
  [rel.otherKey, rel.otherResource, relationModel, allModels]
12485
12661
  );
12486
- React5.useEffect(() => {
12662
+ React6.useEffect(() => {
12487
12663
  if (!recordId || !rel.otherKey || !polyInfo) {
12488
12664
  setGroupedIds(/* @__PURE__ */ new Map());
12489
12665
  setUnresolvedIds([]);
@@ -12602,96 +12778,96 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12602
12778
  color: relatedModelTone.solid,
12603
12779
  margin: 0
12604
12780
  };
12605
- const chartSvgRef = React5.useRef(null);
12606
- const skipNextAnimationRef = React5.useRef(false);
12607
- const [rows, setRows] = React5.useState([]);
12608
- const [localSearch, setLocalSearch] = React5.useState("");
12609
- const [filterRules, setFilterRules] = React5.useState([]);
12610
- const [filtersCollapsed, setFiltersCollapsed] = React5.useState(true);
12611
- const [columnsSelectorOpen, setColumnsSelectorOpen] = React5.useState(false);
12612
- const [selectedColumnKeys, setSelectedColumnKeys] = React5.useState(null);
12613
- const [columnOrder, setColumnOrder] = React5.useState(null);
12614
- const [totalsSummaryFunctions, setTotalsSummaryFunctions] = React5.useState({});
12615
- const [columnFiltersSelected, setColumnFiltersSelected] = React5.useState({});
12616
- const [columnSort, setColumnSort] = React5.useState([]);
12617
- const [currentViewName, setCurrentViewName] = React5.useState(getDefaultViewName());
12618
- const [selectedViewNames, setSelectedViewNames] = React5.useState([]);
12619
- const [availableViewNames, setAvailableViewNames] = React5.useState([]);
12620
- const [viewNamesLoaded, setViewNamesLoaded] = React5.useState(false);
12621
- const [isLoadingViewNames, setIsLoadingViewNames] = React5.useState(false);
12622
- const [saveViewModalOpen, setSaveViewModalOpen] = React5.useState(false);
12623
- const [saveViewName, setSaveViewName] = React5.useState(getDefaultViewName());
12624
- const [saveViewAsNew, setSaveViewAsNew] = React5.useState(false);
12625
- const [pendingSaveTarget, setPendingSaveTarget] = React5.useState(null);
12626
- const [renameViewModalOpen, setRenameViewModalOpen] = React5.useState(false);
12627
- const [renameViewName, setRenameViewName] = React5.useState("");
12628
- const [pageSize, setPageSize] = React5.useState(10);
12629
- const [currentPage, setCurrentPage] = React5.useState(1);
12630
- const [serverTotalRows, setServerTotalRows] = React5.useState(0);
12631
- const [fullDataLoaded, setFullDataLoaded] = React5.useState(false);
12632
- const [relationRowsCapped, setRelationRowsCapped] = React5.useState(false);
12633
- const [loadedRowsCount, setLoadedRowsCount] = React5.useState(0);
12634
- const [loadAllRelatedRequested, setLoadAllRelatedRequested] = React5.useState(false);
12635
- const [loading, setLoading] = React5.useState(false);
12636
- const [error, setError] = React5.useState(null);
12637
- const [listVisible, setListVisible] = React5.useState(true);
12638
- const [isAnalyzeVertical, setIsAnalyzeVertical] = React5.useState(false);
12639
- const [isAnalyzeFirst, setIsAnalyzeFirst] = React5.useState(false);
12640
- const [labelCache, setLabelCache] = React5.useState({});
12641
- const [analyzeOpen, setAnalyzeOpen] = React5.useState(false);
12642
- const analyzeTouchedRef = React5.useRef(false);
12643
- const analyzePrefsTouchedRef = React5.useRef(false);
12644
- const analyzePrefsLoadedRef = React5.useRef(false);
12645
- const [analyzePrefsReady, setAnalyzePrefsReady] = React5.useState(false);
12646
- const analyzePrefsResourceRef = React5.useRef(null);
12647
- const [categoryField1, setCategoryField1] = React5.useState(null);
12648
- const [categoryField2, setCategoryField2] = React5.useState(void 0);
12649
- const [crosstabFilterFields, setCrosstabFilterFields] = React5.useState([]);
12650
- const [crosstabStaged, setCrosstabStaged] = React5.useState({});
12651
- const [chartType, setChartType] = React5.useState("area");
12652
- const [summaryFn, setSummaryFn] = React5.useState("sum");
12653
- const [selectedSeriesKeys, setSelectedSeriesKeys] = React5.useState(null);
12654
- const [rankingMode, setRankingMode] = React5.useState("none");
12655
- const [rankingFieldKey, setRankingFieldKey] = React5.useState(null);
12656
- const [rankingN, setRankingN] = React5.useState(10);
12657
- const [exportRequested, setExportRequested] = React5.useState(false);
12658
- const [isStatsFlipped, setIsStatsFlipped] = React5.useState(false);
12659
- const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] = React5.useState(false);
12660
- const [chartAnimationKey, setChartAnimationKey] = React5.useState(0);
12661
- const [chartAnimationStage, setChartAnimationStage] = React5.useState("enter");
12662
- const [isTotalsDetailsFlipped, setIsTotalsDetailsFlipped] = React5.useState(false);
12663
- const defaultDisplayFields = React5.useMemo(() => getListViewFields(relatedModel), [relatedModel]);
12664
- const orderedColumnKeys = React5.useMemo(() => {
12781
+ const chartSvgRef = React6.useRef(null);
12782
+ const skipNextAnimationRef = React6.useRef(false);
12783
+ const [rows, setRows] = React6.useState([]);
12784
+ const [localSearch, setLocalSearch] = React6.useState("");
12785
+ const [filterRules, setFilterRules] = React6.useState([]);
12786
+ const [filtersCollapsed, setFiltersCollapsed] = React6.useState(true);
12787
+ const [columnsSelectorOpen, setColumnsSelectorOpen] = React6.useState(false);
12788
+ const [selectedColumnKeys, setSelectedColumnKeys] = React6.useState(null);
12789
+ const [columnOrder, setColumnOrder] = React6.useState(null);
12790
+ const [totalsSummaryFunctions, setTotalsSummaryFunctions] = React6.useState({});
12791
+ const [columnFiltersSelected, setColumnFiltersSelected] = React6.useState({});
12792
+ const [columnSort, setColumnSort] = React6.useState([]);
12793
+ const [currentViewName, setCurrentViewName] = React6.useState(getDefaultViewName());
12794
+ const [selectedViewNames, setSelectedViewNames] = React6.useState([]);
12795
+ const [availableViewNames, setAvailableViewNames] = React6.useState([]);
12796
+ const [viewNamesLoaded, setViewNamesLoaded] = React6.useState(false);
12797
+ const [isLoadingViewNames, setIsLoadingViewNames] = React6.useState(false);
12798
+ const [saveViewModalOpen, setSaveViewModalOpen] = React6.useState(false);
12799
+ const [saveViewName, setSaveViewName] = React6.useState(getDefaultViewName());
12800
+ const [saveViewAsNew, setSaveViewAsNew] = React6.useState(false);
12801
+ const [pendingSaveTarget, setPendingSaveTarget] = React6.useState(null);
12802
+ const [renameViewModalOpen, setRenameViewModalOpen] = React6.useState(false);
12803
+ const [renameViewName, setRenameViewName] = React6.useState("");
12804
+ const [pageSize, setPageSize] = React6.useState(10);
12805
+ const [currentPage, setCurrentPage] = React6.useState(1);
12806
+ const [serverTotalRows, setServerTotalRows] = React6.useState(0);
12807
+ const [fullDataLoaded, setFullDataLoaded] = React6.useState(false);
12808
+ const [relationRowsCapped, setRelationRowsCapped] = React6.useState(false);
12809
+ const [loadedRowsCount, setLoadedRowsCount] = React6.useState(0);
12810
+ const [loadAllRelatedRequested, setLoadAllRelatedRequested] = React6.useState(false);
12811
+ const [loading, setLoading] = React6.useState(false);
12812
+ const [error, setError] = React6.useState(null);
12813
+ const [listVisible, setListVisible] = React6.useState(true);
12814
+ const [isAnalyzeVertical, setIsAnalyzeVertical] = React6.useState(false);
12815
+ const [isAnalyzeFirst, setIsAnalyzeFirst] = React6.useState(false);
12816
+ const [labelCache, setLabelCache] = React6.useState({});
12817
+ const [analyzeOpen, setAnalyzeOpen] = React6.useState(false);
12818
+ const analyzeTouchedRef = React6.useRef(false);
12819
+ const analyzePrefsTouchedRef = React6.useRef(false);
12820
+ const analyzePrefsLoadedRef = React6.useRef(false);
12821
+ const [analyzePrefsReady, setAnalyzePrefsReady] = React6.useState(false);
12822
+ const analyzePrefsResourceRef = React6.useRef(null);
12823
+ const [categoryField1, setCategoryField1] = React6.useState(null);
12824
+ const [categoryField2, setCategoryField2] = React6.useState(void 0);
12825
+ const [crosstabFilterFields, setCrosstabFilterFields] = React6.useState([]);
12826
+ const [crosstabStaged, setCrosstabStaged] = React6.useState({});
12827
+ const [chartType, setChartType] = React6.useState("area");
12828
+ const [summaryFn, setSummaryFn] = React6.useState("sum");
12829
+ const [selectedSeriesKeys, setSelectedSeriesKeys] = React6.useState(null);
12830
+ const [rankingMode, setRankingMode] = React6.useState("none");
12831
+ const [rankingFieldKey, setRankingFieldKey] = React6.useState(null);
12832
+ const [rankingN, setRankingN] = React6.useState(10);
12833
+ const [exportRequested, setExportRequested] = React6.useState(false);
12834
+ const [isStatsFlipped, setIsStatsFlipped] = React6.useState(false);
12835
+ const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] = React6.useState(false);
12836
+ const [chartAnimationKey, setChartAnimationKey] = React6.useState(0);
12837
+ const [chartAnimationStage, setChartAnimationStage] = React6.useState("enter");
12838
+ const [isTotalsDetailsFlipped, setIsTotalsDetailsFlipped] = React6.useState(false);
12839
+ const defaultDisplayFields = React6.useMemo(() => getListViewFields(relatedModel), [relatedModel]);
12840
+ const orderedColumnKeys = React6.useMemo(() => {
12665
12841
  if (!selectedColumnKeys || selectedColumnKeys.length === 0) return null;
12666
12842
  const order = columnOrder && columnOrder.length > 0 ? columnOrder : selectedColumnKeys;
12667
12843
  const selectedSet = new Set(selectedColumnKeys);
12668
12844
  const availableKeys = new Set(relatedModel.fields.map((field) => field.key));
12669
12845
  return order.filter((key) => selectedSet.has(key) && availableKeys.has(key));
12670
12846
  }, [columnOrder, relatedModel.fields, selectedColumnKeys]);
12671
- const displayFields = React5.useMemo(() => {
12847
+ const displayFields = React6.useMemo(() => {
12672
12848
  if (!orderedColumnKeys) return defaultDisplayFields;
12673
12849
  const fieldMap = new Map(relatedModel.fields.map((field) => [field.key, field]));
12674
12850
  return orderedColumnKeys.map((key) => fieldMap.get(key)).filter((field) => Boolean(field));
12675
12851
  }, [defaultDisplayFields, orderedColumnKeys, relatedModel.fields]);
12676
12852
  const numericBarColor = relatedModelTone.soft || token.colorPrimaryBg || "rgba(22, 119, 255, 0.16)";
12677
12853
  const [form] = antd.Form.useForm();
12678
- const [savingAll, setSavingAll] = React5.useState(false);
12679
- const [hasPendingEdits, setHasPendingEdits] = React5.useState(false);
12854
+ const [savingAll, setSavingAll] = React6.useState(false);
12855
+ const [hasPendingEdits, setHasPendingEdits] = React6.useState(false);
12680
12856
  const { setWarnWhen } = core.useWarnAboutChange();
12681
- const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] = React5.useState(false);
12682
- const layoutPrefsTouchedRef = React5.useRef(false);
12683
- const layoutPrefsLoadedRef = React5.useRef(false);
12684
- const layoutPrefsResourceRef = React5.useRef(null);
12685
- const sortIntentRef = React5.useRef(null);
12857
+ const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] = React6.useState(false);
12858
+ const layoutPrefsTouchedRef = React6.useRef(false);
12859
+ const layoutPrefsLoadedRef = React6.useRef(false);
12860
+ const layoutPrefsResourceRef = React6.useRef(null);
12861
+ const sortIntentRef = React6.useRef(null);
12686
12862
  const { settings: viewSettings } = useViewSettings();
12687
12863
  const relationsMaxRowsToLoad = Math.max(0, Number(viewSettings?.relationsMaxRowsToLoad ?? 1e3));
12688
- const markAnalyzePrefsTouched = React5.useCallback(() => {
12864
+ const markAnalyzePrefsTouched = React6.useCallback(() => {
12689
12865
  analyzePrefsTouchedRef.current = true;
12690
12866
  }, []);
12691
- const markLayoutPrefsTouched = React5.useCallback(() => {
12867
+ const markLayoutPrefsTouched = React6.useCallback(() => {
12692
12868
  layoutPrefsTouchedRef.current = true;
12693
12869
  }, []);
12694
- const persistLayoutPreferences = React5.useCallback(async (viewName) => {
12870
+ const persistLayoutPreferences = React6.useCallback(async (viewName) => {
12695
12871
  if (!layoutPreferenceType) return;
12696
12872
  const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
12697
12873
  const resolvedViewName = normalizeViewName(viewName);
@@ -12735,7 +12911,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12735
12911
  setIsSavingLayoutPrefs(false);
12736
12912
  }
12737
12913
  }, [apiUrl, analyzeOpen, columnFiltersSelected, columnOrder, columnSort, filtersCollapsed, filterRules, isAnalyzeFirst, isAnalyzeVertical, layoutPreferenceType, listVisible, pageSize, selectedColumnKeys, relatedModel.name, relatedModel.resource, totalsSummaryFunctions, allModels]);
12738
- const persistAnalyzePreferences = React5.useCallback(async (viewName) => {
12914
+ const persistAnalyzePreferences = React6.useCallback(async (viewName) => {
12739
12915
  const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
12740
12916
  const resolvedViewName = normalizeViewName(viewName);
12741
12917
  const preferences = {
@@ -12767,13 +12943,13 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12767
12943
  setIsSavingAnalyzePrefs(false);
12768
12944
  }
12769
12945
  }, [apiUrl, categoryField1, categoryField2, chartType, selectedSeriesKeys, summaryFn, rankingMode, rankingFieldKey, rankingN, crosstabFilterFields, relatedModel.name, relatedModel.resource, allModels]);
12770
- const categoricalFields = React5.useMemo(() => {
12946
+ const categoricalFields = React6.useMemo(() => {
12771
12947
  return relatedModel.fields.filter((field) => isPkField(field, relatedModel) || (field.type !== "number" || field.reference));
12772
12948
  }, [relatedModel]);
12773
- const numericFields = React5.useMemo(() => {
12949
+ const numericFields = React6.useMemo(() => {
12774
12950
  return relatedModel.fields.filter((field) => !isPkField(field, relatedModel) && field.type === "number" && !field.reference);
12775
12951
  }, [relatedModel]);
12776
- const resetLayoutDefaults = React5.useCallback(() => {
12952
+ const resetLayoutDefaults = React6.useCallback(() => {
12777
12953
  setListVisible(true);
12778
12954
  setAnalyzeOpen(false);
12779
12955
  setIsAnalyzeVertical(false);
@@ -12783,7 +12959,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12783
12959
  setSelectedColumnKeys(null);
12784
12960
  setColumnOrder(null);
12785
12961
  }, []);
12786
- const resetAnalyzeDefaults = React5.useCallback(() => {
12962
+ const resetAnalyzeDefaults = React6.useCallback(() => {
12787
12963
  setCategoryField1(categoricalFields[0]?.key ?? null);
12788
12964
  setCategoryField2(categoricalFields.length > 1 ? categoricalFields[1].key : null);
12789
12965
  setChartType("area");
@@ -12794,7 +12970,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12794
12970
  setRankingN(10);
12795
12971
  setCrosstabFilterFields([]);
12796
12972
  }, [categoricalFields, numericFields]);
12797
- const persistCurrentViewNames = React5.useCallback(async (nextSelected, nextCurrent) => {
12973
+ const persistCurrentViewNames = React6.useCallback(async (nextSelected, nextCurrent) => {
12798
12974
  try {
12799
12975
  const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
12800
12976
  await authenticatedFetch(`${apiUrl}/views/preferences/view`, {
@@ -12810,7 +12986,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12810
12986
  } catch {
12811
12987
  }
12812
12988
  }, [apiUrl, relatedModel.name, relatedModel.resource, allModels]);
12813
- const loadViewNames = React5.useCallback(async () => {
12989
+ const loadViewNames = React6.useCallback(async () => {
12814
12990
  const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
12815
12991
  setIsLoadingViewNames(true);
12816
12992
  try {
@@ -12855,13 +13031,13 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12855
13031
  setIsLoadingViewNames(false);
12856
13032
  }
12857
13033
  }, [apiUrl, relatedModel.name, relatedModel.resource, allModels]);
12858
- const openSaveViewModalFor = React5.useCallback((target) => {
13034
+ const openSaveViewModalFor = React6.useCallback((target) => {
12859
13035
  setSaveViewName(currentViewName || getDefaultViewName());
12860
13036
  setSaveViewAsNew(false);
12861
13037
  setPendingSaveTarget(target);
12862
13038
  setSaveViewModalOpen(true);
12863
13039
  }, [currentViewName]);
12864
- const handleConfirmSaveView = React5.useCallback(async () => {
13040
+ const handleConfirmSaveView = React6.useCallback(async () => {
12865
13041
  if (!pendingSaveTarget) return;
12866
13042
  const viewName = normalizeViewName(saveViewName || currentViewName);
12867
13043
  const viewExists = availableViewNames.includes(viewName);
@@ -12888,14 +13064,14 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12888
13064
  await persistCurrentViewNames(nextSelected, viewName);
12889
13065
  await loadViewNames();
12890
13066
  }, [availableViewNames, currentViewName, loadViewNames, pendingSaveTarget, persistAnalyzePreferences, persistCurrentViewNames, persistLayoutPreferences, saveViewAsNew, saveViewName, selectedViewNames]);
12891
- const handleChangeViewName = React5.useCallback(async (nextView) => {
13067
+ const handleChangeViewName = React6.useCallback(async (nextView) => {
12892
13068
  const resolvedName = normalizeViewName(nextView);
12893
13069
  setCurrentViewName(resolvedName);
12894
13070
  setSaveViewName(resolvedName);
12895
13071
  const nextSelected = selectedViewNames.length > 0 ? selectedViewNames : [resolvedName];
12896
13072
  await persistCurrentViewNames(nextSelected, resolvedName);
12897
13073
  }, [persistCurrentViewNames, selectedViewNames]);
12898
- const updateSelectedViewNames = React5.useCallback(async (nextSelected) => {
13074
+ const updateSelectedViewNames = React6.useCallback(async (nextSelected) => {
12899
13075
  if (nextSelected.length === 0) {
12900
13076
  nextSelected = [getDefaultViewName()];
12901
13077
  }
@@ -12907,7 +13083,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12907
13083
  }
12908
13084
  await persistCurrentViewNames(nextSelected, nextCurrent);
12909
13085
  }, [currentViewName, persistCurrentViewNames]);
12910
- const moveSelectedView = React5.useCallback((name, direction) => {
13086
+ const moveSelectedView = React6.useCallback((name, direction) => {
12911
13087
  setSelectedViewNames((prev) => {
12912
13088
  const idx = prev.indexOf(name);
12913
13089
  if (idx < 0) return prev;
@@ -12919,7 +13095,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12919
13095
  return next;
12920
13096
  });
12921
13097
  }, [currentViewName, persistCurrentViewNames]);
12922
- const handleRenameView = React5.useCallback(async () => {
13098
+ const handleRenameView = React6.useCallback(async () => {
12923
13099
  const newName = normalizeViewName(renameViewName);
12924
13100
  if (!newName || newName === currentViewName) {
12925
13101
  setRenameViewModalOpen(false);
@@ -12946,7 +13122,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12946
13122
  antd.message.error(error2 instanceof Error ? error2.message : _34("Failed to rename view."));
12947
13123
  }
12948
13124
  }, [apiUrl, availableViewNames, currentViewName, relatedModel.name, relatedModel.resource, renameViewName, allModels, loadViewNames]);
12949
- const confirmDeleteView = React5.useCallback(() => {
13125
+ const confirmDeleteView = React6.useCallback(() => {
12950
13126
  antd.Modal.confirm({
12951
13127
  title: _34(_34("Delete view")),
12952
13128
  content: `Delete "${currentViewName}" and all its saved preferences?`,
@@ -12991,10 +13167,10 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
12991
13167
  items: selectedViewNames.map((name) => ({ key: name, label: renderToneTabLabel(name, relatedModelTone) }))
12992
13168
  }
12993
13169
  ) : null;
12994
- React5.useEffect(() => {
13170
+ React6.useEffect(() => {
12995
13171
  loadViewNames();
12996
13172
  }, [loadViewNames]);
12997
- React5.useEffect(() => {
13173
+ React6.useEffect(() => {
12998
13174
  if (!viewNamesLoaded) return;
12999
13175
  analyzePrefsTouchedRef.current = false;
13000
13176
  layoutPrefsTouchedRef.current = false;
@@ -13006,7 +13182,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13006
13182
  resetLayoutDefaults();
13007
13183
  resetAnalyzeDefaults();
13008
13184
  }, [currentViewName, resetAnalyzeDefaults, resetLayoutDefaults, viewNamesLoaded]);
13009
- React5.useEffect(() => {
13185
+ React6.useEffect(() => {
13010
13186
  const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
13011
13187
  const viewKey = `${resourceKey}::${currentViewName}`;
13012
13188
  if (analyzePrefsResourceRef.current !== viewKey) {
@@ -13059,7 +13235,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13059
13235
  cancelled = true;
13060
13236
  };
13061
13237
  }, [apiUrl, currentViewName, relatedModel.name, relatedModel.resource, allModels]);
13062
- React5.useEffect(() => {
13238
+ React6.useEffect(() => {
13063
13239
  if (!layoutPreferenceType) return;
13064
13240
  const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
13065
13241
  const viewKey = `${resourceKey}::${layoutPreferenceType}::${currentViewName}`;
@@ -13138,17 +13314,17 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13138
13314
  cancelled = true;
13139
13315
  };
13140
13316
  }, [apiUrl, currentViewName, layoutPreferenceType, relatedModel.name, relatedModel.resource, allModels, viewNamesLoaded]);
13141
- const normalizeFieldValue = React5.useCallback((field, value) => {
13317
+ const normalizeFieldValue = React6.useCallback((field, value) => {
13142
13318
  if (field.type === "date" && value) {
13143
13319
  if (typeof value?.toISOString === "function") return value.toISOString();
13144
13320
  if (typeof value?.format === "function") return value.format("YYYY-MM-DD");
13145
13321
  }
13146
13322
  return value;
13147
13323
  }, []);
13148
- const hasActiveFilterRules = React5.useMemo(() => {
13324
+ const hasActiveFilterRules = React6.useMemo(() => {
13149
13325
  return filterRules.some((rule) => rule.fieldKey && rule.operator && (rule.value !== void 0 && rule.value !== null && rule.value !== ""));
13150
13326
  }, [filterRules]);
13151
- const resolveRelativeDate = React5.useCallback((value, asRange) => {
13327
+ const resolveRelativeDate = React6.useCallback((value, asRange) => {
13152
13328
  const count = Number(value?.count ?? 1);
13153
13329
  const direction = value?.direction || "next";
13154
13330
  const unit = value?.unit || "weeks";
@@ -13174,7 +13350,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13174
13350
  }
13175
13351
  return { date: target.startOf(unit) };
13176
13352
  }, []);
13177
- const getFieldValueForFilter = React5.useCallback((field, recordRow) => {
13353
+ const getFieldValueForFilter = React6.useCallback((field, recordRow) => {
13178
13354
  const raw = recordRow?.[field.key];
13179
13355
  if (raw === void 0 || raw === null) return raw;
13180
13356
  if (field.reference) {
@@ -13186,7 +13362,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13186
13362
  }
13187
13363
  return raw;
13188
13364
  }, [labelCache]);
13189
- const matchesRule = React5.useCallback((recordRow, rule) => {
13365
+ const matchesRule = React6.useCallback((recordRow, rule) => {
13190
13366
  const field = relatedModel.fields.find((f) => f.key === rule.fieldKey);
13191
13367
  if (!field || !rule.operator) return true;
13192
13368
  const rawValue = getFieldValueForFilter(field, recordRow);
@@ -13266,7 +13442,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13266
13442
  }
13267
13443
  return true;
13268
13444
  }, [getFieldValueForFilter, relatedModel.fields, resolveRelativeDate]);
13269
- const applyGlobalSearch = React5.useCallback((data) => {
13445
+ const applyGlobalSearch = React6.useCallback((data) => {
13270
13446
  const query = localSearch.trim().toLowerCase();
13271
13447
  if (!query) return data;
13272
13448
  return data.filter((recordRow) => {
@@ -13285,14 +13461,14 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13285
13461
  return candidates.some((value) => value !== void 0 && value !== null && String(value).toLowerCase().includes(query));
13286
13462
  });
13287
13463
  }, [labelCache, localSearch, relatedModel.fields]);
13288
- const applyFilterRules = React5.useCallback((data) => {
13464
+ const applyFilterRules = React6.useCallback((data) => {
13289
13465
  if (!hasActiveFilterRules) return data;
13290
13466
  return data.filter((recordRow) => filterRules.every((rule) => matchesRule(recordRow, rule)));
13291
13467
  }, [filterRules, hasActiveFilterRules, matchesRule]);
13292
- const filteredRows = React5.useMemo(() => {
13468
+ const filteredRows = React6.useMemo(() => {
13293
13469
  return applyFilterRules(applyGlobalSearch(rows || []));
13294
13470
  }, [applyFilterRules, applyGlobalSearch, rows]);
13295
- const columnFilteredRows = React5.useMemo(() => {
13471
+ const columnFilteredRows = React6.useMemo(() => {
13296
13472
  const activeEntries = Object.entries(columnFiltersSelected).filter(([, values]) => values && values.length > 0);
13297
13473
  if (activeEntries.length === 0) return filteredRows;
13298
13474
  return filteredRows.filter(
@@ -13303,10 +13479,10 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13303
13479
  })
13304
13480
  );
13305
13481
  }, [filteredRows, columnFiltersSelected, relatedModel.fields]);
13306
- React5.useEffect(() => {
13482
+ React6.useEffect(() => {
13307
13483
  setCurrentPage(1);
13308
13484
  }, [localSearch, filterRules]);
13309
- React5.useEffect(() => {
13485
+ React6.useEffect(() => {
13310
13486
  if (!allowInlineEdit) return;
13311
13487
  if (form.isFieldsTouched()) return;
13312
13488
  const initialValues = {};
@@ -13320,7 +13496,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13320
13496
  });
13321
13497
  form.setFieldsValue(initialValues);
13322
13498
  }, [allowInlineEdit, form, relatedModel.fields, filteredRows]);
13323
- React5.useEffect(() => {
13499
+ React6.useEffect(() => {
13324
13500
  if (!allowInlineEdit) {
13325
13501
  setWarnWhen(false);
13326
13502
  return;
@@ -13328,7 +13504,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13328
13504
  setWarnWhen(hasPendingEdits);
13329
13505
  return () => setWarnWhen(false);
13330
13506
  }, [allowInlineEdit, hasPendingEdits, setWarnWhen]);
13331
- const saveAllEdits = React5.useCallback(async () => {
13507
+ const saveAllEdits = React6.useCallback(async () => {
13332
13508
  if (!allowInlineEdit) return;
13333
13509
  setSavingAll(true);
13334
13510
  try {
@@ -13382,7 +13558,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13382
13558
  setSavingAll(false);
13383
13559
  }
13384
13560
  }, [allowInlineEdit, apiUrl, form, normalizeFieldValue, relatedModel.fields, relatedModel.name, relatedModel.resource, allModels, rows]);
13385
- const handleDeleteRelationRow = React5.useCallback((row) => {
13561
+ const handleDeleteRelationRow = React6.useCallback((row) => {
13386
13562
  const relationRow = row?.__relationRow;
13387
13563
  const deleteId = relationRow && rel.targetKey && rel.otherKey ? `${relationRow["eid_from"]}:${relationRow["eid_to"]}` : relationRow?.id ?? relationRow?.eid;
13388
13564
  if (deleteId === void 0 || deleteId === null) return;
@@ -13439,7 +13615,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13439
13615
  overflow: "visible",
13440
13616
  order: isAnalyzeFirst ? 1 : 2
13441
13617
  };
13442
- const getSortValue = React5.useCallback((field, recordRow) => {
13618
+ const getSortValue = React6.useCallback((field, recordRow) => {
13443
13619
  const raw = recordRow?.[field.key];
13444
13620
  if (raw === void 0 || raw === null) return null;
13445
13621
  if (isPkField(field, relatedModel) && recordRow?._label) return recordRow._label;
@@ -13458,7 +13634,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13458
13634
  if (field.type === "boolean") return raw ? 1 : 0;
13459
13635
  return raw;
13460
13636
  }, [labelCache]);
13461
- const compareSortValues = React5.useCallback((field, a, b) => {
13637
+ const compareSortValues = React6.useCallback((field, a, b) => {
13462
13638
  const aVal = getSortValue(field, a);
13463
13639
  const bVal = getSortValue(field, b);
13464
13640
  if (aVal === null && bVal === null) return 0;
@@ -13467,11 +13643,11 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13467
13643
  if (typeof aVal === "number" && typeof bVal === "number") return aVal - bVal;
13468
13644
  return String(aVal).localeCompare(String(bVal));
13469
13645
  }, [getSortValue]);
13470
- const shouldUseFullDataMode = React5.useMemo(() => {
13646
+ const shouldUseFullDataMode = React6.useMemo(() => {
13471
13647
  if (loadAllRelatedRequested) return true;
13472
13648
  return false;
13473
13649
  }, [loadAllRelatedRequested]);
13474
- const fetchRelatedDetailsByIds = React5.useCallback(async (ids, signal) => {
13650
+ const fetchRelatedDetailsByIds = React6.useCallback(async (ids, signal) => {
13475
13651
  const uniqueIds = Array.from(new Set(ids.filter((value) => value !== void 0 && value !== null)));
13476
13652
  if (!rel.otherResource || uniqueIds.length === 0) return [];
13477
13653
  const relatedResource = rel.otherResourcePath || resolveResourcePath(rel.otherResource, allModels);
@@ -13522,7 +13698,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13522
13698
  const now = performance.now();
13523
13699
  console.log(`[JM_TRACE ${now.toFixed(1)}ms] ${label}${detail ? " | " + detail : ""}`);
13524
13700
  };
13525
- React5.useEffect(() => {
13701
+ React6.useEffect(() => {
13526
13702
  if (!recordId || !rel.otherResource || !rel.otherKey) {
13527
13703
  setRows([]);
13528
13704
  setServerTotalRows(0);
@@ -13669,26 +13845,26 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13669
13845
  controller.abort();
13670
13846
  };
13671
13847
  }, [apiUrl, currentPage, pageSize, recordId, rel.label, rel.otherKey, rel.otherResource, rel.resource, rel.targetKey, allowedRelatedIds, allModels, rel.resourcePath, rel.otherResourcePath, shouldUseFullDataMode, fetchRelatedDetailsByIds, fullDataLoaded, relationsMaxRowsToLoad, rows.length]);
13672
- React5.useEffect(() => {
13848
+ React6.useEffect(() => {
13673
13849
  if (!shouldUseFullDataMode && fullDataLoaded) {
13674
13850
  setFullDataLoaded(false);
13675
13851
  }
13676
13852
  }, [fullDataLoaded, shouldUseFullDataMode]);
13677
- React5.useEffect(() => {
13853
+ React6.useEffect(() => {
13678
13854
  if (loading) return;
13679
13855
  if (analyzeTouchedRef.current) return;
13680
13856
  if (filteredRows.length <= 1 && analyzeOpen) {
13681
13857
  setAnalyzeOpen(false);
13682
13858
  }
13683
13859
  }, [analyzeOpen, filteredRows.length, loading]);
13684
- React5.useEffect(() => {
13860
+ React6.useEffect(() => {
13685
13861
  if (loading) return;
13686
13862
  if (analyzeTouchedRef.current) return;
13687
13863
  if (filteredRows.length > 1 && !analyzeOpen) {
13688
13864
  setAnalyzeOpen(true);
13689
13865
  }
13690
13866
  }, [analyzeOpen, filteredRows.length, loading]);
13691
- React5.useEffect(() => {
13867
+ React6.useEffect(() => {
13692
13868
  if (!categoryField1 && categoricalFields.length > 0) {
13693
13869
  setCategoryField1(categoricalFields[0].key);
13694
13870
  }
@@ -13696,7 +13872,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13696
13872
  setCategoryField2(categoricalFields[1].key);
13697
13873
  }
13698
13874
  }, [categoricalFields, categoryField1, categoryField2]);
13699
- React5.useEffect(() => {
13875
+ React6.useEffect(() => {
13700
13876
  if (selectedSeriesKeys !== null) return;
13701
13877
  if (numericFields.length > 0) {
13702
13878
  setSelectedSeriesKeys(numericFields.map((field) => field.key));
@@ -13704,7 +13880,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13704
13880
  setSelectedSeriesKeys(["__count__"]);
13705
13881
  }
13706
13882
  }, [numericFields, selectedSeriesKeys]);
13707
- React5.useEffect(() => {
13883
+ React6.useEffect(() => {
13708
13884
  if (numericFields.length === 0) {
13709
13885
  if (rankingFieldKey !== null) setRankingFieldKey(null);
13710
13886
  if (rankingMode !== "none") setRankingMode("none");
@@ -13714,7 +13890,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13714
13890
  setRankingFieldKey(numericFields[0].key);
13715
13891
  }
13716
13892
  }, [numericFields, rankingFieldKey, rankingMode]);
13717
- const formatCategoryValue = React5.useCallback((field, recordRow) => {
13893
+ const formatCategoryValue = React6.useCallback((field, recordRow) => {
13718
13894
  if (!field) return _34("All");
13719
13895
  const raw = recordRow?.[field.key];
13720
13896
  if (raw === void 0 || raw === null) return "-";
@@ -13730,14 +13906,14 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13730
13906
  if (field.type === "date") return formatDateValue(raw);
13731
13907
  return String(raw);
13732
13908
  }, [labelCache]);
13733
- const chartTitle = React5.useMemo(() => {
13909
+ const chartTitle = React6.useMemo(() => {
13734
13910
  const cat1Label = categoryField1 ? relatedModel.fields.find((field) => field.key === categoryField1)?.label : "All";
13735
13911
  const cat2Label = categoryField2 ? relatedModel.fields.find((field) => field.key === categoryField2)?.label : null;
13736
13912
  const parts = [relatedModel.label || relatedModel.name, cat1Label];
13737
13913
  if (cat2Label) parts.push(cat2Label);
13738
13914
  return parts.filter(Boolean).join(" \u2022 ");
13739
13915
  }, [categoryField1, categoryField2, relatedModel.fields, relatedModel.label, relatedModel.name]);
13740
- const chartData = React5.useMemo(() => {
13916
+ const chartData = React6.useMemo(() => {
13741
13917
  const data = Array.isArray(columnFilteredRows) ? columnFilteredRows : [];
13742
13918
  const cat1Field = categoryField1 ? relatedModel.fields.find((field) => field.key === categoryField1) : void 0;
13743
13919
  const cat2Field = categoryField2 ? relatedModel.fields.find((field) => field.key === categoryField2) : void 0;
@@ -13845,7 +14021,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13845
14021
  };
13846
14022
  }, [columnFilteredRows, categoryField1, categoryField2, relatedModel.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
13847
14023
  const editableCrosstab = isCrosstabView && allowInlineEdit;
13848
- const stageCrosstabCellEdits = React5.useCallback((updates) => {
14024
+ const stageCrosstabCellEdits = React6.useCallback((updates) => {
13849
14025
  if (updates.length === 0) return;
13850
14026
  setCrosstabStaged((prev) => {
13851
14027
  const next = { ...prev };
@@ -13860,11 +14036,11 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13860
14036
  });
13861
14037
  setHasPendingEdits(true);
13862
14038
  }, [form]);
13863
- const getCrosstabStagedValue = React5.useCallback((recordId2, fieldKey) => {
14039
+ const getCrosstabStagedValue = React6.useCallback((recordId2, fieldKey) => {
13864
14040
  return crosstabStaged[String(recordId2)]?.[fieldKey];
13865
14041
  }, [crosstabStaged]);
13866
- const crosstabResolvedRefIdsRef = React5.useRef(/* @__PURE__ */ new Set());
13867
- React5.useEffect(() => {
14042
+ const crosstabResolvedRefIdsRef = React6.useRef(/* @__PURE__ */ new Set());
14043
+ React6.useEffect(() => {
13868
14044
  if (!isCrosstabView) return;
13869
14045
  const refFields = [categoryField1, categoryField2, ...crosstabFilterFields].filter((k) => Boolean(k)).map((k) => relatedModel.fields.find((f) => f.key === k)).filter((f) => Boolean(f && f.reference));
13870
14046
  if (refFields.length === 0) return;
@@ -13900,7 +14076,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13900
14076
  cancelled = true;
13901
14077
  };
13902
14078
  }, [isCrosstabView, categoryField1, categoryField2, crosstabFilterFields, columnFilteredRows, relatedModel.fields, allModels, apiUrl]);
13903
- const crosstabFilterOptions = React5.useMemo(() => {
14079
+ const crosstabFilterOptions = React6.useMemo(() => {
13904
14080
  if (crosstabFilterFields.length === 0) return /* @__PURE__ */ new Map();
13905
14081
  const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
13906
14082
  const fields = crosstabFilterFields.map((k) => relatedModel.fields.find((f) => f.key === k)).filter((f) => Boolean(f));
@@ -14070,7 +14246,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14070
14246
  }
14071
14247
  )
14072
14248
  ] });
14073
- const numericColumnMaxes = React5.useMemo(() => {
14249
+ const numericColumnMaxes = React6.useMemo(() => {
14074
14250
  const maxes = {};
14075
14251
  const data = filteredRows || [];
14076
14252
  displayFields.forEach((field) => {
@@ -14084,7 +14260,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14084
14260
  });
14085
14261
  return maxes;
14086
14262
  }, [filteredRows, displayFields]);
14087
- const chartSignature = React5.useMemo(() => {
14263
+ const chartSignature = React6.useMemo(() => {
14088
14264
  return JSON.stringify({
14089
14265
  chartType,
14090
14266
  summaryFn,
@@ -14097,13 +14273,13 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14097
14273
  groups: chartData.groups
14098
14274
  });
14099
14275
  }, [chartType, summaryFn, categoryField1, categoryField2, rankingMode, rankingFieldKey, rankingN, chartData]);
14100
- React5.useEffect(() => {
14276
+ React6.useEffect(() => {
14101
14277
  if (!analyzeOpen) return;
14102
14278
  skipNextAnimationRef.current = true;
14103
14279
  setChartAnimationStage("enter");
14104
14280
  setChartAnimationKey((key) => key + 1);
14105
14281
  }, [analyzeOpen]);
14106
- React5.useEffect(() => {
14282
+ React6.useEffect(() => {
14107
14283
  if (!analyzeOpen) return;
14108
14284
  if (skipNextAnimationRef.current) {
14109
14285
  skipNextAnimationRef.current = false;
@@ -14112,7 +14288,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14112
14288
  setChartAnimationStage("update");
14113
14289
  setChartAnimationKey((key) => key + 1);
14114
14290
  }, [analyzeOpen, chartSignature]);
14115
- const formatValueForExport = React5.useCallback((field, recordRow) => {
14291
+ const formatValueForExport = React6.useCallback((field, recordRow) => {
14116
14292
  const raw = recordRow?.[field.key];
14117
14293
  if (raw === void 0 || raw === null) return "";
14118
14294
  if (field.reference) {
@@ -14126,7 +14302,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14126
14302
  if (field.type === "date") return formatDateValue(raw);
14127
14303
  return String(raw);
14128
14304
  }, [labelCache]);
14129
- React5.useEffect(() => {
14305
+ React6.useEffect(() => {
14130
14306
  if (!exportRequested) return;
14131
14307
  const escapeCsv = (value) => {
14132
14308
  if (value.includes('"') || value.includes(",") || value.includes("\n")) {
@@ -14212,31 +14388,31 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14212
14388
  const exportStatsPdf = () => {
14213
14389
  openPdfWindow(`${relatedModel.name}-stats`, buildStatsHtml(statsSummary));
14214
14390
  };
14215
- const columnFilters = React5.useMemo(() => {
14391
+ const columnFilters = React6.useMemo(() => {
14216
14392
  const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
14217
14393
  return buildColumnFilterOptions({ fields: displayFields, data: filteredRows || [], rangeCount });
14218
14394
  }, [displayFields, filteredRows, viewSettings]);
14219
- const allFieldOptions = React5.useMemo(() => {
14395
+ const allFieldOptions = React6.useMemo(() => {
14220
14396
  return relatedModel.fields.map((field) => ({ label: field.label, value: field.key }));
14221
14397
  }, [relatedModel.fields]);
14222
- const orderedSelectedColumns = React5.useMemo(() => {
14398
+ const orderedSelectedColumns = React6.useMemo(() => {
14223
14399
  if (!selectedColumnKeys || selectedColumnKeys.length === 0) return [];
14224
14400
  return orderedColumnKeys && orderedColumnKeys.length > 0 ? orderedColumnKeys : selectedColumnKeys;
14225
14401
  }, [orderedColumnKeys, selectedColumnKeys]);
14226
- const syncColumnsSelectionToDisplay = React5.useCallback(() => {
14402
+ const syncColumnsSelectionToDisplay = React6.useCallback(() => {
14227
14403
  const keys = displayFields.map((field) => field.key);
14228
14404
  if (keys.length === 0) return;
14229
14405
  setSelectedColumnKeys(keys);
14230
14406
  setColumnOrder(columnOrder && columnOrder.length > 0 ? columnOrder : keys);
14231
14407
  }, [columnOrder, displayFields]);
14232
- React5.useEffect(() => {
14408
+ React6.useEffect(() => {
14233
14409
  if (selectedColumnKeys !== null) return;
14234
14410
  const defaults = defaultDisplayFields.map((field) => field.key);
14235
14411
  if (defaults.length === 0) return;
14236
14412
  setSelectedColumnKeys(defaults);
14237
14413
  setColumnOrder(defaults);
14238
14414
  }, [defaultDisplayFields, selectedColumnKeys]);
14239
- const handleColumnSelectionChange = React5.useCallback((values) => {
14415
+ const handleColumnSelectionChange = React6.useCallback((values) => {
14240
14416
  markLayoutPrefsTouched();
14241
14417
  if (!values || values.length === 0) {
14242
14418
  setSelectedColumnKeys(null);
@@ -14250,7 +14426,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14250
14426
  return [...baseOrder, ...missing];
14251
14427
  });
14252
14428
  }, [markLayoutPrefsTouched]);
14253
- const moveColumnOrder = React5.useCallback((key, direction) => {
14429
+ const moveColumnOrder = React6.useCallback((key, direction) => {
14254
14430
  setColumnOrder((prev) => {
14255
14431
  const base = prev && prev.length > 0 ? [...prev] : selectedColumnKeys ? [...selectedColumnKeys] : [];
14256
14432
  const index = base.indexOf(key);
@@ -14261,18 +14437,18 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14261
14437
  return base;
14262
14438
  });
14263
14439
  }, [selectedColumnKeys]);
14264
- const statsSummary = React5.useMemo(() => {
14440
+ const statsSummary = React6.useMemo(() => {
14265
14441
  return buildStatsSummary(columnFilteredRows, displayFields, labelCache);
14266
14442
  }, [columnFilteredRows, displayFields, labelCache]);
14267
14443
  const isTotalsDetailsVariant = viewVariant === "totals-details";
14268
- const getDefaultTotalsSummaryFn = React5.useCallback((field) => {
14444
+ const getDefaultTotalsSummaryFn = React6.useCallback((field) => {
14269
14445
  if (isPkField(field, relatedModel)) return "count";
14270
14446
  return "sum";
14271
14447
  }, [relatedModel]);
14272
- const resolveTotalsSummaryFn = React5.useCallback((field) => {
14448
+ const resolveTotalsSummaryFn = React6.useCallback((field) => {
14273
14449
  return totalsSummaryFunctions[field.key] || getDefaultTotalsSummaryFn(field);
14274
14450
  }, [getDefaultTotalsSummaryFn, totalsSummaryFunctions]);
14275
- const computeTotalsSummaryValue = React5.useCallback((field) => {
14451
+ const computeTotalsSummaryValue = React6.useCallback((field) => {
14276
14452
  const fn = resolveTotalsSummaryFn(field);
14277
14453
  const rawValues = filteredRows.map((row) => row?.[field.key]);
14278
14454
  if (field.type === "number" && !field.reference) {
@@ -14295,7 +14471,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14295
14471
  }
14296
14472
  return rawValues.length;
14297
14473
  }, [filteredRows, resolveTotalsSummaryFn]);
14298
- const formatCategoricalBoxValue = React5.useCallback((field, raw) => {
14474
+ const formatCategoricalBoxValue = React6.useCallback((field, raw) => {
14299
14475
  if (raw === void 0 || raw === null) return "-";
14300
14476
  if (field.reference) {
14301
14477
  const cacheKey = `${field.reference}:${raw}`;
@@ -14308,7 +14484,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14308
14484
  if (field.type === "date") return formatDateValue(raw);
14309
14485
  return String(raw);
14310
14486
  }, [labelCache]);
14311
- const totalsDetailsCategoricalBoxes = React5.useMemo(() => {
14487
+ const totalsDetailsCategoricalBoxes = React6.useMemo(() => {
14312
14488
  return displayFields.filter((field) => field.type !== "number" || Boolean(field.reference)).map((field) => {
14313
14489
  const counts = /* @__PURE__ */ new Map();
14314
14490
  filteredRows.forEach((row) => {
@@ -14326,7 +14502,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14326
14502
  };
14327
14503
  });
14328
14504
  }, [displayFields, filteredRows, formatCategoricalBoxValue]);
14329
- const totalsDetailsNumericBoxes = React5.useMemo(() => {
14505
+ const totalsDetailsNumericBoxes = React6.useMemo(() => {
14330
14506
  return displayFields.filter((field) => field.type === "number" && !field.reference).map((field) => {
14331
14507
  return {
14332
14508
  key: field.key,
@@ -14336,10 +14512,10 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14336
14512
  };
14337
14513
  });
14338
14514
  }, [computeTotalsSummaryValue, displayFields, resolveTotalsSummaryFn]);
14339
- const totalsSummaryConfigFields = React5.useMemo(() => {
14515
+ const totalsSummaryConfigFields = React6.useMemo(() => {
14340
14516
  return displayFields.filter((field) => field.type === "number" && !field.reference);
14341
14517
  }, [displayFields]);
14342
- React5.useEffect(() => {
14518
+ React6.useEffect(() => {
14343
14519
  setTotalsSummaryFunctions((prev) => {
14344
14520
  const next = { ...prev };
14345
14521
  let changed = false;
@@ -14352,7 +14528,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14352
14528
  return changed ? next : prev;
14353
14529
  });
14354
14530
  }, [getDefaultTotalsSummaryFn, totalsSummaryConfigFields]);
14355
- const statsNumericMaxes = React5.useMemo(() => {
14531
+ const statsNumericMaxes = React6.useMemo(() => {
14356
14532
  const stats = statsSummary.numericStats;
14357
14533
  const maxAbs = (values) => {
14358
14534
  const absValues = values.filter((val) => typeof val === "number").map((val) => Math.abs(val));
@@ -14366,7 +14542,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
14366
14542
  stddev: maxAbs(stats.map((row) => row.stddev))
14367
14543
  };
14368
14544
  }, [statsSummary.numericStats]);
14369
- React5.useEffect(() => {
14545
+ React6.useEffect(() => {
14370
14546
  if (isTotalsDetailsVariant) {
14371
14547
  setIsTotalsDetailsFlipped(false);
14372
14548
  }
@@ -15413,7 +15589,8 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
15413
15589
  { label: _34("Heatmap"), value: "heatmap" },
15414
15590
  { label: _34("Crosstab"), value: "crosstab" },
15415
15591
  { label: _34("Radar"), value: "radar" },
15416
- { label: _34("Combo (Bar + Line)"), value: "combo" }
15592
+ { label: _34("Combo (Bar + Line)"), value: "combo" },
15593
+ { label: _34("3D Scatter"), value: "3d" }
15417
15594
  ]
15418
15595
  }
15419
15596
  )
@@ -15628,15 +15805,15 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
15628
15805
  };
15629
15806
  var RelatedObjectSingleSelect = ({ rel, record, allModels, required }) => {
15630
15807
  const apiUrl = core.useApiUrl();
15631
- const [currentLinkRow, setCurrentLinkRow] = React5.useState(null);
15632
- const [currentValue, setCurrentValue] = React5.useState(null);
15633
- const [loadingCurrent, setLoadingCurrent] = React5.useState(true);
15634
- const [saving, setSaving] = React5.useState(false);
15808
+ const [currentLinkRow, setCurrentLinkRow] = React6.useState(null);
15809
+ const [currentValue, setCurrentValue] = React6.useState(null);
15810
+ const [loadingCurrent, setLoadingCurrent] = React6.useState(true);
15811
+ const [saving, setSaving] = React6.useState(false);
15635
15812
  const relatedResource = rel.otherResourcePath || resolveResourcePath(rel.otherResource || "", allModels);
15636
15813
  const linkResource = rel.resourcePath || resolveResourcePath(rel.resource, allModels);
15637
15814
  const relatedModel = allModels?.find((m) => m.name === rel.otherResource);
15638
15815
  const relatedPkField = relatedModel?.fields.find((f) => f.isPk)?.key ?? "id";
15639
- React5.useEffect(() => {
15816
+ React6.useEffect(() => {
15640
15817
  const recordId = getRecordId(record);
15641
15818
  if (!recordId || !rel.targetKey || !rel.otherKey) {
15642
15819
  setLoadingCurrent(false);
@@ -15678,7 +15855,7 @@ var RelatedObjectSingleSelect = ({ rel, record, allModels, required }) => {
15678
15855
  filters: [],
15679
15856
  pagination: { current: 1, pageSize: 2e3, mode: "server" }
15680
15857
  });
15681
- const handleChange = React5.useCallback(async (newValue) => {
15858
+ const handleChange = React6.useCallback(async (newValue) => {
15682
15859
  const recordId = getRecordId(record);
15683
15860
  if (!recordId || !rel.otherKey) return;
15684
15861
  setSaving(true);
@@ -15734,11 +15911,11 @@ function useMillerColumnItems({
15734
15911
  allModels,
15735
15912
  apiUrl
15736
15913
  }) {
15737
- const [branches, setBranches] = React5.useState([]);
15738
- const [leaves, setLeaves] = React5.useState([]);
15739
- const [loading, setLoading] = React5.useState(false);
15740
- const [error, setError] = React5.useState(null);
15741
- React5.useEffect(() => {
15914
+ const [branches, setBranches] = React6.useState([]);
15915
+ const [leaves, setLeaves] = React6.useState([]);
15916
+ const [loading, setLoading] = React6.useState(false);
15917
+ const [error, setError] = React6.useState(null);
15918
+ React6.useEffect(() => {
15742
15919
  if (!parentId || !rel.resourcePath || !rel.targetKey || !rel.otherKey || !rel.otherResource) {
15743
15920
  setBranches([]);
15744
15921
  setLeaves([]);
@@ -16003,16 +16180,16 @@ var MillerBrowserLayout = ({
16003
16180
  const screens = antd.Grid.useBreakpoint();
16004
16181
  const { token } = antd.theme.useToken();
16005
16182
  const isDesktop = !!screens.md;
16006
- const columnsRef = React5.useRef(null);
16183
+ const columnsRef = React6.useRef(null);
16007
16184
  const rootId = record?.eid ?? record?.id;
16008
- const [columns, setColumns] = React5.useState([{ parentId: rootId }]);
16009
- const [selectedIds, setSelectedIds] = React5.useState([null]);
16010
- const [detailNode, setDetailNode] = React5.useState(null);
16011
- const [drawerOpen, setDrawerOpen] = React5.useState(false);
16012
- const [containerHeight, setContainerHeight] = React5.useState(INITIAL_HEIGHT);
16013
- const [columnsWidth, setColumnsWidth] = React5.useState(null);
16014
- const [columnWidths, setColumnWidths] = React5.useState([]);
16015
- const [draggingDir, setDraggingDir] = React5.useState(null);
16185
+ const [columns, setColumns] = React6.useState([{ parentId: rootId }]);
16186
+ const [selectedIds, setSelectedIds] = React6.useState([null]);
16187
+ const [detailNode, setDetailNode] = React6.useState(null);
16188
+ const [drawerOpen, setDrawerOpen] = React6.useState(false);
16189
+ const [containerHeight, setContainerHeight] = React6.useState(INITIAL_HEIGHT);
16190
+ const [columnsWidth, setColumnsWidth] = React6.useState(null);
16191
+ const [columnWidths, setColumnWidths] = React6.useState([]);
16192
+ const [draggingDir, setDraggingDir] = React6.useState(null);
16016
16193
  const DEFAULT_COL_WIDTH = 240;
16017
16194
  const getColWidth = (i) => columnWidths[i] ?? DEFAULT_COL_WIDTH;
16018
16195
  const handleResizeV = (e) => {
@@ -16494,7 +16671,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16494
16671
  const canBulkEdit = canEditData?.can !== false;
16495
16672
  const { settings: viewSettings } = useViewSettings();
16496
16673
  viewSettings?.generalActionsButtonPosition || "top-right";
16497
- const [actionsBarEl, setActionsBarEl] = React5.useState(null);
16674
+ const [actionsBarEl, setActionsBarEl] = React6.useState(null);
16498
16675
  const resolvedLayoutPreferenceType = layoutPreferenceType ?? "ShowLayout";
16499
16676
  const [searchParams] = reactRouterDom.useSearchParams();
16500
16677
  const selectMode = searchParams.get("select_mode") === "1";
@@ -16504,7 +16681,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16504
16681
  const selectModeRelateOtherKey = searchParams.get("relate_other_key");
16505
16682
  const selectModeRelateTargetId = searchParams.get("relate_target_id");
16506
16683
  const selectModeReturnTo = searchParams.get("returnTo");
16507
- useKeyboardShortcuts(React5.useMemo(() => isEmbedded ? [] : [
16684
+ useKeyboardShortcuts(React6.useMemo(() => isEmbedded ? [] : [
16508
16685
  { key: "n", ctrl: true, handler: () => go({ to: { resource: model.resource || model.name, action: "create" } }) }
16509
16686
  ], [model.name, model.resource, go, isEmbedded]));
16510
16687
  const { token } = antd.theme.useToken();
@@ -16538,89 +16715,89 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16538
16715
  const editableCrosstab = resolvedListViewType === "editable-crosstab" || resolvedListViewType === "editablecrosstab";
16539
16716
  const galleryImageWidth = viewSettings?.galleryImageWidth ?? 180;
16540
16717
  const galleryImageHeight = viewSettings?.galleryImageHeight ?? 140;
16541
- const calendarDateFieldOptions = React5.useMemo(() => getCalendarDateFieldOptions(model.fields), [model.fields]);
16542
- const [localSearch, setLocalSearch] = React5.useState("");
16543
- const [listVisible, setListVisible] = React5.useState(defaultListVisible ?? true);
16544
- const [isTdFlipped, setIsTdFlipped] = React5.useState(false);
16545
- const [pageSize, setPageSize] = React5.useState(10);
16546
- const [galleryPage, setGalleryPage] = React5.useState(1);
16547
- const [calendarMode, setCalendarMode] = React5.useState("month");
16548
- const [calendarDateField, setCalendarDateField] = React5.useState(() => calendarDateFieldOptions[0]?.key || "");
16549
- const [calendarAnchorDate, setCalendarAnchorDate] = React5.useState(() => dayjs9__default.default().startOf("month"));
16550
- const [isAnalyzeVertical, setIsAnalyzeVertical] = React5.useState(false);
16551
- const [isAnalyzeFirst, setIsAnalyzeFirst] = React5.useState(false);
16552
- const [filterRules, setFilterRules] = React5.useState([]);
16553
- const [filtersCollapsed, setFiltersCollapsed] = React5.useState(isEmbedded);
16554
- const [layoutPrefsReady, setLayoutPrefsReady] = React5.useState(false);
16555
- const [columnsSelectorOpen, setColumnsSelectorOpen] = React5.useState(false);
16556
- const [selectedColumnKeys, setSelectedColumnKeys] = React5.useState(null);
16557
- const [columnOrder, setColumnOrder] = React5.useState(null);
16558
- const [columnFiltersSelected, setColumnFiltersSelected] = React5.useState({});
16559
- const [columnSort, setColumnSort] = React5.useState(
16718
+ const calendarDateFieldOptions = React6.useMemo(() => getCalendarDateFieldOptions(model.fields), [model.fields]);
16719
+ const [localSearch, setLocalSearch] = React6.useState("");
16720
+ const [listVisible, setListVisible] = React6.useState(defaultListVisible ?? true);
16721
+ const [isTdFlipped, setIsTdFlipped] = React6.useState(false);
16722
+ const [pageSize, setPageSize] = React6.useState(10);
16723
+ const [galleryPage, setGalleryPage] = React6.useState(1);
16724
+ const [calendarMode, setCalendarMode] = React6.useState("month");
16725
+ const [calendarDateField, setCalendarDateField] = React6.useState(() => calendarDateFieldOptions[0]?.key || "");
16726
+ const [calendarAnchorDate, setCalendarAnchorDate] = React6.useState(() => dayjs9__default.default().startOf("month"));
16727
+ const [isAnalyzeVertical, setIsAnalyzeVertical] = React6.useState(false);
16728
+ const [isAnalyzeFirst, setIsAnalyzeFirst] = React6.useState(false);
16729
+ const [filterRules, setFilterRules] = React6.useState([]);
16730
+ const [filtersCollapsed, setFiltersCollapsed] = React6.useState(isEmbedded);
16731
+ const [layoutPrefsReady, setLayoutPrefsReady] = React6.useState(false);
16732
+ const [columnsSelectorOpen, setColumnsSelectorOpen] = React6.useState(false);
16733
+ const [selectedColumnKeys, setSelectedColumnKeys] = React6.useState(null);
16734
+ const [columnOrder, setColumnOrder] = React6.useState(null);
16735
+ const [columnFiltersSelected, setColumnFiltersSelected] = React6.useState({});
16736
+ const [columnSort, setColumnSort] = React6.useState(
16560
16737
  model.defaultSort ? [{ fieldKey: model.defaultSort.field, order: model.defaultSort.order === "desc" ? "descend" : "ascend" }] : []
16561
16738
  );
16562
- const [totalsSummaryFunctions, setTotalsSummaryFunctions] = React5.useState({});
16563
- const [currentViewName, setCurrentViewName] = React5.useState(getDefaultViewName());
16564
- const [selectedViewNames, setSelectedViewNames] = React5.useState([]);
16565
- const [availableViewNames, setAvailableViewNames] = React5.useState([]);
16566
- const [viewNamesLoaded, setViewNamesLoaded] = React5.useState(false);
16567
- const [isLoadingViewNames, setIsLoadingViewNames] = React5.useState(false);
16568
- const [saveViewModalOpen, setSaveViewModalOpen] = React5.useState(false);
16569
- const [saveViewName, setSaveViewName] = React5.useState(getDefaultViewName());
16570
- const [saveViewAsNew, setSaveViewAsNew] = React5.useState(false);
16571
- const [pendingSaveTarget, setPendingSaveTarget] = React5.useState(null);
16572
- const [renameViewModalOpen, setRenameViewModalOpen] = React5.useState(false);
16573
- const [renameViewName, setRenameViewName] = React5.useState("");
16574
- const [labelCache, setLabelCache] = React5.useState({});
16575
- const [analyzeOpen, setAnalyzeOpen] = React5.useState(isEmbedded);
16576
- const analyzeTouchedRef = React5.useRef(false);
16577
- const analyzePrefsTouchedRef = React5.useRef(false);
16578
- const analyzePrefsLoadedRef = React5.useRef(false);
16579
- const [analyzePrefsReady, setAnalyzePrefsReady] = React5.useState(false);
16580
- const analyzePrefsResourceRef = React5.useRef(null);
16739
+ const [totalsSummaryFunctions, setTotalsSummaryFunctions] = React6.useState({});
16740
+ const [currentViewName, setCurrentViewName] = React6.useState(getDefaultViewName());
16741
+ const [selectedViewNames, setSelectedViewNames] = React6.useState([]);
16742
+ const [availableViewNames, setAvailableViewNames] = React6.useState([]);
16743
+ const [viewNamesLoaded, setViewNamesLoaded] = React6.useState(false);
16744
+ const [isLoadingViewNames, setIsLoadingViewNames] = React6.useState(false);
16745
+ const [saveViewModalOpen, setSaveViewModalOpen] = React6.useState(false);
16746
+ const [saveViewName, setSaveViewName] = React6.useState(getDefaultViewName());
16747
+ const [saveViewAsNew, setSaveViewAsNew] = React6.useState(false);
16748
+ const [pendingSaveTarget, setPendingSaveTarget] = React6.useState(null);
16749
+ const [renameViewModalOpen, setRenameViewModalOpen] = React6.useState(false);
16750
+ const [renameViewName, setRenameViewName] = React6.useState("");
16751
+ const [labelCache, setLabelCache] = React6.useState({});
16752
+ const [analyzeOpen, setAnalyzeOpen] = React6.useState(isEmbedded);
16753
+ const analyzeTouchedRef = React6.useRef(false);
16754
+ const analyzePrefsTouchedRef = React6.useRef(false);
16755
+ const analyzePrefsLoadedRef = React6.useRef(false);
16756
+ const [analyzePrefsReady, setAnalyzePrefsReady] = React6.useState(false);
16757
+ const analyzePrefsResourceRef = React6.useRef(null);
16581
16758
  const { metadataButton, metadataModal } = useMetadataModal(model, allModels);
16582
- const defaultDisplayFields = React5.useMemo(() => getListViewFields(model, filter?.field), [model, filter?.field]);
16583
- const orderedColumnKeys = React5.useMemo(() => {
16759
+ const defaultDisplayFields = React6.useMemo(() => getListViewFields(model, filter?.field), [model, filter?.field]);
16760
+ const orderedColumnKeys = React6.useMemo(() => {
16584
16761
  if (!selectedColumnKeys || selectedColumnKeys.length === 0) return null;
16585
16762
  const order = columnOrder && columnOrder.length > 0 ? columnOrder : selectedColumnKeys;
16586
16763
  const selectedSet = new Set(selectedColumnKeys);
16587
16764
  const availableKeys = new Set(model.fields.map((field) => field.key));
16588
16765
  return order.filter((key) => selectedSet.has(key) && availableKeys.has(key));
16589
16766
  }, [columnOrder, model.fields, selectedColumnKeys]);
16590
- const displayFields = React5.useMemo(() => {
16767
+ const displayFields = React6.useMemo(() => {
16591
16768
  if (!orderedColumnKeys) return defaultDisplayFields;
16592
16769
  const fieldMap = new Map(model.fields.map((field) => [field.key, field]));
16593
16770
  return orderedColumnKeys.map((key) => fieldMap.get(key)).filter((field) => Boolean(field));
16594
16771
  }, [defaultDisplayFields, model.fields, orderedColumnKeys]);
16595
16772
  const useLocalSearch = true;
16596
- const [categoryField1, setCategoryField1] = React5.useState(null);
16597
- const [categoryField2, setCategoryField2] = React5.useState(void 0);
16598
- const [crosstabFilterFields, setCrosstabFilterFields] = React5.useState([]);
16599
- const [crosstabStaged, setCrosstabStaged] = React5.useState({});
16600
- const [crosstabSaving, setCrosstabSaving] = React5.useState(false);
16601
- const [chartType, setChartType] = React5.useState("area");
16602
- const [summaryFn, setSummaryFn] = React5.useState("sum");
16603
- const [selectedSeriesKeys, setSelectedSeriesKeys] = React5.useState(null);
16604
- const [rankingMode, setRankingMode] = React5.useState("none");
16605
- const [rankingFieldKey, setRankingFieldKey] = React5.useState(null);
16606
- const [rankingN, setRankingN] = React5.useState(10);
16607
- const [exportRequested, setExportRequested] = React5.useState(false);
16608
- const [isStatsFlipped, setIsStatsFlipped] = React5.useState(false);
16609
- const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] = React5.useState(false);
16610
- const chartSvgRef = React5.useRef(null);
16611
- const [chartAnimationKey, setChartAnimationKey] = React5.useState(0);
16612
- const [chartAnimationStage, setChartAnimationStage] = React5.useState("enter");
16613
- const skipNextAnimationRef = React5.useRef(false);
16614
- const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] = React5.useState(false);
16615
- const layoutPrefsTouchedRef = React5.useRef(false);
16616
- const layoutPrefsLoadedRef = React5.useRef(false);
16617
- const layoutPrefsResourceRef = React5.useRef(null);
16618
- const sortIntentRef = React5.useRef(null);
16619
- const prevViewNameForResetRef = React5.useRef(null);
16620
- const [bulkSelectedRowKeys, setBulkSelectedRowKeys] = React5.useState([]);
16621
- const bulkSelectedRowsMapRef = React5.useRef(/* @__PURE__ */ new Map());
16622
- const [selectModeAssociating, setSelectModeAssociating] = React5.useState(false);
16623
- const handleAssociateSelected = React5.useCallback(async () => {
16773
+ const [categoryField1, setCategoryField1] = React6.useState(null);
16774
+ const [categoryField2, setCategoryField2] = React6.useState(void 0);
16775
+ const [crosstabFilterFields, setCrosstabFilterFields] = React6.useState([]);
16776
+ const [crosstabStaged, setCrosstabStaged] = React6.useState({});
16777
+ const [crosstabSaving, setCrosstabSaving] = React6.useState(false);
16778
+ const [chartType, setChartType] = React6.useState("area");
16779
+ const [summaryFn, setSummaryFn] = React6.useState("sum");
16780
+ const [selectedSeriesKeys, setSelectedSeriesKeys] = React6.useState(null);
16781
+ const [rankingMode, setRankingMode] = React6.useState("none");
16782
+ const [rankingFieldKey, setRankingFieldKey] = React6.useState(null);
16783
+ const [rankingN, setRankingN] = React6.useState(10);
16784
+ const [exportRequested, setExportRequested] = React6.useState(false);
16785
+ const [isStatsFlipped, setIsStatsFlipped] = React6.useState(false);
16786
+ const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] = React6.useState(false);
16787
+ const chartSvgRef = React6.useRef(null);
16788
+ const [chartAnimationKey, setChartAnimationKey] = React6.useState(0);
16789
+ const [chartAnimationStage, setChartAnimationStage] = React6.useState("enter");
16790
+ const skipNextAnimationRef = React6.useRef(false);
16791
+ const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] = React6.useState(false);
16792
+ const layoutPrefsTouchedRef = React6.useRef(false);
16793
+ const layoutPrefsLoadedRef = React6.useRef(false);
16794
+ const layoutPrefsResourceRef = React6.useRef(null);
16795
+ const sortIntentRef = React6.useRef(null);
16796
+ const prevViewNameForResetRef = React6.useRef(null);
16797
+ const [bulkSelectedRowKeys, setBulkSelectedRowKeys] = React6.useState([]);
16798
+ const bulkSelectedRowsMapRef = React6.useRef(/* @__PURE__ */ new Map());
16799
+ const [selectModeAssociating, setSelectModeAssociating] = React6.useState(false);
16800
+ const handleAssociateSelected = React6.useCallback(async () => {
16624
16801
  if (!selectModeRelateResource || !selectModeRelateTargetKey || !selectModeRelateTargetId) return;
16625
16802
  if (!selectModeFk && !selectModeRelateOtherKey) return;
16626
16803
  setSelectModeAssociating(true);
@@ -16655,18 +16832,18 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16655
16832
  setSelectModeAssociating(false);
16656
16833
  }
16657
16834
  }, [apiUrl, bulkSelectedRowKeys, selectModeFk, selectModeRelateResource, selectModeRelateTargetKey, selectModeRelateOtherKey, selectModeRelateTargetId, selectModeReturnTo, navigate]);
16658
- const [bulkActionModalOpen, setBulkActionModalOpen] = React5.useState(false);
16659
- const [bulkActionsToApply, setBulkActionsToApply] = React5.useState([]);
16660
- const [bulkChangeFieldKey, setBulkChangeFieldKey] = React5.useState(null);
16661
- const [bulkChangeFieldValue, setBulkChangeFieldValue] = React5.useState(null);
16662
- const [isBulkExecuting, setIsBulkExecuting] = React5.useState(false);
16663
- const [selectAllFilteredPending, setSelectAllFilteredPending] = React5.useState(false);
16664
- const [columnFilterDropdownEverOpened, setColumnFilterDropdownEverOpened] = React5.useState(false);
16665
- const handleReferenceLabel = React5.useCallback((resource, id, label) => {
16835
+ const [bulkActionModalOpen, setBulkActionModalOpen] = React6.useState(false);
16836
+ const [bulkActionsToApply, setBulkActionsToApply] = React6.useState([]);
16837
+ const [bulkChangeFieldKey, setBulkChangeFieldKey] = React6.useState(null);
16838
+ const [bulkChangeFieldValue, setBulkChangeFieldValue] = React6.useState(null);
16839
+ const [isBulkExecuting, setIsBulkExecuting] = React6.useState(false);
16840
+ const [selectAllFilteredPending, setSelectAllFilteredPending] = React6.useState(false);
16841
+ const [columnFilterDropdownEverOpened, setColumnFilterDropdownEverOpened] = React6.useState(false);
16842
+ const handleReferenceLabel = React6.useCallback((resource, id, label) => {
16666
16843
  const key = `${resource}:${id}`;
16667
16844
  setLabelCache((prev) => prev[key] === label ? prev : { ...prev, [key]: label });
16668
16845
  }, []);
16669
- const tableFilters = React5.useMemo(() => {
16846
+ const tableFilters = React6.useMemo(() => {
16670
16847
  if (!filter) return [];
16671
16848
  if (filter.value === void 0 || filter.value === null) return [];
16672
16849
  return [filter];
@@ -16688,19 +16865,19 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16688
16865
  if (["true", "1", "t", "yes", "y"].includes(normalized)) value = true;
16689
16866
  if (["false", "0", "f", "no", "n"].includes(normalized)) value = false;
16690
16867
  }
16691
- return [{ field: searchField.key, operator: "eq", value }];
16868
+ return [{ field: searchField.key, operator: "contains", value }];
16692
16869
  }
16693
16870
  });
16694
- const [allRowsData, setAllRowsData] = React5.useState([]);
16695
- const [isAllRowsLoading, setIsAllRowsLoading] = React5.useState(false);
16696
- const [allRowsError, setAllRowsError] = React5.useState(null);
16697
- const lastAllRowsSignature = React5.useRef("");
16698
- const [allRowsLoaded, setAllRowsLoaded] = React5.useState(false);
16871
+ const [allRowsData, setAllRowsData] = React6.useState([]);
16872
+ const [isAllRowsLoading, setIsAllRowsLoading] = React6.useState(false);
16873
+ const [allRowsError, setAllRowsError] = React6.useState(null);
16874
+ const lastAllRowsSignature = React6.useRef("");
16875
+ const [allRowsLoaded, setAllRowsLoaded] = React6.useState(false);
16699
16876
  const isRelationView = !!filter;
16700
- const hasActiveFilterRules = React5.useMemo(() => {
16877
+ const hasActiveFilterRules = React6.useMemo(() => {
16701
16878
  return filterRules.some((rule) => rule.fieldKey && rule.operator && (rule.value !== void 0 && rule.value !== null && rule.value !== ""));
16702
16879
  }, [filterRules]);
16703
- const getFieldValueForFilter = React5.useCallback((field, record) => {
16880
+ const getFieldValueForFilter = React6.useCallback((field, record) => {
16704
16881
  const raw = record?.[field.key];
16705
16882
  if (raw === void 0 || raw === null) return raw;
16706
16883
  if (field.reference) {
@@ -16712,7 +16889,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16712
16889
  }
16713
16890
  return raw;
16714
16891
  }, [labelCache]);
16715
- const getSortValue = React5.useCallback((field, record) => {
16892
+ const getSortValue = React6.useCallback((field, record) => {
16716
16893
  const raw = record?.[field.key];
16717
16894
  if (raw === void 0 || raw === null) return null;
16718
16895
  if (isPkField(field, model) && record?._label) return record._label;
@@ -16734,7 +16911,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16734
16911
  if (field.type === "boolean") return raw ? 1 : 0;
16735
16912
  return raw;
16736
16913
  }, [labelCache]);
16737
- const compareSortValues = React5.useCallback((field, a, b) => {
16914
+ const compareSortValues = React6.useCallback((field, a, b) => {
16738
16915
  const aVal = getSortValue(field, a);
16739
16916
  const bVal = getSortValue(field, b);
16740
16917
  if (aVal === null && bVal === null) return 0;
@@ -16743,7 +16920,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16743
16920
  if (typeof aVal === "number" && typeof bVal === "number") return aVal - bVal;
16744
16921
  return String(aVal).localeCompare(String(bVal));
16745
16922
  }, [getSortValue]);
16746
- const resolveRelativeDate = React5.useCallback((value, asRange) => {
16923
+ const resolveRelativeDate = React6.useCallback((value, asRange) => {
16747
16924
  const count = Number(value?.count ?? 1);
16748
16925
  const direction = value?.direction || "next";
16749
16926
  const unit = value?.unit || "weeks";
@@ -16769,7 +16946,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16769
16946
  }
16770
16947
  return { date: target.startOf(unit) };
16771
16948
  }, []);
16772
- const matchesRule = React5.useCallback((record, rule) => {
16949
+ const matchesRule = React6.useCallback((record, rule) => {
16773
16950
  const field = model.fields.find((f) => f.key === rule.fieldKey);
16774
16951
  if (!field || !rule.operator) return true;
16775
16952
  const rawValue = getFieldValueForFilter(field, record);
@@ -16849,7 +17026,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16849
17026
  }
16850
17027
  return true;
16851
17028
  }, [getFieldValueForFilter, model.fields, resolveRelativeDate]);
16852
- const applyGlobalSearch = React5.useCallback((rows) => {
17029
+ const applyGlobalSearch = React6.useCallback((rows) => {
16853
17030
  const query = localSearch.trim().toLowerCase();
16854
17031
  if (!query) return rows;
16855
17032
  return rows.filter((record) => {
@@ -16868,11 +17045,11 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16868
17045
  return candidates.some((value) => value !== void 0 && value !== null && String(value).toLowerCase().includes(query));
16869
17046
  });
16870
17047
  }, [labelCache, localSearch, model.fields, useLocalSearch]);
16871
- const applyFilterRules = React5.useCallback((rows) => {
17048
+ const applyFilterRules = React6.useCallback((rows) => {
16872
17049
  if (!hasActiveFilterRules) return rows;
16873
17050
  return rows.filter((record) => filterRules.every((rule) => matchesRule(record, rule)));
16874
17051
  }, [filterRules, hasActiveFilterRules, matchesRule]);
16875
- const allRows = React5.useMemo(() => {
17052
+ const allRows = React6.useMemo(() => {
16876
17053
  const data = allRowsData || [];
16877
17054
  const query = localSearch.trim().toLowerCase();
16878
17055
  if (!query) return data;
@@ -16893,12 +17070,12 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16893
17070
  });
16894
17071
  }, [allRowsData, useLocalSearch, localSearch, model.fields, labelCache]);
16895
17072
  const isClientFiltering = allRowsLoaded && !allRowsError;
16896
- const filteredDataSource = React5.useMemo(() => {
17073
+ const filteredDataSource = React6.useMemo(() => {
16897
17074
  if (!isClientFiltering) return Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
16898
17075
  const baseRows = allRows || [];
16899
17076
  return applyFilterRules(applyGlobalSearch(baseRows));
16900
17077
  }, [allRows, applyFilterRules, applyGlobalSearch, isClientFiltering, tableProps.dataSource]);
16901
- const columnFilteredDataSource = React5.useMemo(() => {
17078
+ const columnFilteredDataSource = React6.useMemo(() => {
16902
17079
  const activeEntries = Object.entries(columnFiltersSelected).filter(([, values]) => values && values.length > 0);
16903
17080
  if (activeEntries.length === 0) return filteredDataSource;
16904
17081
  return filteredDataSource.filter(
@@ -16909,41 +17086,41 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16909
17086
  })
16910
17087
  );
16911
17088
  }, [filteredDataSource, columnFiltersSelected, model.fields]);
16912
- React5.useEffect(() => {
17089
+ React6.useEffect(() => {
16913
17090
  setGalleryPage(1);
16914
17091
  }, [localSearch, filterRules, resolvedListViewType]);
16915
- const columnFilters = React5.useMemo(() => {
17092
+ const columnFilters = React6.useMemo(() => {
16916
17093
  const data = allRowsData.length > 0 ? allRowsData : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
16917
17094
  const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
16918
17095
  return buildColumnFilterOptions({ fields: displayFields, data, rangeCount });
16919
17096
  }, [allRowsData, displayFields, tableProps.dataSource, viewSettings]);
16920
- const allFieldOptions = React5.useMemo(() => {
17097
+ const allFieldOptions = React6.useMemo(() => {
16921
17098
  return model.fields.map((field) => ({ label: field.label, value: field.key }));
16922
17099
  }, [model.fields]);
16923
- const orderedSelectedColumns = React5.useMemo(() => {
17100
+ const orderedSelectedColumns = React6.useMemo(() => {
16924
17101
  if (!selectedColumnKeys || selectedColumnKeys.length === 0) return [];
16925
17102
  return orderedColumnKeys && orderedColumnKeys.length > 0 ? orderedColumnKeys : selectedColumnKeys;
16926
17103
  }, [orderedColumnKeys, selectedColumnKeys]);
16927
- const syncColumnsSelectionToDisplay = React5.useCallback(() => {
17104
+ const syncColumnsSelectionToDisplay = React6.useCallback(() => {
16928
17105
  const keys = displayFields.map((field) => field.key);
16929
17106
  if (keys.length === 0) return;
16930
17107
  setSelectedColumnKeys(keys);
16931
17108
  setColumnOrder(orderedColumnKeys && orderedColumnKeys.length > 0 ? orderedColumnKeys : keys);
16932
17109
  }, [displayFields, orderedColumnKeys]);
16933
- React5.useEffect(() => {
17110
+ React6.useEffect(() => {
16934
17111
  if (selectedColumnKeys !== null) return;
16935
17112
  const defaults = defaultDisplayFields.map((field) => field.key);
16936
17113
  if (defaults.length === 0) return;
16937
17114
  setSelectedColumnKeys(defaults);
16938
17115
  setColumnOrder(defaults);
16939
17116
  }, [defaultDisplayFields, selectedColumnKeys]);
16940
- const markAnalyzePrefsTouched = React5.useCallback(() => {
17117
+ const markAnalyzePrefsTouched = React6.useCallback(() => {
16941
17118
  analyzePrefsTouchedRef.current = true;
16942
17119
  }, []);
16943
- const markLayoutPrefsTouched = React5.useCallback(() => {
17120
+ const markLayoutPrefsTouched = React6.useCallback(() => {
16944
17121
  layoutPrefsTouchedRef.current = true;
16945
17122
  }, []);
16946
- const handleColumnSelectionChange = React5.useCallback((values) => {
17123
+ const handleColumnSelectionChange = React6.useCallback((values) => {
16947
17124
  markLayoutPrefsTouched();
16948
17125
  if (!values || values.length === 0) {
16949
17126
  setSelectedColumnKeys(null);
@@ -16957,7 +17134,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16957
17134
  return [...baseOrder, ...missing];
16958
17135
  });
16959
17136
  }, [markLayoutPrefsTouched]);
16960
- const moveColumnOrder = React5.useCallback((key, direction) => {
17137
+ const moveColumnOrder = React6.useCallback((key, direction) => {
16961
17138
  setColumnOrder((prev) => {
16962
17139
  const base = prev && prev.length > 0 ? [...prev] : selectedColumnKeys ? [...selectedColumnKeys] : [];
16963
17140
  const index = base.indexOf(key);
@@ -16968,7 +17145,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16968
17145
  return base;
16969
17146
  });
16970
17147
  }, [selectedColumnKeys]);
16971
- const handleTablePageChange = React5.useCallback((page, newPageSize) => {
17148
+ const handleTablePageChange = React6.useCallback((page, newPageSize) => {
16972
17149
  if (newPageSize && newPageSize !== pageSize) {
16973
17150
  setPageSize(newPageSize);
16974
17151
  setGalleryPage(1);
@@ -16978,7 +17155,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16978
17155
  pagination.onChange(page, newPageSize ?? pageSize);
16979
17156
  }
16980
17157
  }, [pageSize, tableProps.pagination]);
16981
- const tablePagination = React5.useMemo(() => {
17158
+ const tablePagination = React6.useMemo(() => {
16982
17159
  if (!isClientFiltering) {
16983
17160
  if (!tableProps.pagination || typeof tableProps.pagination !== "object") return tableProps.pagination;
16984
17161
  return {
@@ -16999,23 +17176,23 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16999
17176
  onShowSizeChange: handleTablePageChange
17000
17177
  };
17001
17178
  }, [handleTablePageChange, isClientFiltering, pageSize, tableProps.pagination]);
17002
- const categoricalFields = React5.useMemo(() => {
17179
+ const categoricalFields = React6.useMemo(() => {
17003
17180
  return model.fields.filter((field) => isPkField(field, model) || (field.type !== "number" || field.reference));
17004
17181
  }, [model.fields]);
17005
- const numericFields = React5.useMemo(() => {
17182
+ const numericFields = React6.useMemo(() => {
17006
17183
  return model.fields.filter((field) => !isPkField(field, model) && field.type === "number" && !field.reference);
17007
17184
  }, [model.fields]);
17008
- const hasActiveRangeColumnFilter = React5.useMemo(() => {
17185
+ const hasActiveRangeColumnFilter = React6.useMemo(() => {
17009
17186
  return Object.values(columnFiltersSelected).some(
17010
17187
  (vals) => vals.some((v) => v.startsWith("__range__:"))
17011
17188
  );
17012
17189
  }, [columnFiltersSelected]);
17013
- const shouldLoadAllRows = React5.useMemo(() => {
17190
+ const shouldLoadAllRows = React6.useMemo(() => {
17014
17191
  return Boolean(
17015
17192
  localSearch.trim().length > 0 || hasActiveFilterRules || analyzeOpen || exportRequested || isTotalsDetailsView || isCrosstabView || columnFilterDropdownEverOpened || hasActiveRangeColumnFilter
17016
17193
  );
17017
17194
  }, [analyzeOpen, columnFilterDropdownEverOpened, exportRequested, hasActiveFilterRules, hasActiveRangeColumnFilter, isTotalsDetailsView, isCrosstabView, localSearch]);
17018
- React5.useEffect(() => {
17195
+ React6.useEffect(() => {
17019
17196
  if (!categoryField1 && categoricalFields.length > 0) {
17020
17197
  setCategoryField1(categoricalFields[0].key);
17021
17198
  }
@@ -17023,7 +17200,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17023
17200
  setCategoryField2(categoricalFields[1].key);
17024
17201
  }
17025
17202
  }, [categoricalFields, categoryField1, categoryField2]);
17026
- React5.useEffect(() => {
17203
+ React6.useEffect(() => {
17027
17204
  if (selectedSeriesKeys !== null) return;
17028
17205
  if (numericFields.length > 0) {
17029
17206
  setSelectedSeriesKeys(numericFields.map((field) => field.key));
@@ -17031,7 +17208,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17031
17208
  setSelectedSeriesKeys(["__count__"]);
17032
17209
  }
17033
17210
  }, [numericFields, selectedSeriesKeys]);
17034
- React5.useEffect(() => {
17211
+ React6.useEffect(() => {
17035
17212
  if (numericFields.length === 0) {
17036
17213
  if (rankingFieldKey !== null) setRankingFieldKey(null);
17037
17214
  if (rankingMode !== "none") setRankingMode("none");
@@ -17041,7 +17218,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17041
17218
  setRankingFieldKey(numericFields[0].key);
17042
17219
  }
17043
17220
  }, [numericFields, rankingFieldKey, rankingMode]);
17044
- const resetLayoutDefaults = React5.useCallback(() => {
17221
+ const resetLayoutDefaults = React6.useCallback(() => {
17045
17222
  setListVisible(defaultListVisible ?? true);
17046
17223
  setAnalyzeOpen(isEmbedded);
17047
17224
  setIsAnalyzeVertical(false);
@@ -17052,7 +17229,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17052
17229
  setColumnOrder(null);
17053
17230
  setTotalsSummaryFunctions({});
17054
17231
  }, [isEmbedded, defaultListVisible]);
17055
- const resetAnalyzeDefaults = React5.useCallback(() => {
17232
+ const resetAnalyzeDefaults = React6.useCallback(() => {
17056
17233
  setCategoryField1(categoricalFields[0]?.key ?? null);
17057
17234
  setCategoryField2(categoricalFields.length > 1 ? categoricalFields[1].key : null);
17058
17235
  setChartType("area");
@@ -17063,7 +17240,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17063
17240
  setRankingN(10);
17064
17241
  setCrosstabFilterFields([]);
17065
17242
  }, [categoricalFields, numericFields]);
17066
- const persistCurrentViewNames = React5.useCallback(async (nextSelected, nextCurrent) => {
17243
+ const persistCurrentViewNames = React6.useCallback(async (nextSelected, nextCurrent) => {
17067
17244
  try {
17068
17245
  const resourceKey = prefsKey;
17069
17246
  await authenticatedFetch(`${apiUrl}/views/preferences/view`, {
@@ -17079,7 +17256,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17079
17256
  } catch {
17080
17257
  }
17081
17258
  }, [apiUrl, model.name, model.resource, allModels, preferencesResourceOverride]);
17082
- const loadViewNames = React5.useCallback(async () => {
17259
+ const loadViewNames = React6.useCallback(async () => {
17083
17260
  const resourceKey = prefsKey;
17084
17261
  setIsLoadingViewNames(true);
17085
17262
  try {
@@ -17124,20 +17301,20 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17124
17301
  setIsLoadingViewNames(false);
17125
17302
  }
17126
17303
  }, [apiUrl, model.name, model.resource, allModels, preferencesResourceOverride]);
17127
- const openSaveViewModalFor = React5.useCallback((target) => {
17304
+ const openSaveViewModalFor = React6.useCallback((target) => {
17128
17305
  setSaveViewName(currentViewName || getDefaultViewName());
17129
17306
  setSaveViewAsNew(false);
17130
17307
  setPendingSaveTarget(target);
17131
17308
  setSaveViewModalOpen(true);
17132
17309
  }, [currentViewName]);
17133
- const handleChangeViewName = React5.useCallback(async (nextView) => {
17310
+ const handleChangeViewName = React6.useCallback(async (nextView) => {
17134
17311
  const resolvedName = normalizeViewName(nextView);
17135
17312
  setCurrentViewName(resolvedName);
17136
17313
  setSaveViewName(resolvedName);
17137
17314
  const nextSelected = selectedViewNames.length > 0 ? selectedViewNames : [resolvedName];
17138
17315
  await persistCurrentViewNames(nextSelected, resolvedName);
17139
17316
  }, [persistCurrentViewNames, selectedViewNames]);
17140
- const updateSelectedViewNames = React5.useCallback(async (nextSelected) => {
17317
+ const updateSelectedViewNames = React6.useCallback(async (nextSelected) => {
17141
17318
  if (nextSelected.length === 0) {
17142
17319
  nextSelected = [getDefaultViewName()];
17143
17320
  }
@@ -17149,7 +17326,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17149
17326
  }
17150
17327
  await persistCurrentViewNames(nextSelected, nextCurrent);
17151
17328
  }, [currentViewName, persistCurrentViewNames]);
17152
- const moveSelectedView = React5.useCallback((name, direction) => {
17329
+ const moveSelectedView = React6.useCallback((name, direction) => {
17153
17330
  setSelectedViewNames((prev) => {
17154
17331
  const idx = prev.indexOf(name);
17155
17332
  if (idx < 0) return prev;
@@ -17161,7 +17338,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17161
17338
  return next;
17162
17339
  });
17163
17340
  }, [currentViewName, persistCurrentViewNames]);
17164
- const handleRenameView = React5.useCallback(async () => {
17341
+ const handleRenameView = React6.useCallback(async () => {
17165
17342
  const newName = normalizeViewName(renameViewName);
17166
17343
  if (!newName || newName === currentViewName) {
17167
17344
  setRenameViewModalOpen(false);
@@ -17188,7 +17365,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17188
17365
  antd.message.error(error instanceof Error ? error.message : _36("Failed to rename view."));
17189
17366
  }
17190
17367
  }, [apiUrl, availableViewNames, currentViewName, model.name, model.resource, renameViewName, allModels, loadViewNames]);
17191
- const confirmDeleteView = React5.useCallback(() => {
17368
+ const confirmDeleteView = React6.useCallback(() => {
17192
17369
  antd.Modal.confirm({
17193
17370
  title: _36(_36("Delete view")),
17194
17371
  content: `Delete "${currentViewName}" and all its saved preferences?`,
@@ -17213,7 +17390,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17213
17390
  }
17214
17391
  });
17215
17392
  }, [apiUrl, currentViewName, model.name, model.resource, allModels, loadViewNames]);
17216
- const persistLayoutPreferences = React5.useCallback(async (viewName) => {
17393
+ const persistLayoutPreferences = React6.useCallback(async (viewName) => {
17217
17394
  if (!resolvedLayoutPreferenceType) return;
17218
17395
  const resourceKey = prefsKey;
17219
17396
  const resolvedViewName = normalizeViewName(viewName);
@@ -17257,7 +17434,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17257
17434
  setIsSavingLayoutPrefs(false);
17258
17435
  }
17259
17436
  }, [apiUrl, analyzeOpen, columnFiltersSelected, columnOrder, columnSort, filtersCollapsed, filterRules, isAnalyzeFirst, isAnalyzeVertical, resolvedLayoutPreferenceType, listVisible, pageSize, selectedColumnKeys, totalsSummaryFunctions, model.name, model.resource, allModels, preferencesResourceOverride]);
17260
- const persistAnalyzePreferences = React5.useCallback(async (viewName) => {
17437
+ const persistAnalyzePreferences = React6.useCallback(async (viewName) => {
17261
17438
  const resourceKey = prefsKey;
17262
17439
  const resolvedViewName = normalizeViewName(viewName);
17263
17440
  const preferences = {
@@ -17289,7 +17466,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17289
17466
  setIsSavingAnalyzePrefs(false);
17290
17467
  }
17291
17468
  }, [apiUrl, categoryField1, categoryField2, chartType, selectedSeriesKeys, summaryFn, rankingMode, rankingFieldKey, rankingN, crosstabFilterFields, model.name, model.resource, allModels, preferencesResourceOverride]);
17292
- const handleConfirmSaveView = React5.useCallback(async () => {
17469
+ const handleConfirmSaveView = React6.useCallback(async () => {
17293
17470
  if (!pendingSaveTarget) return;
17294
17471
  const viewName = normalizeViewName(saveViewName || currentViewName);
17295
17472
  const viewExists = availableViewNames.includes(viewName);
@@ -17316,10 +17493,10 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17316
17493
  await persistCurrentViewNames(nextSelected, viewName);
17317
17494
  await loadViewNames();
17318
17495
  }, [availableViewNames, currentViewName, loadViewNames, pendingSaveTarget, persistAnalyzePreferences, persistCurrentViewNames, persistLayoutPreferences, saveViewAsNew, saveViewName, selectedViewNames]);
17319
- React5.useEffect(() => {
17496
+ React6.useEffect(() => {
17320
17497
  loadViewNames();
17321
17498
  }, [loadViewNames]);
17322
- React5.useEffect(() => {
17499
+ React6.useEffect(() => {
17323
17500
  if (!viewNamesLoaded) return;
17324
17501
  const viewChanged = prevViewNameForResetRef.current !== null && prevViewNameForResetRef.current !== currentViewName;
17325
17502
  prevViewNameForResetRef.current = currentViewName;
@@ -17336,7 +17513,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17336
17513
  resetAnalyzeDefaults();
17337
17514
  }
17338
17515
  }, [currentViewName, resetAnalyzeDefaults, resetLayoutDefaults, viewNamesLoaded]);
17339
- React5.useEffect(() => {
17516
+ React6.useEffect(() => {
17340
17517
  const resourceKey = prefsKey;
17341
17518
  const viewKey = `${resourceKey}::${currentViewName}`;
17342
17519
  if (analyzePrefsResourceRef.current !== viewKey) {
@@ -17389,7 +17566,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17389
17566
  cancelled = true;
17390
17567
  };
17391
17568
  }, [apiUrl, currentViewName, model.name, model.resource, allModels, preferencesResourceOverride]);
17392
- React5.useEffect(() => {
17569
+ React6.useEffect(() => {
17393
17570
  if (!resolvedLayoutPreferenceType) return;
17394
17571
  const resourceKey = prefsKey;
17395
17572
  const viewKey = `${resourceKey}::${resolvedLayoutPreferenceType}::${currentViewName}`;
@@ -17474,7 +17651,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17474
17651
  cancelled = true;
17475
17652
  };
17476
17653
  }, [apiUrl, currentViewName, resolvedLayoutPreferenceType, model.name, model.resource, allModels, preferencesResourceOverride]);
17477
- const fetchAllRows = React5.useCallback(async () => {
17654
+ const fetchAllRows = React6.useCallback(async () => {
17478
17655
  setIsAllRowsLoading(true);
17479
17656
  setAllRowsError(null);
17480
17657
  const filtersToApply = activeFilters && activeFilters.length > 0 ? activeFilters : tableFilters;
@@ -17510,7 +17687,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17510
17687
  setAllRowsLoaded(true);
17511
17688
  }
17512
17689
  }, [activeFilters, apiUrl, model.name, model.resource, tableFilters, allModels]);
17513
- React5.useEffect(() => {
17690
+ React6.useEffect(() => {
17514
17691
  if (!shouldLoadAllRows) return;
17515
17692
  const filtersToApply = activeFilters && activeFilters.length > 0 ? activeFilters : tableFilters;
17516
17693
  const signature = JSON.stringify({
@@ -17525,7 +17702,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17525
17702
  lastAllRowsSignature.current = signature;
17526
17703
  fetchAllRows();
17527
17704
  }, [activeFilters, analyzeOpen, exportRequested, fetchAllRows, model.name, shouldLoadAllRows, tableFilters]);
17528
- React5.useEffect(() => {
17705
+ React6.useEffect(() => {
17529
17706
  if (!allRowsLoaded) return;
17530
17707
  if (analyzeTouchedRef.current) return;
17531
17708
  if (isTotalsDetailsView) return;
@@ -17535,7 +17712,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17535
17712
  setAnalyzeOpen(true);
17536
17713
  }
17537
17714
  }, [allRows?.length, allRowsLoaded, isTotalsDetailsView]);
17538
- React5.useEffect(() => {
17715
+ React6.useEffect(() => {
17539
17716
  if (!hasActiveFilterRules || isClientFiltering) return;
17540
17717
  const resolveServerDate = (val, forRange) => {
17541
17718
  if (val?.mode === "relative") {
@@ -17598,7 +17775,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17598
17775
  const combined = [...tableFilters, ...serverFilters];
17599
17776
  setFilters(combined, "replace");
17600
17777
  }, [filterRules, hasActiveFilterRules, isClientFiltering, model.fields, setFilters, tableFilters]);
17601
- const formatCategoryValue = React5.useCallback((field, record) => {
17778
+ const formatCategoryValue = React6.useCallback((field, record) => {
17602
17779
  if (!field) return _36("All");
17603
17780
  const raw = record?.[field.key];
17604
17781
  if (raw === void 0 || raw === null) return "-";
@@ -17616,7 +17793,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17616
17793
  if (field.type === "time") return formatTimeValue(raw);
17617
17794
  return String(raw);
17618
17795
  }, [labelCache]);
17619
- const chartData = React5.useMemo(() => {
17796
+ const chartData = React6.useMemo(() => {
17620
17797
  const data = Array.isArray(columnFilteredDataSource) ? columnFilteredDataSource : [];
17621
17798
  const cat1Field = categoryField1 ? model.fields.find((field) => field.key === categoryField1) : void 0;
17622
17799
  const cat2Field = categoryField2 ? model.fields.find((field) => field.key === categoryField2) : void 0;
@@ -17723,7 +17900,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17723
17900
  };
17724
17901
  }, [columnFilteredDataSource, categoryField1, categoryField2, model.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
17725
17902
  const crosstabBarColor = modelTone.soft || token.colorPrimaryBg || "rgba(22, 119, 255, 0.16)";
17726
- const stageCrosstabCellEdits = React5.useCallback((updates) => {
17903
+ const stageCrosstabCellEdits = React6.useCallback((updates) => {
17727
17904
  if (updates.length === 0) return;
17728
17905
  setCrosstabStaged((prev) => {
17729
17906
  const next = { ...prev };
@@ -17734,11 +17911,11 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17734
17911
  return next;
17735
17912
  });
17736
17913
  }, []);
17737
- const getCrosstabStagedValue = React5.useCallback((recordId, fieldKey) => {
17914
+ const getCrosstabStagedValue = React6.useCallback((recordId, fieldKey) => {
17738
17915
  return crosstabStaged[String(recordId)]?.[fieldKey];
17739
17916
  }, [crosstabStaged]);
17740
17917
  const crosstabHasPendingEdits = Object.keys(crosstabStaged).length > 0;
17741
- const saveCrosstabEdits = React5.useCallback(async () => {
17918
+ const saveCrosstabEdits = React6.useCallback(async () => {
17742
17919
  const entries = Object.entries(crosstabStaged);
17743
17920
  if (entries.length === 0) return;
17744
17921
  setCrosstabSaving(true);
@@ -17761,8 +17938,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17761
17938
  setCrosstabSaving(false);
17762
17939
  }
17763
17940
  }, [crosstabStaged, apiUrl, allModels, model.resource, model.name, invalidate]);
17764
- const crosstabResolvedRefIdsRef = React5.useRef(/* @__PURE__ */ new Set());
17765
- React5.useEffect(() => {
17941
+ const crosstabResolvedRefIdsRef = React6.useRef(/* @__PURE__ */ new Set());
17942
+ React6.useEffect(() => {
17766
17943
  if (!isCrosstabView) return;
17767
17944
  const refFields = [categoryField1, categoryField2, ...crosstabFilterFields].filter((k) => Boolean(k)).map((k) => model.fields.find((f) => f.key === k)).filter((f) => Boolean(f && f.reference));
17768
17945
  if (refFields.length === 0) return;
@@ -17797,7 +17974,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17797
17974
  cancelled = true;
17798
17975
  };
17799
17976
  }, [isCrosstabView, categoryField1, categoryField2, crosstabFilterFields, allRowsData, columnFilteredDataSource, model.fields, allModels, apiUrl, handleReferenceLabel]);
17800
- const crosstabFilterOptions = React5.useMemo(() => {
17977
+ const crosstabFilterOptions = React6.useMemo(() => {
17801
17978
  if (crosstabFilterFields.length === 0) return /* @__PURE__ */ new Map();
17802
17979
  const data = allRowsData.length > 0 ? allRowsData : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
17803
17980
  const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
@@ -17969,7 +18146,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17969
18146
  }
17970
18147
  )
17971
18148
  ] });
17972
- const chartSignature = React5.useMemo(() => {
18149
+ const chartSignature = React6.useMemo(() => {
17973
18150
  return JSON.stringify({
17974
18151
  chartType,
17975
18152
  summaryFn,
@@ -17982,10 +18159,10 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17982
18159
  groups: chartData.groups
17983
18160
  });
17984
18161
  }, [chartType, summaryFn, categoryField1, categoryField2, rankingMode, rankingFieldKey, rankingN, chartData]);
17985
- const statsSummary = React5.useMemo(() => {
18162
+ const statsSummary = React6.useMemo(() => {
17986
18163
  return buildStatsSummary(columnFilteredDataSource, displayFields, labelCache);
17987
18164
  }, [columnFilteredDataSource, displayFields, labelCache]);
17988
- const tdCategoricalBoxes = React5.useMemo(() => {
18165
+ const tdCategoricalBoxes = React6.useMemo(() => {
17989
18166
  if (!isTotalsDetailsView) return [];
17990
18167
  return displayFields.filter((field) => field.type !== "number" || Boolean(field.reference)).map((field) => {
17991
18168
  const counts = /* @__PURE__ */ new Map();
@@ -18022,14 +18199,14 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18022
18199
  };
18023
18200
  });
18024
18201
  }, [isTotalsDetailsView, allRows, displayFields, labelCache]);
18025
- const getDefaultTotalsSummaryFn = React5.useCallback((field) => {
18202
+ const getDefaultTotalsSummaryFn = React6.useCallback((field) => {
18026
18203
  if (isPkField(field, model) || isReferenceField(field)) return "count";
18027
18204
  return "sum";
18028
18205
  }, []);
18029
- const resolveTotalsSummaryFn = React5.useCallback((field) => {
18206
+ const resolveTotalsSummaryFn = React6.useCallback((field) => {
18030
18207
  return totalsSummaryFunctions[field.key] || getDefaultTotalsSummaryFn(field);
18031
18208
  }, [getDefaultTotalsSummaryFn, totalsSummaryFunctions]);
18032
- const computeTotalsSummaryValue = React5.useCallback((field) => {
18209
+ const computeTotalsSummaryValue = React6.useCallback((field) => {
18033
18210
  const fn = resolveTotalsSummaryFn(field);
18034
18211
  if (field.type === "number" && !field.reference) {
18035
18212
  const values = (allRows || []).map((row) => Number(row?.[field.key])).filter((v) => !Number.isNaN(v) && Number.isFinite(v));
@@ -18058,7 +18235,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18058
18235
  if (fn === "distinct") return new Set(rawValues.map((v) => String(v ?? "-"))).size;
18059
18236
  return rawValues.length;
18060
18237
  }, [allRows, resolveTotalsSummaryFn]);
18061
- const getSummaryFunctionDisplayText = React5.useCallback((fn) => {
18238
+ const getSummaryFunctionDisplayText = React6.useCallback((fn) => {
18062
18239
  if (!fn) return "";
18063
18240
  const labels = {
18064
18241
  sum: _36("Sum"),
@@ -18071,7 +18248,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18071
18248
  };
18072
18249
  return labels[fn] || fn;
18073
18250
  }, []);
18074
- const tdNumericBoxes = React5.useMemo(() => {
18251
+ const tdNumericBoxes = React6.useMemo(() => {
18075
18252
  if (!isTotalsDetailsView) return [];
18076
18253
  return displayFields.filter((field) => field.type === "number" && !field.reference).map((field) => {
18077
18254
  const summaryFnVal = resolveTotalsSummaryFn(field);
@@ -18080,7 +18257,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18080
18257
  return { key: field.key, label, value, summaryFn: summaryFnVal };
18081
18258
  });
18082
18259
  }, [isTotalsDetailsView, displayFields, resolveTotalsSummaryFn, computeTotalsSummaryValue]);
18083
- const totalsSummaryConfigFields = React5.useMemo(() => {
18260
+ const totalsSummaryConfigFields = React6.useMemo(() => {
18084
18261
  return displayFields.filter((field) => field.type === "number" && !field.reference);
18085
18262
  }, [displayFields]);
18086
18263
  const renderDynamicListTotalsBoxes = () => {
@@ -18145,7 +18322,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18145
18322
  ) })
18146
18323
  ] }) });
18147
18324
  };
18148
- const numericColumnMaxes = React5.useMemo(() => {
18325
+ const numericColumnMaxes = React6.useMemo(() => {
18149
18326
  const maxes = {};
18150
18327
  const rows = allRows || [];
18151
18328
  displayFields.forEach((field) => {
@@ -18159,7 +18336,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18159
18336
  });
18160
18337
  return maxes;
18161
18338
  }, [allRows, displayFields]);
18162
- const statsNumericMaxes = React5.useMemo(() => {
18339
+ const statsNumericMaxes = React6.useMemo(() => {
18163
18340
  const stats = statsSummary.numericStats;
18164
18341
  const maxAbs = (values) => {
18165
18342
  const absValues = values.filter((val) => typeof val === "number").map((val) => Math.abs(val));
@@ -18173,13 +18350,13 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18173
18350
  stddev: maxAbs(stats.map((row) => row.stddev))
18174
18351
  };
18175
18352
  }, [statsSummary.numericStats]);
18176
- React5.useEffect(() => {
18353
+ React6.useEffect(() => {
18177
18354
  if (!analyzeOpen) return;
18178
18355
  skipNextAnimationRef.current = true;
18179
18356
  setChartAnimationStage("enter");
18180
18357
  setChartAnimationKey((key) => key + 1);
18181
18358
  }, [analyzeOpen]);
18182
- React5.useEffect(() => {
18359
+ React6.useEffect(() => {
18183
18360
  if (!analyzeOpen) return;
18184
18361
  if (skipNextAnimationRef.current) {
18185
18362
  skipNextAnimationRef.current = false;
@@ -18188,17 +18365,17 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18188
18365
  setChartAnimationStage("update");
18189
18366
  setChartAnimationKey((key) => key + 1);
18190
18367
  }, [analyzeOpen, chartSignature]);
18191
- const fieldByKey = React5.useMemo(() => {
18368
+ const fieldByKey = React6.useMemo(() => {
18192
18369
  return new Map(model.fields.map((field) => [field.key, field]));
18193
18370
  }, [model.fields]);
18194
- const chartTitle = React5.useMemo(() => {
18371
+ const chartTitle = React6.useMemo(() => {
18195
18372
  const cat1Label = categoryField1 ? fieldByKey.get(categoryField1)?.label : "All";
18196
18373
  const cat2Label = categoryField2 ? fieldByKey.get(categoryField2)?.label : null;
18197
18374
  const parts = [model.label || model.name, cat1Label];
18198
18375
  if (cat2Label) parts.push(cat2Label);
18199
18376
  return parts.filter(Boolean).join(" \u2022 ");
18200
18377
  }, [categoryField1, categoryField2, fieldByKey, model.label, model.name]);
18201
- const formatValueForExport = React5.useCallback((field, record) => {
18378
+ const formatValueForExport = React6.useCallback((field, record) => {
18202
18379
  const raw = record?.[field.key];
18203
18380
  if (raw === void 0 || raw === null) return "";
18204
18381
  if (field.reference) {
@@ -18214,7 +18391,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18214
18391
  if (field.type === "time") return formatTimeValue(raw);
18215
18392
  return String(raw);
18216
18393
  }, [labelCache]);
18217
- React5.useEffect(() => {
18394
+ React6.useEffect(() => {
18218
18395
  if (!exportRequested || isAllRowsLoading) return;
18219
18396
  const escapeCsv = (value) => {
18220
18397
  if (value.includes('"') || value.includes(",") || value.includes("\n")) {
@@ -18327,11 +18504,11 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18327
18504
  }
18328
18505
  return { resource: null, id: null, isLinkRow: false };
18329
18506
  };
18330
- const clearBulkSelection = React5.useCallback(() => {
18507
+ const clearBulkSelection = React6.useCallback(() => {
18331
18508
  setBulkSelectedRowKeys([]);
18332
18509
  bulkSelectedRowsMapRef.current.clear();
18333
18510
  }, []);
18334
- React5.useEffect(() => {
18511
+ React6.useEffect(() => {
18335
18512
  if (!selectAllFilteredPending || !allRowsLoaded) return;
18336
18513
  setSelectAllFilteredPending(false);
18337
18514
  const keys = filteredDataSource.map((r) => getRowKey(r));
@@ -18339,7 +18516,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18339
18516
  filteredDataSource.forEach((r) => bulkSelectedRowsMapRef.current.set(getRowKey(r), r));
18340
18517
  setBulkSelectedRowKeys(keys);
18341
18518
  }, [selectAllFilteredPending, allRowsLoaded, filteredDataSource]);
18342
- const handleSelectAllFiltered = React5.useCallback(() => {
18519
+ const handleSelectAllFiltered = React6.useCallback(() => {
18343
18520
  if (!allRowsLoaded) {
18344
18521
  setSelectAllFilteredPending(true);
18345
18522
  fetchAllRows();
@@ -18350,7 +18527,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18350
18527
  setBulkSelectedRowKeys(keys);
18351
18528
  }
18352
18529
  }, [allRowsLoaded, fetchAllRows, filteredDataSource]);
18353
- const executeBulkActions = React5.useCallback(async () => {
18530
+ const executeBulkActions = React6.useCallback(async () => {
18354
18531
  const records = bulkSelectedRowKeys.map((k) => bulkSelectedRowsMapRef.current.get(k)).filter(Boolean);
18355
18532
  if (records.length === 0) return;
18356
18533
  const resource = resolveResourcePath(model.resource || model.name, allModels);
@@ -18462,9 +18639,9 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18462
18639
  }
18463
18640
  };
18464
18641
  const isEmptyTable = (filteredDataSource?.length ?? 0) === 0;
18465
- const getRowKeyRef = React5.useRef(getRowKey);
18642
+ const getRowKeyRef = React6.useRef(getRowKey);
18466
18643
  getRowKeyRef.current = getRowKey;
18467
- const handleBulkRowSelectionChange = React5.useCallback(
18644
+ const handleBulkRowSelectionChange = React6.useCallback(
18468
18645
  (newKeys, newRowsOnPage) => {
18469
18646
  const currentPageData = isClientFiltering ? filteredDataSource : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
18470
18647
  const currentPageKeys = new Set(currentPageData.map((r) => String(getRowKeyRef.current(r))));
@@ -18493,7 +18670,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18493
18670
  ]
18494
18671
  };
18495
18672
  const filteredTotalCount = isClientFiltering ? filteredDataSource.length : typeof tableProps.pagination === "object" ? tableProps.pagination?.total ?? filteredDataSource.length : filteredDataSource.length;
18496
- const bulkActionsAvailable = React5.useMemo(() => {
18673
+ const bulkActionsAvailable = React6.useMemo(() => {
18497
18674
  const opts = [];
18498
18675
  if (canBulkEdit) {
18499
18676
  opts.push({ label: _36("Change field value"), value: "__change_field__" });
@@ -18923,7 +19100,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18923
19100
  });
18924
19101
  };
18925
19102
  const galleryPageSize = typeof tablePagination === "object" && tablePagination?.pageSize ? tablePagination.pageSize : 10;
18926
- const handleGalleryPageChange = React5.useCallback((page, nextPageSize) => {
19103
+ const handleGalleryPageChange = React6.useCallback((page, nextPageSize) => {
18927
19104
  setGalleryPage(page);
18928
19105
  if (nextPageSize && nextPageSize !== pageSize) {
18929
19106
  setPageSize(nextPageSize);
@@ -18941,19 +19118,19 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18941
19118
  }, [isClientFiltering, pageSize, tableProps]);
18942
19119
  const serverCurrentPage = !isClientFiltering && typeof tableProps.pagination === "object" ? Number(tableProps.pagination.current || 1) : 1;
18943
19120
  const serverTotal = !isClientFiltering && typeof tableProps.pagination === "object" ? Number(tableProps.pagination.total || 0) : 0;
18944
- React5.useEffect(() => {
19121
+ React6.useEffect(() => {
18945
19122
  if (isClientFiltering) return;
18946
19123
  if (Number.isFinite(serverCurrentPage) && serverCurrentPage > 0 && serverCurrentPage !== galleryPage) {
18947
19124
  setGalleryPage(serverCurrentPage);
18948
19125
  }
18949
19126
  }, [galleryPage, isClientFiltering, serverCurrentPage]);
18950
- const galleryRows = React5.useMemo(() => {
19127
+ const galleryRows = React6.useMemo(() => {
18951
19128
  if (!isGalleryView) return [];
18952
19129
  if (!isClientFiltering) return filteredDataSource;
18953
19130
  const start = (galleryPage - 1) * galleryPageSize;
18954
19131
  return filteredDataSource.slice(start, start + galleryPageSize);
18955
19132
  }, [filteredDataSource, galleryPage, galleryPageSize, isClientFiltering, isGalleryView]);
18956
- const galleryPaginationProps = React5.useMemo(() => {
19133
+ const galleryPaginationProps = React6.useMemo(() => {
18957
19134
  if (!isGalleryView) return void 0;
18958
19135
  if (!isClientFiltering) {
18959
19136
  return {
@@ -18978,17 +19155,17 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18978
19155
  onShowSizeChange: handleGalleryPageChange
18979
19156
  };
18980
19157
  }, [filteredDataSource.length, galleryPage, galleryPageSize, handleGalleryPageChange, isClientFiltering, isGalleryView, serverTotal, tablePagination]);
18981
- const calendarDateFieldKeySet = React5.useMemo(
19158
+ const calendarDateFieldKeySet = React6.useMemo(
18982
19159
  () => new Set(calendarDateFieldOptions.map((field) => field.key)),
18983
19160
  [calendarDateFieldOptions]
18984
19161
  );
18985
- React5.useEffect(() => {
19162
+ React6.useEffect(() => {
18986
19163
  if (!isCalendarView) return;
18987
19164
  if (calendarDateField && calendarDateFieldKeySet.has(calendarDateField)) return;
18988
19165
  const fallback = calendarDateFieldOptions[0]?.key || "";
18989
19166
  if (fallback !== calendarDateField) setCalendarDateField(fallback);
18990
19167
  }, [calendarDateField, calendarDateFieldKeySet, calendarDateFieldOptions, isCalendarView]);
18991
- const calendarEntries = React5.useMemo(() => {
19168
+ const calendarEntries = React6.useMemo(() => {
18992
19169
  if (!isCalendarView || !calendarDateField) return [];
18993
19170
  const entries = [];
18994
19171
  filteredDataSource.forEach((record) => {
@@ -19006,7 +19183,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
19006
19183
  });
19007
19184
  return entries;
19008
19185
  }, [calendarDateField, filteredDataSource, isCalendarView]);
19009
- const calendarEarliestDateTs = React5.useMemo(() => {
19186
+ const calendarEarliestDateTs = React6.useMemo(() => {
19010
19187
  if (calendarEntries.length === 0) return null;
19011
19188
  let earliest = calendarEntries[0].date.valueOf();
19012
19189
  for (let index = 1; index < calendarEntries.length; index += 1) {
@@ -19015,8 +19192,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
19015
19192
  }
19016
19193
  return earliest;
19017
19194
  }, [calendarEntries]);
19018
- const calendarInitSignatureRef = React5.useRef("");
19019
- React5.useEffect(() => {
19195
+ const calendarInitSignatureRef = React6.useRef("");
19196
+ React6.useEffect(() => {
19020
19197
  if (!isCalendarView) return;
19021
19198
  const signature = `${calendarDateField}|${calendarMode}|${calendarEarliestDateTs ?? "none"}`;
19022
19199
  if (calendarInitSignatureRef.current === signature) return;
@@ -19027,7 +19204,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
19027
19204
  }
19028
19205
  setCalendarAnchorDate(dayjs9__default.default(calendarEarliestDateTs).startOf(calendarMode));
19029
19206
  }, [calendarDateField, calendarEarliestDateTs, calendarMode, isCalendarView]);
19030
- const calendarEntriesByDate = React5.useMemo(() => {
19207
+ const calendarEntriesByDate = React6.useMemo(() => {
19031
19208
  const grouped = /* @__PURE__ */ new Map();
19032
19209
  calendarEntries.forEach((entry) => {
19033
19210
  const key = entry.date.format("YYYY-MM-DD");
@@ -19037,7 +19214,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
19037
19214
  });
19038
19215
  return grouped;
19039
19216
  }, [calendarEntries]);
19040
- const calendarRangeDays = React5.useMemo(() => {
19217
+ const calendarRangeDays = React6.useMemo(() => {
19041
19218
  const current = calendarAnchorDate.startOf(calendarMode);
19042
19219
  if (calendarMode === "week") {
19043
19220
  const start2 = current.startOf("week");
@@ -19048,7 +19225,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
19048
19225
  const totalDays = end.diff(start, "day") + 1;
19049
19226
  return Array.from({ length: totalDays }, (_unused, offset) => start.add(offset, "day"));
19050
19227
  }, [calendarAnchorDate, calendarMode]);
19051
- const calendarPeriodLabel = React5.useMemo(() => {
19228
+ const calendarPeriodLabel = React6.useMemo(() => {
19052
19229
  if (calendarMode === "week") {
19053
19230
  const weekStart = calendarAnchorDate.startOf("week");
19054
19231
  const weekEnd = weekStart.endOf("week");
@@ -19944,7 +20121,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
19944
20121
  { label: _36("Heatmap"), value: "heatmap" },
19945
20122
  { label: _36("Crosstab"), value: "crosstab" },
19946
20123
  { label: _36("Radar"), value: "radar" },
19947
- { label: _36("Combo (Bar + Line)"), value: "combo" }
20124
+ { label: _36("Combo (Bar + Line)"), value: "combo" },
20125
+ { label: _36("3D Scatter"), value: "3d" }
19948
20126
  ]
19949
20127
  }
19950
20128
  )
@@ -20236,8 +20414,8 @@ var LIST_PANEL_ID = "list-panel";
20236
20414
  var detailPanelId = (idx) => `detail-panel-${idx}`;
20237
20415
  var COLLAPSED_SIZE = 10;
20238
20416
  var FakeRouteProvider = ({ model, id, children }) => {
20239
- const existingRouteContext = React5.useContext(reactRouterDom.UNSAFE_RouteContext);
20240
- const fakeRouteContext = React5.useMemo(() => ({
20417
+ const existingRouteContext = React6.useContext(reactRouterDom.UNSAFE_RouteContext);
20418
+ const fakeRouteContext = React6.useMemo(() => ({
20241
20419
  ...existingRouteContext,
20242
20420
  matches: [
20243
20421
  ...existingRouteContext.matches,
@@ -20357,9 +20535,9 @@ var ResizeHandle = () => {
20357
20535
  );
20358
20536
  };
20359
20537
  var MultiPaneLayout = ({ children }) => {
20360
- const containerRef = React5.useRef(null);
20361
- const [panelHeight, setPanelHeight] = React5.useState("100vh");
20362
- React5.useLayoutEffect(() => {
20538
+ const containerRef = React6.useRef(null);
20539
+ const [panelHeight, setPanelHeight] = React6.useState("100vh");
20540
+ React6.useLayoutEffect(() => {
20363
20541
  const measure = () => {
20364
20542
  if (!containerRef.current) return;
20365
20543
  const top = containerRef.current.getBoundingClientRect().top;
@@ -20371,13 +20549,13 @@ var MultiPaneLayout = ({ children }) => {
20371
20549
  }, []);
20372
20550
  const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
20373
20551
  const allModels = useAllModels();
20374
- const PrimaryShowRenderer = React5.useContext(PrimaryShowContext);
20552
+ const PrimaryShowRenderer = React6.useContext(PrimaryShowContext);
20375
20553
  const { token } = antd.theme.useToken();
20376
- const panes = React5.useMemo(() => parsePanes(searchParams), [searchParams]);
20377
- const groupRef = React5.useRef(null);
20378
- const pendingLayoutRef = React5.useRef(null);
20379
- const prevPaneCountRef = React5.useRef(0);
20380
- React5.useEffect(() => {
20554
+ const panes = React6.useMemo(() => parsePanes(searchParams), [searchParams]);
20555
+ const groupRef = React6.useRef(null);
20556
+ const pendingLayoutRef = React6.useRef(null);
20557
+ const prevPaneCountRef = React6.useRef(0);
20558
+ React6.useEffect(() => {
20381
20559
  const newCount = panes.length;
20382
20560
  const prevCount = prevPaneCountRef.current;
20383
20561
  if (!pendingLayoutRef.current || !groupRef.current) {
@@ -20404,7 +20582,7 @@ var MultiPaneLayout = ({ children }) => {
20404
20582
  });
20405
20583
  return () => cancelAnimationFrame(frameId);
20406
20584
  }, [panes.length]);
20407
- const openDetail = React5.useCallback(
20585
+ const openDetail = React6.useCallback(
20408
20586
  (fromPaneIndex, resource, id) => {
20409
20587
  if (groupRef.current) {
20410
20588
  pendingLayoutRef.current = { ...groupRef.current.getLayout() };
@@ -20424,7 +20602,7 @@ var MultiPaneLayout = ({ children }) => {
20424
20602
  },
20425
20603
  [allModels, setSearchParams]
20426
20604
  );
20427
- const closePane = React5.useCallback(
20605
+ const closePane = React6.useCallback(
20428
20606
  (fromArrayIndex) => {
20429
20607
  setSearchParams(
20430
20608
  (prev) => {
@@ -20436,7 +20614,7 @@ var MultiPaneLayout = ({ children }) => {
20436
20614
  },
20437
20615
  [setSearchParams]
20438
20616
  );
20439
- const minimizePane = React5.useCallback((panelId) => {
20617
+ const minimizePane = React6.useCallback((panelId) => {
20440
20618
  if (!groupRef.current) return;
20441
20619
  const layout = groupRef.current.getLayout();
20442
20620
  const currentSize = layout[panelId] ?? COLLAPSED_SIZE;
@@ -20451,7 +20629,7 @@ var MultiPaneLayout = ({ children }) => {
20451
20629
  });
20452
20630
  groupRef.current.setLayout(newLayout);
20453
20631
  }, []);
20454
- const maximizePane = React5.useCallback((panelId) => {
20632
+ const maximizePane = React6.useCallback((panelId) => {
20455
20633
  if (!groupRef.current) return;
20456
20634
  const layout = groupRef.current.getLayout();
20457
20635
  const panelIds = Object.keys(layout);
@@ -20463,7 +20641,7 @@ var MultiPaneLayout = ({ children }) => {
20463
20641
  });
20464
20642
  groupRef.current.setLayout(newLayout);
20465
20643
  }, []);
20466
- const listPaneContext = React5.useMemo(
20644
+ const listPaneContext = React6.useMemo(
20467
20645
  () => ({
20468
20646
  isInMultiPane: true,
20469
20647
  paneIndex: 0,
@@ -20471,7 +20649,7 @@ var MultiPaneLayout = ({ children }) => {
20471
20649
  }),
20472
20650
  [openDetail]
20473
20651
  );
20474
- const detailPaneContexts = React5.useMemo(
20652
+ const detailPaneContexts = React6.useMemo(
20475
20653
  () => panes.map((_43, idx) => ({
20476
20654
  isInMultiPane: true,
20477
20655
  paneIndex: idx + 1,
@@ -20479,7 +20657,7 @@ var MultiPaneLayout = ({ children }) => {
20479
20657
  })),
20480
20658
  [panes, openDetail]
20481
20659
  );
20482
- const panelChildren = React5.useMemo(() => {
20660
+ const panelChildren = React6.useMemo(() => {
20483
20661
  const result = [
20484
20662
  /* @__PURE__ */ jsxRuntime.jsx(Yt, { id: LIST_PANEL_ID, minSize: 10, style: { overflow: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(PaneNavigationContext.Provider, { value: listPaneContext, children }) }, "master-list")
20485
20663
  ];
@@ -20610,8 +20788,8 @@ var HierarchyView = ({ resource, recordId, fallback }) => {
20610
20788
  };
20611
20789
  var instanceCounter = 0;
20612
20790
  var InlinePlotlyHtml = ({ html, style }) => {
20613
- const containerRef = React5.useRef(null);
20614
- const instanceIdRef = React5.useRef("");
20791
+ const containerRef = React6.useRef(null);
20792
+ const instanceIdRef = React6.useRef("");
20615
20793
  if (!instanceIdRef.current) {
20616
20794
  instanceCounter += 1;
20617
20795
  instanceIdRef.current = `iph-${instanceCounter}-${Date.now()}`;
@@ -20637,7 +20815,7 @@ var InlinePlotlyHtml = ({ html, style }) => {
20637
20815
  /((?:reduceCardWidth|increaseCardWidth|optimizeCardSizeInViewPort|maximizeCardSize|minimizeCardSize|flipCard)\()(\d+)\)/g,
20638
20816
  (match, func, suffix) => `${func}'${suffix}-${instanceId}')`
20639
20817
  );
20640
- React5.useEffect(() => {
20818
+ React6.useEffect(() => {
20641
20819
  const container = containerRef.current;
20642
20820
  if (!container) return;
20643
20821
  const scripts = Array.from(container.querySelectorAll("script"));
@@ -20901,15 +21079,15 @@ var ColorModeContextProvider = ({
20901
21079
  "(prefers-color-scheme: dark)"
20902
21080
  ).matches;
20903
21081
  const systemPreference = isSystemPreferenceDark ? "dark" : "light";
20904
- const [mode, setMode] = React5.useState(
21082
+ const [mode, setMode] = React6.useState(
20905
21083
  colorModeFromLocalStorage === "dark" || colorModeFromLocalStorage === "light" ? colorModeFromLocalStorage : systemPreference
20906
21084
  );
20907
- const initializedFromServer = React5.useRef(false);
20908
- const [schemaVersion, setSchemaVersion] = React5.useState(0);
20909
- React5.useEffect(() => {
21085
+ const initializedFromServer = React6.useRef(false);
21086
+ const [schemaVersion, setSchemaVersion] = React6.useState(0);
21087
+ React6.useEffect(() => {
20910
21088
  return onColorSchemaChange(() => setSchemaVersion((v) => v + 1));
20911
21089
  }, []);
20912
- React5.useEffect(() => {
21090
+ React6.useEffect(() => {
20913
21091
  let cancelled = false;
20914
21092
  const load = async () => {
20915
21093
  try {
@@ -20930,12 +21108,12 @@ var ColorModeContextProvider = ({
20930
21108
  cancelled = true;
20931
21109
  };
20932
21110
  }, []);
20933
- React5.useEffect(() => {
21111
+ React6.useEffect(() => {
20934
21112
  window.localStorage.setItem("colorMode", mode);
20935
21113
  document.body.classList.toggle("jm-dark", mode === "dark");
20936
21114
  document.body.classList.toggle("jm-light", mode === "light");
20937
21115
  }, [mode]);
20938
- const saveToServer = React5.useCallback(async (newMode) => {
21116
+ const saveToServer = React6.useCallback(async (newMode) => {
20939
21117
  try {
20940
21118
  await authenticatedFetch(`${API_BASE_URL}/views/preferences/color-mode`, {
20941
21119
  method: "POST",
@@ -20945,7 +21123,7 @@ var ColorModeContextProvider = ({
20945
21123
  } catch (_e3) {
20946
21124
  }
20947
21125
  }, []);
20948
- const setColorMode = React5.useCallback((newMode) => {
21126
+ const setColorMode = React6.useCallback((newMode) => {
20949
21127
  setMode(newMode);
20950
21128
  void saveToServer(newMode);
20951
21129
  }, [saveToServer]);
@@ -20961,7 +21139,7 @@ var ColorModeContextProvider = ({
20961
21139
  }
20962
21140
  ) });
20963
21141
  };
20964
- var ResourceContext = React5.createContext({
21142
+ var ResourceContext = React6.createContext({
20965
21143
  allResources: [],
20966
21144
  allSystemModels: []
20967
21145
  });
@@ -21067,10 +21245,10 @@ var LoginPage = ({ appTitle = "VeloIQ", logo }) => {
21067
21245
  };
21068
21246
  function useDashboardConfig() {
21069
21247
  const apiUrl = core.useApiUrl();
21070
- const [config, setConfig] = React5.useState(null);
21071
- const [enabled, setEnabled] = React5.useState(false);
21072
- const [loading, setLoading] = React5.useState(true);
21073
- const load = React5.useCallback(async () => {
21248
+ const [config, setConfig] = React6.useState(null);
21249
+ const [enabled, setEnabled] = React6.useState(false);
21250
+ const [loading, setLoading] = React6.useState(true);
21251
+ const load = React6.useCallback(async () => {
21074
21252
  setLoading(true);
21075
21253
  try {
21076
21254
  const res = await authenticatedFetch(`${apiUrl}/dashboard/config`);
@@ -21088,10 +21266,10 @@ function useDashboardConfig() {
21088
21266
  setLoading(false);
21089
21267
  }
21090
21268
  }, [apiUrl]);
21091
- React5.useEffect(() => {
21269
+ React6.useEffect(() => {
21092
21270
  load();
21093
21271
  }, [load]);
21094
- const save = React5.useCallback(async (next) => {
21272
+ const save = React6.useCallback(async (next) => {
21095
21273
  setConfig(next);
21096
21274
  try {
21097
21275
  await authenticatedFetch(`${apiUrl}/dashboard/config`, {
@@ -21104,10 +21282,52 @@ function useDashboardConfig() {
21104
21282
  }, [apiUrl]);
21105
21283
  return { config, enabled, loading, save, reload: load };
21106
21284
  }
21285
+ var PlotlyChartContent = ({ chartUrl, refreshNonce }) => {
21286
+ const [chartHtml, setChartHtml] = React6.useState("");
21287
+ const [loading, setLoading] = React6.useState(true);
21288
+ const [error, setError] = React6.useState("");
21289
+ const fetchChart = React6.useCallback(async () => {
21290
+ setLoading(true);
21291
+ setError("");
21292
+ try {
21293
+ const apiUrl = typeof API_URL3 === "string" ? API_URL3 : "";
21294
+ const fullUrl = chartUrl.startsWith("http") ? chartUrl : `${apiUrl}${chartUrl}`;
21295
+ const sep = fullUrl.includes("?") ? "&" : "?";
21296
+ const lang = (() => {
21297
+ try {
21298
+ return (localStorage.getItem("locale") || navigator.language || "en").split("-")[0].toLowerCase();
21299
+ } catch {
21300
+ return "en";
21301
+ }
21302
+ })();
21303
+ const res = await authenticatedFetch(`${fullUrl}${sep}lang=${encodeURIComponent(lang)}`);
21304
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
21305
+ const data = await res.json();
21306
+ setChartHtml(data.chart_html || "");
21307
+ } catch (e) {
21308
+ setError(e?.message ?? String(e));
21309
+ } finally {
21310
+ setLoading(false);
21311
+ }
21312
+ }, [chartUrl]);
21313
+ React6.useEffect(() => {
21314
+ fetchChart();
21315
+ }, [fetchChart, refreshNonce]);
21316
+ if (loading) {
21317
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx(antd.Spin, {}) });
21318
+ }
21319
+ if (error) {
21320
+ return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: `Chart error: ${error}`, style: { padding: 20 }, image: antd.Empty.PRESENTED_IMAGE_SIMPLE });
21321
+ }
21322
+ if (!chartHtml) {
21323
+ return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "No chart data", style: { padding: 20 }, image: antd.Empty.PRESENTED_IMAGE_SIMPLE });
21324
+ }
21325
+ return /* @__PURE__ */ jsxRuntime.jsx(InlinePlotlyHtml, { html: chartHtml, style: { padding: 8, height: "100%", overflow: "auto" } });
21326
+ };
21107
21327
  var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigureLayout, onConfigure, onMaximize, onMinimize, onResize, onMove }) => {
21108
21328
  const { token } = antd.theme.useToken();
21109
21329
  const model = findModelByName(allModels, cell.model);
21110
- const cellRef = React5.useRef(null);
21330
+ const cellRef = React6.useRef(null);
21111
21331
  const cellStyle = {
21112
21332
  position: "relative",
21113
21333
  border: `1px solid ${token.colorBorderSecondary}`,
@@ -21136,11 +21356,13 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
21136
21356
  minHeight: 32,
21137
21357
  position: "relative"
21138
21358
  };
21359
+ const isPlotlyChart = cell.source_type === "plotly_chart";
21139
21360
  const resource = model?.resource || cell.model;
21140
21361
  const isModelLike = cell.source_type === "model" || cell.source_type === "named_query";
21141
- const cellTitle = isModelLike ? model?.label || cell.model : cell.section_name || cell.model;
21362
+ const cellTitle = isPlotlyChart ? cell.chart_title || cell.model : isModelLike ? model?.label || cell.model : cell.section_name || cell.model;
21142
21363
  const tone = isModelLike && model ? getModelTone(model) : null;
21143
- const startResize = React5.useCallback((e, dir) => {
21364
+ const [chartRefreshNonce, setChartRefreshNonce] = React6.useState(0);
21365
+ const startResize = React6.useCallback((e, dir) => {
21144
21366
  e.preventDefault();
21145
21367
  e.stopPropagation();
21146
21368
  const el = cellRef.current;
@@ -21293,7 +21515,7 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
21293
21515
  ) })
21294
21516
  ] })
21295
21517
  ] }),
21296
- !isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflow: "auto", minHeight: 0 }, children: model ? /* @__PURE__ */ jsxRuntime.jsx(
21518
+ !isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflow: "auto", minHeight: 0 }, children: isPlotlyChart && cell.chart_url ? /* @__PURE__ */ jsxRuntime.jsx(PlotlyChartContent, { chartUrl: cell.chart_url, refreshNonce: chartRefreshNonce }) : model ? /* @__PURE__ */ jsxRuntime.jsx(
21297
21519
  DynamicList,
21298
21520
  {
21299
21521
  model,
@@ -21316,11 +21538,11 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
21316
21538
  };
21317
21539
  var DashboardTabContent = ({ tab, allModels, maximizedCellId, minimizedCellIds, canConfigureLayout, onMaximize, onMinimize, onConfigure, onResize, onMove }) => {
21318
21540
  const cells = tab.cells;
21319
- const numCols = React5.useMemo(() => {
21541
+ const numCols = React6.useMemo(() => {
21320
21542
  if (!cells.length) return 2;
21321
21543
  return Math.max(...cells.map((c) => c.col)) + 1;
21322
21544
  }, [cells]);
21323
- const numRows = React5.useMemo(() => {
21545
+ const numRows = React6.useMemo(() => {
21324
21546
  if (!cells.length) return 1;
21325
21547
  return Math.max(...cells.map((c) => c.row)) + 1;
21326
21548
  }, [cells]);
@@ -21366,13 +21588,13 @@ var DashboardTabContent = ({ tab, allModels, maximizedCellId, minimizedCellIds,
21366
21588
  var ViewsGrid = ({ config, allModels, onConfigChange }) => {
21367
21589
  const { data: canLayoutData } = core.useCan({ resource: "veloiq_layout", action: "configure_layout" });
21368
21590
  const canConfigureLayout = canLayoutData?.can !== false;
21369
- const [maximizedCellId, setMaximizedCellId] = React5.useState(null);
21370
- const [minimizedCellIds, setMinimizedCellIds] = React5.useState(/* @__PURE__ */ new Set());
21371
- const [drawerSelection, setDrawerSelection] = React5.useState(null);
21372
- const handleMaximize = React5.useCallback((cellId) => {
21591
+ const [maximizedCellId, setMaximizedCellId] = React6.useState(null);
21592
+ const [minimizedCellIds, setMinimizedCellIds] = React6.useState(/* @__PURE__ */ new Set());
21593
+ const [drawerSelection, setDrawerSelection] = React6.useState(null);
21594
+ const handleMaximize = React6.useCallback((cellId) => {
21373
21595
  setMaximizedCellId((prev) => prev === cellId ? null : cellId);
21374
21596
  }, []);
21375
- const handleMinimize = React5.useCallback((cellId) => {
21597
+ const handleMinimize = React6.useCallback((cellId) => {
21376
21598
  setMinimizedCellIds((prev) => {
21377
21599
  const next = new Set(prev);
21378
21600
  if (next.has(cellId)) {
@@ -21383,14 +21605,14 @@ var ViewsGrid = ({ config, allModels, onConfigChange }) => {
21383
21605
  return next;
21384
21606
  });
21385
21607
  }, []);
21386
- const handleOpenDrawer = React5.useCallback((tabId, cell) => {
21608
+ const handleOpenDrawer = React6.useCallback((tabId, cell) => {
21387
21609
  setDrawerSelection({ tabId, cell });
21388
21610
  }, []);
21389
- const handleSaveConfig = React5.useCallback((nextConfig) => {
21611
+ const handleSaveConfig = React6.useCallback((nextConfig) => {
21390
21612
  onConfigChange(nextConfig);
21391
21613
  setDrawerSelection(null);
21392
21614
  }, [onConfigChange]);
21393
- const handleMoveCell = React5.useCallback((tabId, cellId, direction) => {
21615
+ const handleMoveCell = React6.useCallback((tabId, cellId, direction) => {
21394
21616
  const nextTabs = config.tabs.map((tab) => {
21395
21617
  if (tab.id !== tabId) return tab;
21396
21618
  const cell = tab.cells.find((c) => c.id === cellId);
@@ -21411,7 +21633,7 @@ var ViewsGrid = ({ config, allModels, onConfigChange }) => {
21411
21633
  });
21412
21634
  onConfigChange({ ...config, tabs: nextTabs });
21413
21635
  }, [config, onConfigChange]);
21414
- const handleResizeCell = React5.useCallback((tabId, cellId, minWidth, minHeight) => {
21636
+ const handleResizeCell = React6.useCallback((tabId, cellId, minWidth, minHeight) => {
21415
21637
  const nextTabs = config.tabs.map((tab) => {
21416
21638
  if (tab.id !== tabId) return tab;
21417
21639
  return {
@@ -21428,7 +21650,7 @@ var ViewsGrid = ({ config, allModels, onConfigChange }) => {
21428
21650
  });
21429
21651
  onConfigChange({ ...config, tabs: nextTabs });
21430
21652
  }, [config, onConfigChange]);
21431
- const tabItems = React5.useMemo(
21653
+ const tabItems = React6.useMemo(
21432
21654
  () => config.tabs.map((tab) => ({
21433
21655
  key: tab.id,
21434
21656
  label: tab.name,
@@ -21508,7 +21730,7 @@ function relativeTime3(iso) {
21508
21730
  var RecentActivityPanel = () => {
21509
21731
  const { token } = antd.theme.useToken();
21510
21732
  const allModels = useAllModels();
21511
- const [days, setDays] = React5.useState(30);
21733
+ const [days, setDays] = React6.useState(30);
21512
21734
  const { data, loading, reload } = useRecentActivity(days);
21513
21735
  const groups = data?.groups ?? [];
21514
21736
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "16px 0" }, children: [
@@ -21616,9 +21838,9 @@ var RecentActivityPanel = () => {
21616
21838
  };
21617
21839
  var { Text: AntText, Title: AntTitle } = antd.Typography;
21618
21840
  function usePinnedRecords() {
21619
- const [groups, setGroups] = React5.useState([]);
21620
- const [loading, setLoading] = React5.useState(true);
21621
- const load = React5.useCallback(async () => {
21841
+ const [groups, setGroups] = React6.useState([]);
21842
+ const [loading, setLoading] = React6.useState(true);
21843
+ const load = React6.useCallback(async () => {
21622
21844
  setLoading(true);
21623
21845
  try {
21624
21846
  const res = await authenticatedFetch(`${API_URL3}/dashboard/pinned-records`);
@@ -21631,7 +21853,7 @@ function usePinnedRecords() {
21631
21853
  setLoading(false);
21632
21854
  }
21633
21855
  }, []);
21634
- React5__default.default.useEffect(() => {
21856
+ React6__default.default.useEffect(() => {
21635
21857
  load();
21636
21858
  }, [load]);
21637
21859
  return { groups, loading, reload: load };
@@ -21640,9 +21862,9 @@ var PinnedRecordsPanel = () => {
21640
21862
  const { token } = antd.theme.useToken();
21641
21863
  const allModels = useAllModels();
21642
21864
  const { groups, loading, reload } = usePinnedRecords();
21643
- const [unpinning, setUnpinning] = React5.useState(/* @__PURE__ */ new Set());
21865
+ const [unpinning, setUnpinning] = React6.useState(/* @__PURE__ */ new Set());
21644
21866
  const visibleGroups = groups.filter((g) => findModelByName(allModels, g.resource));
21645
- const handleUnpin = React5.useCallback(async (resource, recordId) => {
21867
+ const handleUnpin = React6.useCallback(async (resource, recordId) => {
21646
21868
  const key = `${resource}:${recordId}`;
21647
21869
  setUnpinning((prev) => new Set(prev).add(key));
21648
21870
  try {
@@ -21971,6 +22193,7 @@ var authSystemModels = [
21971
22193
 
21972
22194
  exports.API_URL = API_URL3;
21973
22195
  exports.AllModelsProvider = AllModelsProvider;
22196
+ exports.AuthenticatedImage = AuthenticatedImage;
21974
22197
  exports.ColorModeContext = ColorModeContext;
21975
22198
  exports.ColorModeContextProvider = ColorModeContextProvider;
21976
22199
  exports.CommandCenterPortal = CommandCenterPortal;
@@ -22017,6 +22240,7 @@ exports.resolveIcon = resolveIcon;
22017
22240
  exports.setColorSchemas = setColorSchemas;
22018
22241
  exports.sortItemsByNavConfig = sortItemsByNavConfig;
22019
22242
  exports.useAllModels = useAllModels;
22243
+ exports.useAuthenticatedFileUrl = useAuthenticatedFileUrl;
22020
22244
  exports.useKeyboardShortcuts = useKeyboardShortcuts;
22021
22245
  exports.useMetadataModal = useMetadataModal;
22022
22246
  exports.useNavConfig = useNavConfig;