@juicemantics/veloiq-ui 0.8.0 → 0.8.3

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.d.mts CHANGED
@@ -444,6 +444,10 @@ declare const useAllModels: () => ModelDef[];
444
444
  declare const ColorModeContext: React$1.Context<{
445
445
  mode: "light" | "dark";
446
446
  setMode: (mode: "light" | "dark") => void;
447
+ /** Increments every time the color schema (plain-color / color-coded / hex)
448
+ * changes via setColorSchemas(). Components that depend on derived tones
449
+ * use this to re-render when the schema updates. */
450
+ schemaVersion: number;
447
451
  }>;
448
452
 
449
453
  declare const ColorModeContextProvider: React.FC<PropsWithChildren>;
package/dist/index.d.ts CHANGED
@@ -444,6 +444,10 @@ declare const useAllModels: () => ModelDef[];
444
444
  declare const ColorModeContext: React$1.Context<{
445
445
  mode: "light" | "dark";
446
446
  setMode: (mode: "light" | "dark") => void;
447
+ /** Increments every time the color schema (plain-color / color-coded / hex)
448
+ * changes via setColorSchemas(). Components that depend on derived tones
449
+ * use this to re-render when the schema updates. */
450
+ schemaVersion: number;
447
451
  }>;
448
452
 
449
453
  declare const ColorModeContextProvider: React.FC<PropsWithChildren>;
package/dist/index.js CHANGED
@@ -46,7 +46,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
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
48
  var ColorModeContext = React5.createContext({ mode: "light", setMode: () => {
49
- } });
49
+ }, schemaVersion: 0 });
50
50
 
51
51
  // src/utils/modelTone.ts
52
52
  var MODEL_TONES_LIGHT = [
@@ -85,6 +85,16 @@ var _modulesColorSchema = typeof localStorage !== "undefined" && localStorage.ge
85
85
  var _modelsColorSchema = typeof localStorage !== "undefined" && localStorage.getItem("jm_modelsColorSchema") || "plain-color";
86
86
  var _customPlainToneLight = null;
87
87
  var _customPlainToneDark = null;
88
+ var _colorSchemaListeners = [];
89
+ var onColorSchemaChange = (listener) => {
90
+ _colorSchemaListeners.push(listener);
91
+ return () => {
92
+ _colorSchemaListeners = _colorSchemaListeners.filter((l) => l !== listener);
93
+ };
94
+ };
95
+ var _notifyColorSchemaListeners = () => {
96
+ for (const l of [..._colorSchemaListeners]) l();
97
+ };
88
98
  var hexToRgb = (hex) => {
89
99
  const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
90
100
  if (!match) return null;
@@ -219,6 +229,7 @@ var setColorSchemas = (schemas) => {
219
229
  }
220
230
  }
221
231
  }
232
+ _notifyColorSchemaListeners();
222
233
  };
223
234
  var hashString = (input) => {
224
235
  let hash = 0;
@@ -248,7 +259,7 @@ var getModelTone = (modelLike, darkMode) => {
248
259
  return tones[hashString(seed) % tones.length];
249
260
  };
250
261
  var useModelTone = (modelLike) => {
251
- const { mode } = React5.useContext(ColorModeContext);
262
+ const { mode, schemaVersion } = React5.useContext(ColorModeContext);
252
263
  return getModelTone(modelLike, mode === "dark");
253
264
  };
254
265
  var getContrastingTextColor = (background) => isDarkColor(background) ? "#f8fafc" : "#0f172a";
@@ -303,6 +314,7 @@ function getNavEntry(navConfig, key) {
303
314
  return navConfig.find((e) => e.key === key);
304
315
  }
305
316
  function sortItemsByNavConfig(items, navConfig) {
317
+ if (!Array.isArray(items)) return [];
306
318
  return [...items].sort((a, b) => {
307
319
  const aSeq = getNavEntry(navConfig, a.key ?? a.name ?? "")?.sequence ?? 999;
308
320
  const bSeq = getNavEntry(navConfig, b.key ?? b.name ?? "")?.sequence ?? 999;
@@ -358,6 +370,7 @@ function useJourneyMenuItems() {
358
370
  return byModule;
359
371
  }
360
372
  function injectJourneyMenuItems(items, byModule) {
373
+ if (!Array.isArray(items)) return [];
361
374
  if (!byModule || Object.keys(byModule).length === 0) return items;
362
375
  const moduleNameOf = (item) => {
363
376
  let key = String(item?.key ?? item?.name ?? "");
@@ -366,16 +379,20 @@ function injectJourneyMenuItems(items, byModule) {
366
379
  if (byModule[key]) return key;
367
380
  return null;
368
381
  };
369
- const walk = (list) => list.map((item) => {
370
- const childrenWalked = Array.isArray(item?.children) && item.children.length ? walk(item.children) : item?.children;
371
- const moduleName = moduleNameOf(item);
372
- const extra = moduleName ? byModule[moduleName] : void 0;
373
- if (extra && extra.length) {
374
- return { ...item, children: [...extra, ...childrenWalked || []] };
375
- }
376
- if (childrenWalked !== item?.children) return { ...item, children: childrenWalked };
377
- return item;
378
- });
382
+ const walk = (list) => {
383
+ if (!Array.isArray(list)) return [];
384
+ return list.map((item) => {
385
+ const safeChildren = Array.isArray(item?.children) ? item.children : [];
386
+ const childrenWalked = safeChildren.length ? walk(safeChildren) : safeChildren;
387
+ const moduleName = moduleNameOf(item);
388
+ const extra = moduleName ? byModule[moduleName] : void 0;
389
+ if (extra && extra.length) {
390
+ return { ...item, children: [...extra, ...Array.isArray(childrenWalked) ? childrenWalked : []] };
391
+ }
392
+ if (childrenWalked !== item?.children) return { ...item, children: Array.isArray(childrenWalked) ? childrenWalked : item?.children };
393
+ return item;
394
+ });
395
+ };
379
396
  return walk(items);
380
397
  }
381
398
  var HorizontalMenu = ({ navConfig = [] }) => {
@@ -422,8 +439,10 @@ var HorizontalMenu = ({ navConfig = [] }) => {
422
439
  );
423
440
  };
424
441
  const transformItems = (items2, depth = 0) => {
442
+ if (!Array.isArray(items2)) return [];
425
443
  return items2.map((item) => {
426
- const hasChildren = item.children && item.children.length > 0;
444
+ const safeChildren = Array.isArray(item?.children) ? item.children : [];
445
+ const hasChildren = safeChildren.length > 0;
427
446
  return {
428
447
  key: item.key,
429
448
  label: renderLabel(item, depth, hasChildren),
@@ -494,8 +513,10 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
494
513
  );
495
514
  };
496
515
  const transformItems = (items2, depth = 0) => {
516
+ if (!Array.isArray(items2)) return [];
497
517
  return items2.map((item) => {
498
- const hasChildren = item.children && item.children.length > 0;
518
+ const safeChildren = Array.isArray(item?.children) ? item.children : [];
519
+ const hasChildren = safeChildren.length > 0;
499
520
  return {
500
521
  key: item.key,
501
522
  label: renderLabel(item, depth, hasChildren),
@@ -524,7 +545,7 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
524
545
  theme: mode === "dark" ? "dark" : "light",
525
546
  style: {
526
547
  borderRight: `1px solid ${token.colorBorderSecondary}`,
527
- background: token.colorBgContainer,
548
+ background: mode === "dark" ? token.colorBgContainer : token.colorBgLayout,
528
549
  height: "100vh",
529
550
  position: "sticky",
530
551
  top: 0,
@@ -1569,7 +1590,6 @@ function useNavModules() {
1569
1590
  const navConfig = useNavConfig();
1570
1591
  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) }));
1571
1592
  }
1572
- var API_URL4 = "/api";
1573
1593
  var DefaultLogo = ({ logo, appTitle, collapsed, isHeader = false, hideTitle = false }) => {
1574
1594
  const logoEl = typeof logo === "string" ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logo, alt: appTitle || "App", style: { height: isHeader ? "32px" : "40px", width: "auto", marginRight: collapsed || hideTitle ? 0 : 10 } }) : logo ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginRight: collapsed || hideTitle ? 0 : 10, display: "flex", alignItems: "center" }, children: logo }) : null;
1575
1595
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: collapsed ? "center" : "flex-start", padding: isHeader ? 0 : "10px 0" }, children: [
@@ -1580,16 +1600,19 @@ var DefaultLogo = ({ logo, appTitle, collapsed, isHeader = false, hideTitle = fa
1580
1600
  var MobileMenuContent = ({ onClose }) => {
1581
1601
  const { menuItems, selectedKey } = core.useMenu();
1582
1602
  const go = core.useGo();
1583
- const transformItems = (items) => items.map((item) => ({
1584
- key: item.key,
1585
- label: item.label || item.name || item.key,
1586
- icon: item.icon,
1587
- onClick: item.children?.length ? void 0 : () => {
1588
- go({ to: item.route });
1589
- onClose();
1590
- },
1591
- children: item.children?.length ? transformItems(item.children) : void 0
1592
- }));
1603
+ const transformItems = (items) => {
1604
+ if (!Array.isArray(items)) return [];
1605
+ return items.map((item) => ({
1606
+ key: item.key,
1607
+ label: item.label || item.name || item.key,
1608
+ icon: item.icon,
1609
+ onClick: item.children?.length ? void 0 : () => {
1610
+ go({ to: item.route });
1611
+ onClose();
1612
+ },
1613
+ children: item.children?.length ? transformItems(item.children) : void 0
1614
+ }));
1615
+ };
1593
1616
  return /* @__PURE__ */ jsxRuntime.jsx(
1594
1617
  antd.Menu,
1595
1618
  {
@@ -1642,7 +1665,7 @@ var LayoutWrapper = ({
1642
1665
  const handleChangePassword = async (values) => {
1643
1666
  setPwdLoading(true);
1644
1667
  try {
1645
- const res = await authenticatedFetch(`${API_URL4}/auth/change-password`, {
1668
+ const res = await authenticatedFetch(`/auth/change-password`, {
1646
1669
  method: "PUT",
1647
1670
  headers: { "Content-Type": "application/json" },
1648
1671
  body: JSON.stringify(values)
@@ -13715,7 +13738,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
13715
13738
  return parts.filter(Boolean).join(" \u2022 ");
13716
13739
  }, [categoryField1, categoryField2, relatedModel.fields, relatedModel.label, relatedModel.name]);
13717
13740
  const chartData = React5.useMemo(() => {
13718
- const data = columnFilteredRows || [];
13741
+ const data = Array.isArray(columnFilteredRows) ? columnFilteredRows : [];
13719
13742
  const cat1Field = categoryField1 ? relatedModel.fields.find((field) => field.key === categoryField1) : void 0;
13720
13743
  const cat2Field = categoryField2 ? relatedModel.fields.find((field) => field.key === categoryField2) : void 0;
13721
13744
  const groupMap = /* @__PURE__ */ new Map();
@@ -16871,7 +16894,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16871
16894
  }, [allRowsData, useLocalSearch, localSearch, model.fields, labelCache]);
16872
16895
  const isClientFiltering = allRowsLoaded && !allRowsError;
16873
16896
  const filteredDataSource = React5.useMemo(() => {
16874
- if (!isClientFiltering) return tableProps.dataSource || [];
16897
+ if (!isClientFiltering) return Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
16875
16898
  const baseRows = allRows || [];
16876
16899
  return applyFilterRules(applyGlobalSearch(baseRows));
16877
16900
  }, [allRows, applyFilterRules, applyGlobalSearch, isClientFiltering, tableProps.dataSource]);
@@ -16890,7 +16913,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
16890
16913
  setGalleryPage(1);
16891
16914
  }, [localSearch, filterRules, resolvedListViewType]);
16892
16915
  const columnFilters = React5.useMemo(() => {
16893
- const data = allRowsData.length > 0 ? allRowsData : tableProps.dataSource || [];
16916
+ const data = allRowsData.length > 0 ? allRowsData : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
16894
16917
  const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
16895
16918
  return buildColumnFilterOptions({ fields: displayFields, data, rangeCount });
16896
16919
  }, [allRowsData, displayFields, tableProps.dataSource, viewSettings]);
@@ -17594,7 +17617,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17594
17617
  return String(raw);
17595
17618
  }, [labelCache]);
17596
17619
  const chartData = React5.useMemo(() => {
17597
- const data = columnFilteredDataSource || [];
17620
+ const data = Array.isArray(columnFilteredDataSource) ? columnFilteredDataSource : [];
17598
17621
  const cat1Field = categoryField1 ? model.fields.find((field) => field.key === categoryField1) : void 0;
17599
17622
  const cat2Field = categoryField2 ? model.fields.find((field) => field.key === categoryField2) : void 0;
17600
17623
  const groupMap = /* @__PURE__ */ new Map();
@@ -17776,7 +17799,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
17776
17799
  }, [isCrosstabView, categoryField1, categoryField2, crosstabFilterFields, allRowsData, columnFilteredDataSource, model.fields, allModels, apiUrl, handleReferenceLabel]);
17777
17800
  const crosstabFilterOptions = React5.useMemo(() => {
17778
17801
  if (crosstabFilterFields.length === 0) return /* @__PURE__ */ new Map();
17779
- const data = allRowsData.length > 0 ? allRowsData : tableProps.dataSource || [];
17802
+ const data = allRowsData.length > 0 ? allRowsData : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
17780
17803
  const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
17781
17804
  const fields = crosstabFilterFields.map((k) => model.fields.find((f) => f.key === k)).filter((f) => Boolean(f));
17782
17805
  return buildColumnFilterOptions({ fields, data, rangeCount });
@@ -18443,7 +18466,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
18443
18466
  getRowKeyRef.current = getRowKey;
18444
18467
  const handleBulkRowSelectionChange = React5.useCallback(
18445
18468
  (newKeys, newRowsOnPage) => {
18446
- const currentPageData = isClientFiltering ? filteredDataSource : tableProps.dataSource || [];
18469
+ const currentPageData = isClientFiltering ? filteredDataSource : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
18447
18470
  const currentPageKeys = new Set(currentPageData.map((r) => String(getRowKeyRef.current(r))));
18448
18471
  const newKeySet = new Set(newKeys.map((k) => String(k)));
18449
18472
  newRowsOnPage.forEach((row) => {
@@ -20882,6 +20905,10 @@ var ColorModeContextProvider = ({
20882
20905
  colorModeFromLocalStorage === "dark" || colorModeFromLocalStorage === "light" ? colorModeFromLocalStorage : systemPreference
20883
20906
  );
20884
20907
  const initializedFromServer = React5.useRef(false);
20908
+ const [schemaVersion, setSchemaVersion] = React5.useState(0);
20909
+ React5.useEffect(() => {
20910
+ return onColorSchemaChange(() => setSchemaVersion((v) => v + 1));
20911
+ }, []);
20885
20912
  React5.useEffect(() => {
20886
20913
  let cancelled = false;
20887
20914
  const load = async () => {
@@ -20923,7 +20950,7 @@ var ColorModeContextProvider = ({
20923
20950
  void saveToServer(newMode);
20924
20951
  }, [saveToServer]);
20925
20952
  const { darkAlgorithm, defaultAlgorithm } = antd.theme;
20926
- return /* @__PURE__ */ jsxRuntime.jsx(ColorModeContext.Provider, { value: { mode, setMode: setColorMode }, children: /* @__PURE__ */ jsxRuntime.jsx(
20953
+ return /* @__PURE__ */ jsxRuntime.jsx(ColorModeContext.Provider, { value: { mode, setMode: setColorMode, schemaVersion }, children: /* @__PURE__ */ jsxRuntime.jsx(
20927
20954
  antd.ConfigProvider,
20928
20955
  {
20929
20956
  theme: {