@firecms/core 3.0.0-rc.1 → 3.0.0-rc.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.
Files changed (96) hide show
  1. package/dist/components/HomePage/HomePageDnD.d.ts +2 -1
  2. package/dist/components/PropertyCollectionView.d.ts +23 -0
  3. package/dist/components/UserDisplay.d.ts +7 -0
  4. package/dist/components/VirtualTable/fields/VirtualTableUserSelect.d.ts +12 -0
  5. package/dist/contexts/InternalUserManagementContext.d.ts +3 -0
  6. package/dist/core/EntityEditView.d.ts +10 -4
  7. package/dist/core/FireCMS.d.ts +0 -1
  8. package/dist/core/field_configs.d.ts +1 -1
  9. package/dist/form/EntityForm.d.ts +5 -2
  10. package/dist/form/components/LocalChangesMenu.d.ts +11 -0
  11. package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +12 -0
  12. package/dist/form/index.d.ts +2 -1
  13. package/dist/hooks/index.d.ts +2 -0
  14. package/dist/hooks/useCollapsedGroups.d.ts +9 -0
  15. package/dist/hooks/useInternalUserManagementController.d.ts +12 -0
  16. package/dist/index.es.js +1983 -650
  17. package/dist/index.es.js.map +1 -1
  18. package/dist/index.umd.js +1981 -648
  19. package/dist/index.umd.js.map +1 -1
  20. package/dist/preview/components/UserPreview.d.ts +8 -0
  21. package/dist/preview/index.d.ts +1 -0
  22. package/dist/types/collections.d.ts +13 -0
  23. package/dist/types/entities.d.ts +5 -1
  24. package/dist/types/firecms.d.ts +15 -0
  25. package/dist/types/firecms_context.d.ts +16 -0
  26. package/dist/types/index.d.ts +1 -0
  27. package/dist/types/internal_user_management.d.ts +20 -0
  28. package/dist/types/plugins.d.ts +2 -0
  29. package/dist/types/properties.d.ts +41 -6
  30. package/dist/types/property_config.d.ts +1 -1
  31. package/dist/types/user.d.ts +1 -1
  32. package/dist/util/collections.d.ts +1 -0
  33. package/dist/util/entity_cache.d.ts +6 -1
  34. package/dist/util/make_properties_editable.d.ts +1 -2
  35. package/dist/util/objects.d.ts +1 -0
  36. package/dist/util/useStorageUploadController.d.ts +1 -0
  37. package/package.json +6 -6
  38. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +47 -47
  39. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +12 -0
  40. package/src/components/EntityCollectionView/EntityCollectionView.tsx +6 -1
  41. package/src/components/EntityView.tsx +29 -40
  42. package/src/components/ErrorView.tsx +1 -1
  43. package/src/components/HomePage/DefaultHomePage.tsx +21 -34
  44. package/src/components/HomePage/HomePageDnD.tsx +143 -83
  45. package/src/components/HomePage/RenameGroupDialog.tsx +9 -3
  46. package/src/components/PropertyCollectionView.tsx +329 -0
  47. package/src/components/PropertyConfigBadge.tsx +2 -2
  48. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +2 -1
  49. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
  50. package/src/components/UserDisplay.tsx +55 -0
  51. package/src/components/VirtualTable/fields/VirtualTableUserSelect.tsx +99 -0
  52. package/src/components/common/useColumnsIds.tsx +1 -8
  53. package/src/contexts/InternalUserManagementContext.tsx +4 -0
  54. package/src/core/EntityEditView.tsx +27 -14
  55. package/src/core/EntityEditViewFormActions.tsx +33 -18
  56. package/src/core/EntitySidePanel.tsx +9 -3
  57. package/src/core/FireCMS.tsx +22 -13
  58. package/src/core/field_configs.tsx +15 -1
  59. package/src/form/EntityForm.tsx +173 -42
  60. package/src/form/EntityFormActions.tsx +30 -15
  61. package/src/form/PropertyFieldBinding.tsx +4 -0
  62. package/src/form/components/ErrorFocus.tsx +22 -29
  63. package/src/form/components/LocalChangesMenu.tsx +144 -0
  64. package/src/form/field_bindings/UserSelectFieldBinding.tsx +94 -0
  65. package/src/form/index.tsx +5 -1
  66. package/src/hooks/index.tsx +3 -0
  67. package/src/hooks/useBrowserTitleAndIcon.tsx +1 -1
  68. package/src/hooks/useBuildNavigationController.tsx +104 -31
  69. package/src/hooks/useCollapsedGroups.ts +64 -0
  70. package/src/hooks/useFireCMSContext.tsx +6 -2
  71. package/src/hooks/useInternalUserManagementController.tsx +16 -0
  72. package/src/preview/PropertyPreview.tsx +8 -0
  73. package/src/preview/components/ReferencePreview.tsx +4 -2
  74. package/src/preview/components/UserPreview.tsx +27 -0
  75. package/src/preview/index.ts +1 -0
  76. package/src/preview/property_previews/ArrayPropertyPreview.tsx +1 -1
  77. package/src/preview/property_previews/MapPropertyPreview.tsx +2 -2
  78. package/src/preview/property_previews/NumberPropertyPreview.tsx +2 -2
  79. package/src/types/collections.ts +14 -0
  80. package/src/types/entities.ts +7 -1
  81. package/src/types/firecms.tsx +16 -0
  82. package/src/types/firecms_context.tsx +17 -0
  83. package/src/types/index.ts +1 -0
  84. package/src/types/internal_user_management.ts +24 -0
  85. package/src/types/plugins.tsx +3 -0
  86. package/src/types/properties.ts +45 -6
  87. package/src/types/property_config.tsx +1 -0
  88. package/src/types/user.ts +1 -1
  89. package/src/util/collections.ts +8 -0
  90. package/src/util/createFormexStub.tsx +4 -0
  91. package/src/util/entities.ts +1 -1
  92. package/src/util/entity_cache.ts +72 -53
  93. package/src/util/join_collections.ts +3 -3
  94. package/src/util/make_properties_editable.ts +0 -22
  95. package/src/util/objects.ts +40 -2
  96. package/src/util/useStorageUploadController.tsx +71 -34
package/dist/index.umd.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function(global, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("react-compiler-runtime"), require("react"), require("@firecms/ui"), require("notistack"), require("object-hash"), require("@firecms/formex"), require("react-router-dom"), require("fuse.js"), require("react-fast-compare"), require("date-fns"), require("date-fns/locale"), require("react-use-measure"), require("yup"), require("react-window"), require("@dnd-kit/core"), require("@dnd-kit/sortable"), require("@dnd-kit/utilities"), require("@dnd-kit/modifiers"), require("react-dropzone"), require("react-image-file-resizer"), require("@firecms/editor"), require("prism-react-renderer"), require("react-router"), require("@radix-ui/react-portal")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "react-compiler-runtime", "react", "@firecms/ui", "notistack", "object-hash", "@firecms/formex", "react-router-dom", "fuse.js", "react-fast-compare", "date-fns", "date-fns/locale", "react-use-measure", "yup", "react-window", "@dnd-kit/core", "@dnd-kit/sortable", "@dnd-kit/utilities", "@dnd-kit/modifiers", "react-dropzone", "react-image-file-resizer", "@firecms/editor", "prism-react-renderer", "react-router", "@radix-ui/react-portal"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["FireCMS Core"] = {}, global.jsxRuntime, global.reactCompilerRuntime, global.React, global.ui, global.notistack, global.hash, global.formex, global.reactRouterDom, global.Fuse, global.equal, global.dateFns, global.locales, global.useMeasure, global.yup, global.reactWindow, global.core, global.sortable, global.utilities, global.modifiers, global.reactDropzone, global.Resizer, global.editor, global.prismReactRenderer, global.reactRouter, global.Portal));
3
- })(this, (function(exports2, jsxRuntime, reactCompilerRuntime, React, ui, notistack, hash, formex, reactRouterDom, Fuse, equal, dateFns, locales, useMeasure, yup, reactWindow, core, sortable, utilities, modifiers, reactDropzone, Resizer, editor, prismReactRenderer, reactRouter, Portal) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("react-compiler-runtime"), require("react"), require("@firecms/ui"), require("notistack"), require("object-hash"), require("@firecms/formex"), require("react-router-dom"), require("fuse.js"), require("react-fast-compare"), require("date-fns"), require("date-fns/locale"), require("react-use-measure"), require("yup"), require("react-window"), require("@dnd-kit/core"), require("@dnd-kit/sortable"), require("@dnd-kit/utilities"), require("@dnd-kit/modifiers"), require("react-dropzone"), require("compressorjs"), require("@firecms/editor"), require("prism-react-renderer"), require("react-router"), require("@radix-ui/react-portal")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "react-compiler-runtime", "react", "@firecms/ui", "notistack", "object-hash", "@firecms/formex", "react-router-dom", "fuse.js", "react-fast-compare", "date-fns", "date-fns/locale", "react-use-measure", "yup", "react-window", "@dnd-kit/core", "@dnd-kit/sortable", "@dnd-kit/utilities", "@dnd-kit/modifiers", "react-dropzone", "compressorjs", "@firecms/editor", "prism-react-renderer", "react-router", "@radix-ui/react-portal"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["FireCMS Core"] = {}, global.jsxRuntime, global.reactCompilerRuntime, global.React, global.ui, global.notistack, global.hash, global.formex, global.reactRouterDom, global.Fuse, global.equal, global.dateFns, global.locales, global.useMeasure, global.yup, global.reactWindow, global.core, global.sortable, global.utilities, global.modifiers, global.reactDropzone, global.Compressor, global.editor, global.prismReactRenderer, global.reactRouter, global.Portal));
3
+ })(this, (function(exports2, jsxRuntime, reactCompilerRuntime, React, ui, notistack, hash, formex, reactRouterDom, Fuse, equal, dateFns, locales, useMeasure, yup, reactWindow, core, sortable, utilities, modifiers, reactDropzone, Compressor, editor, prismReactRenderer, reactRouter, Portal) {
4
4
  "use strict";
5
5
  function _interopNamespaceDefault(e) {
6
6
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -208,9 +208,14 @@
208
208
  * to the root of the database).
209
209
  */
210
210
  path;
211
- constructor(id, path) {
211
+ /**
212
+ * Optional database ID where the entity is stored (if multiple databases are used)
213
+ */
214
+ databaseId;
215
+ constructor(id, path, databaseId) {
212
216
  this.id = id;
213
217
  this.path = path;
218
+ this.databaseId = databaseId;
214
219
  }
215
220
  get pathWithId() {
216
221
  return `${this.path}/${this.id}`;
@@ -248,6 +253,13 @@
248
253
  function isObject(item) {
249
254
  return item && typeof item === "object" && !Array.isArray(item);
250
255
  }
256
+ function isPlainObject(obj) {
257
+ if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
258
+ return false;
259
+ }
260
+ const proto = Object.getPrototypeOf(obj);
261
+ return proto === Object.prototype;
262
+ }
251
263
  function mergeDeep(target, source, ignoreUndefined = false) {
252
264
  if (!isObject(target)) {
253
265
  return target;
@@ -268,7 +280,28 @@
268
280
  if (sourceValue instanceof Date) {
269
281
  output[key] = new Date(sourceValue.getTime());
270
282
  } else if (Array.isArray(sourceValue)) {
271
- output[key] = [...sourceValue];
283
+ if (Array.isArray(outputValue)) {
284
+ const newArray = [];
285
+ const maxLength = Math.max(outputValue.length, sourceValue.length);
286
+ for (let i = 0; i < maxLength; i++) {
287
+ const sourceItem = sourceValue[i];
288
+ const targetItem = outputValue[i];
289
+ if (i >= sourceValue.length) {
290
+ newArray[i] = targetItem;
291
+ } else if (i >= outputValue.length) {
292
+ newArray[i] = sourceItem;
293
+ } else if (sourceItem === null) {
294
+ newArray[i] = targetItem;
295
+ } else if (isObject(sourceItem) && isObject(targetItem)) {
296
+ newArray[i] = mergeDeep(targetItem, sourceItem, ignoreUndefined);
297
+ } else {
298
+ newArray[i] = sourceItem;
299
+ }
300
+ }
301
+ output[key] = newArray;
302
+ } else {
303
+ output[key] = [...sourceValue];
304
+ }
272
305
  } else if (isObject(sourceValue)) {
273
306
  if (isObject(outputValue)) {
274
307
  output[key] = mergeDeep(outputValue, sourceValue, ignoreUndefined);
@@ -515,7 +548,7 @@
515
548
  return result;
516
549
  }
517
550
  function getReferenceFrom(entity) {
518
- return new EntityReference(entity.id, entity.path);
551
+ return new EntityReference(entity.id, entity.path, entity.databaseId);
519
552
  }
520
553
  function traverseValuesProperties(inputValues, properties, operation) {
521
554
  const updatedValues = Object.entries(properties).map(([key, property]) => {
@@ -1047,6 +1080,12 @@
1047
1080
  };
1048
1081
  });
1049
1082
  };
1083
+ function getLocalChangesBackup(collection) {
1084
+ if (!collection.localChangesBackup) {
1085
+ return "manual_apply";
1086
+ }
1087
+ return collection.localChangesBackup;
1088
+ }
1050
1089
  const kebabCaseRegex = /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g;
1051
1090
  const toKebabCase = (str) => {
1052
1091
  const regExpMatchArray = str.match(kebabCaseRegex);
@@ -3503,26 +3542,6 @@
3503
3542
  });
3504
3543
  return properties;
3505
3544
  }
3506
- function makePropertiesNonEditable(properties) {
3507
- return Object.entries(properties).reduce((acc, [key, property]) => {
3508
- if (!isPropertyBuilder(property) && property.dataType === "map" && property.properties) {
3509
- const updated = {
3510
- ...property,
3511
- properties: makePropertiesNonEditable(property.properties)
3512
- };
3513
- acc[key] = updated;
3514
- }
3515
- if (isPropertyBuilder(property)) {
3516
- acc[key] = property;
3517
- } else {
3518
- acc[key] = {
3519
- ...property,
3520
- editable: false
3521
- };
3522
- }
3523
- return acc;
3524
- }, {});
3525
- }
3526
3545
  function applyModifyFunction(modifyCollection, collection, parentPaths) {
3527
3546
  if (modifyCollection) {
3528
3547
  const modified = modifyCollection({
@@ -3604,8 +3623,8 @@
3604
3623
  return target;
3605
3624
  } else {
3606
3625
  const mergedProperty = mergeDeep(target, source);
3607
- const targetEditable = Boolean(target.editable);
3608
- const sourceEditable = Boolean(source.editable);
3626
+ const targetEditable = target.editable === void 0 ? true : Boolean(target.editable);
3627
+ const sourceEditable = source.editable === void 0 ? true : Boolean(source.editable);
3609
3628
  if (source.dataType === "map" && source.properties) {
3610
3629
  const targetProperties = "properties" in target ? target.properties : {};
3611
3630
  const sourceProperties = "properties" in source ? source.properties : {};
@@ -4066,6 +4085,10 @@
4066
4085
  const useAnalyticsController = () => {
4067
4086
  return React.useContext(AnalyticsContext);
4068
4087
  };
4088
+ const InternalUserManagementContext = React.createContext({});
4089
+ const useInternalUserManagementController = () => {
4090
+ return React.useContext(InternalUserManagementContext);
4091
+ };
4069
4092
  const useFireCMSContext = () => {
4070
4093
  const authController = useAuthController();
4071
4094
  const sideDialogsController = useSideDialogsController();
@@ -4078,6 +4101,7 @@
4078
4101
  const dialogsController = useDialogsController();
4079
4102
  const customizationController = useCustomizationController();
4080
4103
  const analyticsController = useAnalyticsController();
4104
+ const userManagement = useInternalUserManagementController();
4081
4105
  const fireCMSContextRef = React.useRef({
4082
4106
  authController,
4083
4107
  sideDialogsController,
@@ -4089,7 +4113,8 @@
4089
4113
  userConfigPersistence,
4090
4114
  dialogsController,
4091
4115
  customizationController,
4092
- analyticsController
4116
+ analyticsController,
4117
+ userManagement
4093
4118
  });
4094
4119
  React.useEffect(() => {
4095
4120
  fireCMSContextRef.current = {
@@ -4103,7 +4128,8 @@
4103
4128
  userConfigPersistence,
4104
4129
  dialogsController,
4105
4130
  customizationController,
4106
- analyticsController
4131
+ analyticsController,
4132
+ userManagement
4107
4133
  };
4108
4134
  }, [authController, dialogsController, navigation, sideDialogsController]);
4109
4135
  return fireCMSContextRef.current;
@@ -4164,7 +4190,7 @@
4164
4190
  }
4165
4191
  setDataLoading(false);
4166
4192
  setDataLoadingError(void 0);
4167
- setData(entities.map(_temp$r));
4193
+ setData(entities.map(_temp$t));
4168
4194
  setNoMoreToLoad(!itemCount || entities.length < itemCount);
4169
4195
  };
4170
4196
  const onError = (error) => {
@@ -4197,7 +4223,7 @@
4197
4223
  orderBy: sortByProperty,
4198
4224
  order: currentSort
4199
4225
  }).then(onEntitiesUpdate).catch(onError);
4200
- return _temp2$d;
4226
+ return _temp2$e;
4201
4227
  }
4202
4228
  };
4203
4229
  $[4] = collection;
@@ -4245,9 +4271,9 @@
4245
4271
  }
4246
4272
  return t5;
4247
4273
  }
4248
- function _temp2$d() {
4274
+ function _temp2$e() {
4249
4275
  }
4250
- function _temp$r(e_0) {
4276
+ function _temp$t(e_0) {
4251
4277
  return {
4252
4278
  ...e_0
4253
4279
  };
@@ -4312,7 +4338,7 @@
4312
4338
  setEntity(CACHE[`${path}/${entityId}`]);
4313
4339
  setDataLoading(false);
4314
4340
  setDataLoadingError(void 0);
4315
- return _temp$q;
4341
+ return _temp$s;
4316
4342
  } else {
4317
4343
  if (entityId && path && collection) {
4318
4344
  if (dataSource.listenEntity) {
@@ -4331,7 +4357,7 @@
4331
4357
  databaseId,
4332
4358
  collection
4333
4359
  }).then(onEntityUpdate).catch(onError);
4334
- return _temp2$c;
4360
+ return _temp2$d;
4335
4361
  }
4336
4362
  } else {
4337
4363
  onEntityUpdate(void 0);
@@ -4378,9 +4404,9 @@
4378
4404
  }
4379
4405
  function _temp3$4() {
4380
4406
  }
4381
- function _temp2$c() {
4407
+ function _temp2$d() {
4382
4408
  }
4383
- function _temp$q() {
4409
+ function _temp$s() {
4384
4410
  }
4385
4411
  async function saveEntityWithCallbacks({
4386
4412
  collection,
@@ -4760,6 +4786,48 @@
4760
4786
  if (typeof window === "undefined") return false;
4761
4787
  return window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
4762
4788
  }
4789
+ function useCollapsedGroups(groupNames) {
4790
+ const [collapsedGroups, setCollapsedGroups] = React.useState(() => {
4791
+ try {
4792
+ const stored = localStorage.getItem("firecms-collapsed-groups");
4793
+ return stored ? JSON.parse(stored) : {};
4794
+ } catch {
4795
+ return {};
4796
+ }
4797
+ });
4798
+ React.useEffect(() => {
4799
+ try {
4800
+ localStorage.setItem("firecms-collapsed-groups", JSON.stringify(collapsedGroups));
4801
+ } catch {
4802
+ }
4803
+ }, [collapsedGroups]);
4804
+ React.useEffect(() => {
4805
+ if (groupNames.length === 0) return;
4806
+ const currentGroupNames = new Set(groupNames);
4807
+ setCollapsedGroups((prev) => {
4808
+ const cleaned = Object.fromEntries(Object.entries(prev).filter(([groupName]) => currentGroupNames.has(groupName)));
4809
+ const prevKeys = Object.keys(prev);
4810
+ const cleanedKeys = Object.keys(cleaned);
4811
+ if (prevKeys.length === cleanedKeys.length && prevKeys.every((key) => cleanedKeys.includes(key))) {
4812
+ return prev;
4813
+ }
4814
+ return cleaned;
4815
+ });
4816
+ }, [groupNames]);
4817
+ const isGroupCollapsed = React.useCallback((name) => {
4818
+ return !!collapsedGroups[name];
4819
+ }, [collapsedGroups]);
4820
+ const toggleGroupCollapsed = React.useCallback((name_0) => {
4821
+ setCollapsedGroups((prev_0) => ({
4822
+ ...prev_0,
4823
+ [name_0]: !prev_0[name_0]
4824
+ }));
4825
+ }, []);
4826
+ return {
4827
+ isGroupCollapsed,
4828
+ toggleGroupCollapsed
4829
+ };
4830
+ }
4763
4831
  function ErrorTooltip(props) {
4764
4832
  const $ = reactCompilerRuntime.c(2);
4765
4833
  let t0;
@@ -4780,6 +4848,7 @@
4780
4848
  tooltip
4781
4849
  } = t0;
4782
4850
  const component = error instanceof Error ? error.message : error;
4851
+ console.warn("ErrorView", JSON.stringify(error));
4783
4852
  let t1;
4784
4853
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4785
4854
  t1 = /* @__PURE__ */ jsxRuntime.jsx(ui.ErrorIcon, { className: "mx-2", size: "small", color: "error" });
@@ -4964,7 +5033,7 @@
4964
5033
  }
4965
5034
  let t9;
4966
5035
  if ($[16] !== url) {
4967
- t9 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Open image in new tab", side: "bottom", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "invisible group-hover:visible", variant: "filled", component: "a", href: url, rel: "noopener noreferrer", target: "_blank", size: "smallest", onClick: _temp$p, children: t8 }) });
5036
+ t9 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Open image in new tab", side: "bottom", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "invisible group-hover:visible", variant: "filled", component: "a", href: url, rel: "noopener noreferrer", target: "_blank", size: "smallest", onClick: _temp$r, children: t8 }) });
4968
5037
  $[16] = url;
4969
5038
  $[17] = t9;
4970
5039
  } else {
@@ -4998,7 +5067,7 @@
4998
5067
  }
4999
5068
  return t11;
5000
5069
  }
5001
- function _temp$p(e_0) {
5070
+ function _temp$r(e_0) {
5002
5071
  return e_0.stopPropagation();
5003
5072
  }
5004
5073
  function UrlComponentPreview(t0) {
@@ -5031,7 +5100,7 @@
5031
5100
  }
5032
5101
  let t3;
5033
5102
  if ($[2] !== url) {
5034
- t3 = /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "flex gap-4 break-words items-center font-medium text-primary visited:text-primary dark:visited:text-primary dark:text-primary", href: url, rel: "noopener noreferrer", onMouseDown: _temp$o, target: "_blank", children: [
5103
+ t3 = /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "flex gap-4 break-words items-center font-medium text-primary visited:text-primary dark:visited:text-primary dark:text-primary", href: url, rel: "noopener noreferrer", onMouseDown: _temp$q, target: "_blank", children: [
5035
5104
  t2,
5036
5105
  url
5037
5106
  ] });
@@ -5134,7 +5203,7 @@
5134
5203
  }
5135
5204
  let t7;
5136
5205
  if ($[24] !== t4 || $[25] !== t6 || $[26] !== url) {
5137
- t7 = /* @__PURE__ */ jsxRuntime.jsxs("a", { href: url, rel: "noopener noreferrer", target: "_blank", onClick: _temp2$b, className: "flex flex-col items-center justify-center", style: t4, children: [
5206
+ t7 = /* @__PURE__ */ jsxRuntime.jsxs("a", { href: url, rel: "noopener noreferrer", target: "_blank", onClick: _temp2$c, className: "flex flex-col items-center justify-center", style: t4, children: [
5138
5207
  t5,
5139
5208
  t6
5140
5209
  ] });
@@ -5159,10 +5228,10 @@
5159
5228
  }
5160
5229
  }
5161
5230
  }
5162
- function _temp2$b(e_0) {
5231
+ function _temp2$c(e_0) {
5163
5232
  return e_0.stopPropagation();
5164
5233
  }
5165
- function _temp$o(e) {
5234
+ function _temp$q(e) {
5166
5235
  e.preventDefault();
5167
5236
  }
5168
5237
  function VideoPreview(t0) {
@@ -5296,7 +5365,7 @@
5296
5365
  if (Array.isArray(arrayProperty.of)) {
5297
5366
  let t1;
5298
5367
  if ($[6] !== arrayProperty.of) {
5299
- t1 = arrayProperty.of.map(_temp$n);
5368
+ t1 = arrayProperty.of.map(_temp$p);
5300
5369
  $[6] = arrayProperty.of;
5301
5370
  $[7] = t1;
5302
5371
  } else {
@@ -5434,7 +5503,7 @@
5434
5503
  }
5435
5504
  return content || null;
5436
5505
  }
5437
- function _temp$n(p, i) {
5506
+ function _temp$p(p, i) {
5438
5507
  return renderGenericArrayCell(p, i);
5439
5508
  }
5440
5509
  function renderMap(property, size) {
@@ -5793,7 +5862,7 @@
5793
5862
  }
5794
5863
  let t3;
5795
5864
  if ($[11] !== t2) {
5796
- t3 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: t2 });
5865
+ t3 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex flex-col gap-2", children: t2 });
5797
5866
  $[11] = t2;
5798
5867
  $[12] = t3;
5799
5868
  } else {
@@ -6005,7 +6074,7 @@
6005
6074
  }
6006
6075
  let t0;
6007
6076
  if ($[8] !== props) {
6008
- t0 = /* @__PURE__ */ jsxRuntime.jsx(ReferencePreviewInternal, { ...props });
6077
+ t0 = /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(ReferencePreviewInternal, { ...props }) });
6009
6078
  $[8] = props;
6010
6079
  $[9] = t0;
6011
6080
  } else {
@@ -6581,7 +6650,7 @@
6581
6650
  const isArrayOrMap = childProperty.dataType === "map" || childProperty === "array";
6582
6651
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls(ui.defaultBorderMixin, "last:border-b-0 border-b"), children: [
6583
6652
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row pt-0.5 pb-0.5 gap-2", children: [
6584
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[140px] w-[25%] py-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "font-mono break-words", color: "secondary", children: childProperty.name }) }),
6653
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[140px] w-[25%] py-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "break-words font-semibold", color: "secondary", children: childProperty.name }) }),
6585
6654
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow max-w-[75%]", children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: !isArrayOrMap && /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: key_0, value: value[key_0], property: childProperty, size }) }) })
6586
6655
  ] }),
6587
6656
  isArrayOrMap && /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.cls(ui.defaultBorderMixin, "border-l pl-4 ml-2 my-2"), children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: key_0, value: value[key_0], property: childProperty, size }) })
@@ -6617,7 +6686,7 @@
6617
6686
  }
6618
6687
  let t1;
6619
6688
  if ($[1] !== value) {
6620
- t1 = Object.entries(value).map(_temp$m);
6689
+ t1 = Object.entries(value).map(_temp$o);
6621
6690
  $[1] = value;
6622
6691
  $[2] = t1;
6623
6692
  } else {
@@ -6633,11 +6702,11 @@
6633
6702
  }
6634
6703
  return t2;
6635
6704
  }
6636
- function _temp$m(t0) {
6705
+ function _temp$o(t0) {
6637
6706
  const [key, childValue] = t0;
6638
6707
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls(ui.defaultBorderMixin, "last:border-b-0 border-b"), children: [
6639
6708
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row pt-0.5 pb-0.5 gap-2", children: [
6640
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[140px] w-[25%] py-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "font-mono break-words", color: "secondary", children: key }) }, `table-cell-title-${key}-${key}`),
6709
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[140px] w-[25%] py-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "font-semibold break-words", color: "secondary", children: key }) }, `table-cell-title-${key}-${key}`),
6641
6710
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow max-w-[75%]", children: childValue && typeof childValue !== "object" && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: childValue.toString() }) }) })
6642
6711
  ] }),
6643
6712
  typeof childValue === "object" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.cls(ui.defaultBorderMixin, "border-l pl-4"), children: /* @__PURE__ */ jsxRuntime.jsx(KeyValuePreview, { value: childValue }) })
@@ -6714,7 +6783,7 @@
6714
6783
  return t3;
6715
6784
  }
6716
6785
  function NumberPropertyPreview(t0) {
6717
- const $ = reactCompilerRuntime.c(10);
6786
+ const $ = reactCompilerRuntime.c(12);
6718
6787
  const {
6719
6788
  value,
6720
6789
  property,
@@ -6732,39 +6801,178 @@
6732
6801
  }
6733
6802
  const enumValues = t1;
6734
6803
  if (!enumValues) {
6735
- let t22;
6736
- if ($[2] !== value) {
6737
- t22 = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value });
6738
- $[2] = value;
6739
- $[3] = t22;
6804
+ const t22 = size === "small" ? "text-sm" : "";
6805
+ let t32;
6806
+ if ($[2] !== t22 || $[3] !== value) {
6807
+ t32 = /* @__PURE__ */ jsxRuntime.jsx("span", { className: t22, children: value });
6808
+ $[2] = t22;
6809
+ $[3] = value;
6810
+ $[4] = t32;
6740
6811
  } else {
6741
- t22 = $[3];
6812
+ t32 = $[4];
6742
6813
  }
6743
- return t22;
6814
+ return t32;
6744
6815
  }
6745
6816
  const t2 = size !== "medium" ? "small" : "medium";
6746
6817
  let t3;
6747
- if ($[4] !== enumKey || $[5] !== enumValues || $[6] !== t2) {
6818
+ if ($[5] !== enumKey || $[6] !== enumValues || $[7] !== t2) {
6748
6819
  t3 = /* @__PURE__ */ jsxRuntime.jsx(EnumValuesChip, { enumKey, enumValues, size: t2 });
6749
- $[4] = enumKey;
6750
- $[5] = enumValues;
6751
- $[6] = t2;
6752
- $[7] = t3;
6820
+ $[5] = enumKey;
6821
+ $[6] = enumValues;
6822
+ $[7] = t2;
6823
+ $[8] = t3;
6753
6824
  } else {
6754
- t3 = $[7];
6825
+ t3 = $[8];
6755
6826
  }
6756
6827
  return t3;
6757
6828
  } else {
6758
- let t1;
6759
- if ($[8] !== value) {
6760
- t1 = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value });
6761
- $[8] = value;
6829
+ const t1 = size === "small" ? "text-sm" : "";
6830
+ let t2;
6831
+ if ($[9] !== t1 || $[10] !== value) {
6832
+ t2 = /* @__PURE__ */ jsxRuntime.jsx("span", { className: t1, children: value });
6762
6833
  $[9] = t1;
6834
+ $[10] = value;
6835
+ $[11] = t2;
6836
+ } else {
6837
+ t2 = $[11];
6838
+ }
6839
+ return t2;
6840
+ }
6841
+ }
6842
+ function UserDisplay(t0) {
6843
+ const $ = reactCompilerRuntime.c(18);
6844
+ const {
6845
+ user
6846
+ } = t0;
6847
+ if (!user) {
6848
+ let t12;
6849
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
6850
+ t12 = /* @__PURE__ */ jsxRuntime.jsx(EmptyValue, {});
6851
+ $[0] = t12;
6852
+ } else {
6853
+ t12 = $[0];
6854
+ }
6855
+ return t12;
6856
+ }
6857
+ let t1;
6858
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
6859
+ t1 = ui.cls("inline-flex items-center gap-4 px-2 py-1 rounded-xl", "bg-surface-accent-100 dark:bg-surface-accent-800", "border", ui.defaultBorderMixin);
6860
+ $[1] = t1;
6861
+ } else {
6862
+ t1 = $[1];
6863
+ }
6864
+ let t2;
6865
+ if ($[2] !== user.displayName || $[3] !== user.email || $[4] !== user.photoURL) {
6866
+ t2 = user.photoURL ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: user.photoURL, alt: user.displayName || user.email || "User", className: ui.cls("rounded-full object-cover", "w-6 h-6") }) : /* @__PURE__ */ jsxRuntime.jsx(ui.AccountCircleIcon, { className: ui.cls("text-text-secondary dark:text-text-secondary-dark", "w-6 h-6") });
6867
+ $[2] = user.displayName;
6868
+ $[3] = user.email;
6869
+ $[4] = user.photoURL;
6870
+ $[5] = t2;
6871
+ } else {
6872
+ t2 = $[5];
6873
+ }
6874
+ let t3;
6875
+ if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
6876
+ t3 = ui.cls("font-regular truncate", "text-sm");
6877
+ $[6] = t3;
6878
+ } else {
6879
+ t3 = $[6];
6880
+ }
6881
+ const t4 = user.displayName || user.email || "-";
6882
+ let t5;
6883
+ if ($[7] !== t4) {
6884
+ t5 = /* @__PURE__ */ jsxRuntime.jsx("span", { className: t3, children: t4 });
6885
+ $[7] = t4;
6886
+ $[8] = t5;
6887
+ } else {
6888
+ t5 = $[8];
6889
+ }
6890
+ let t6;
6891
+ if ($[9] !== user.displayName || $[10] !== user.email) {
6892
+ t6 = user.displayName && user.email && /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.cls("text-text-secondary dark:text-text-secondary-dark truncate", "text-xs"), children: user.email });
6893
+ $[9] = user.displayName;
6894
+ $[10] = user.email;
6895
+ $[11] = t6;
6896
+ } else {
6897
+ t6 = $[11];
6898
+ }
6899
+ let t7;
6900
+ if ($[12] !== t5 || $[13] !== t6) {
6901
+ t7 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0", children: [
6902
+ t5,
6903
+ t6
6904
+ ] });
6905
+ $[12] = t5;
6906
+ $[13] = t6;
6907
+ $[14] = t7;
6908
+ } else {
6909
+ t7 = $[14];
6910
+ }
6911
+ let t8;
6912
+ if ($[15] !== t2 || $[16] !== t7) {
6913
+ t8 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t1, children: [
6914
+ t2,
6915
+ t7
6916
+ ] });
6917
+ $[15] = t2;
6918
+ $[16] = t7;
6919
+ $[17] = t8;
6920
+ } else {
6921
+ t8 = $[17];
6922
+ }
6923
+ return t8;
6924
+ }
6925
+ function UserPreview(t0) {
6926
+ const $ = reactCompilerRuntime.c(8);
6927
+ const {
6928
+ value
6929
+ } = t0;
6930
+ const {
6931
+ getUser
6932
+ } = useInternalUserManagementController();
6933
+ if (!value) {
6934
+ let t12;
6935
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
6936
+ t12 = /* @__PURE__ */ jsxRuntime.jsx(EmptyValue, {});
6937
+ $[0] = t12;
6938
+ } else {
6939
+ t12 = $[0];
6940
+ }
6941
+ return t12;
6942
+ }
6943
+ let t1;
6944
+ if ($[1] !== getUser || $[2] !== value) {
6945
+ t1 = getUser(value);
6946
+ $[1] = getUser;
6947
+ $[2] = value;
6948
+ $[3] = t1;
6949
+ } else {
6950
+ t1 = $[3];
6951
+ }
6952
+ const user = t1;
6953
+ if (!user) {
6954
+ let t22;
6955
+ if ($[4] !== value) {
6956
+ t22 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Typography, { variant: "caption", color: "secondary", children: [
6957
+ "User not found: ",
6958
+ value
6959
+ ] });
6960
+ $[4] = value;
6961
+ $[5] = t22;
6763
6962
  } else {
6764
- t1 = $[9];
6963
+ t22 = $[5];
6765
6964
  }
6766
- return t1;
6965
+ return t22;
6767
6966
  }
6967
+ let t2;
6968
+ if ($[6] !== user) {
6969
+ t2 = /* @__PURE__ */ jsxRuntime.jsx(UserDisplay, { user });
6970
+ $[6] = user;
6971
+ $[7] = t2;
6972
+ } else {
6973
+ t2 = $[7];
6974
+ }
6975
+ return t2;
6768
6976
  }
6769
6977
  const PropertyPreview = React.memo(function PropertyPreview2(props) {
6770
6978
  const $ = reactCompilerRuntime.c(31);
@@ -6866,21 +7074,25 @@
6866
7074
  }
6867
7075
  content = t02;
6868
7076
  } else {
6869
- if (stringProperty.reference) {
6870
- if (typeof stringProperty.reference.path === "string") {
6871
- content = /* @__PURE__ */ jsxRuntime.jsx(ReferencePreview, { disabled: !stringProperty.reference.path, previewProperties: stringProperty.reference.previewProperties, includeId: stringProperty.reference.includeId, includeEntityLink: stringProperty.reference.includeEntityLink, size: props.size, reference: new EntityReference(value, stringProperty.reference.path) });
6872
- } else {
6873
- let t02;
6874
- if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
6875
- t02 = /* @__PURE__ */ jsxRuntime.jsx(EmptyValue, {});
6876
- $[23] = t02;
7077
+ if (stringProperty.userSelect) {
7078
+ content = /* @__PURE__ */ jsxRuntime.jsx(UserPreview, { value, property: stringProperty, propertyKey, size: props.size });
7079
+ } else {
7080
+ if (stringProperty.reference) {
7081
+ if (typeof stringProperty.reference.path === "string") {
7082
+ content = /* @__PURE__ */ jsxRuntime.jsx(ReferencePreview, { disabled: !stringProperty.reference.path, previewProperties: stringProperty.reference.previewProperties, includeId: stringProperty.reference.includeId, includeEntityLink: stringProperty.reference.includeEntityLink, size: props.size, reference: new EntityReference(value, stringProperty.reference.path) });
6877
7083
  } else {
6878
- t02 = $[23];
7084
+ let t02;
7085
+ if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
7086
+ t02 = /* @__PURE__ */ jsxRuntime.jsx(EmptyValue, {});
7087
+ $[23] = t02;
7088
+ } else {
7089
+ t02 = $[23];
7090
+ }
7091
+ content = t02;
6879
7092
  }
6880
- content = t02;
7093
+ } else {
7094
+ content = /* @__PURE__ */ jsxRuntime.jsx(StringPropertyPreview, { ...props, property: stringProperty, value });
6881
7095
  }
6882
- } else {
6883
- content = /* @__PURE__ */ jsxRuntime.jsx(StringPropertyPreview, { ...props, property: stringProperty, value });
6884
7096
  }
6885
7097
  }
6886
7098
  }
@@ -7173,98 +7385,467 @@
7173
7385
  }
7174
7386
  return t3;
7175
7387
  });
7176
- function EntityView({
7177
- entity,
7178
- collection,
7179
- path,
7180
- className
7181
- }) {
7182
- const authController = useAuthController();
7183
- const customizationController = useCustomizationController();
7184
- const resolvedCollection = React.useMemo(() => resolveCollection({
7185
- collection,
7186
- path,
7187
- entityId: entity.id,
7188
- values: entity.values,
7189
- propertyConfigs: customizationController.propertyConfigs,
7190
- authController
7191
- }), [collection, path, entity, customizationController.propertyConfigs]);
7192
- const properties = resolvedCollection.properties;
7193
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full " + className, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full mb-4", children: [
7194
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls(ui.defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0"), children: [
7195
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center w-1/4", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pl-2 text-sm text-surface-600", children: "Id" }) }),
7196
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow p-2 ml-2 w-3/4 text-surface-900 dark:text-white min-h-[56px] flex items-center", children: [
7197
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-grow mr-2", children: entity.id }),
7198
- customizationController?.entityLinkBuilder && /* @__PURE__ */ jsxRuntime.jsx("a", { href: customizationController.entityLinkBuilder({
7199
- entity
7200
- }), rel: "noopener noreferrer", target: "_blank", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.OpenInNewIcon, { size: "small" }) }) })
7201
- ] })
7202
- ] }),
7203
- Object.entries(properties).map(([key, property]) => {
7204
- const value = entity.values?.[key];
7205
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls(ui.defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0"), children: [
7206
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center w-1/4", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pl-2 text-sm text-surface-600", children: property.name }) }),
7207
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow p-2 ml-2 w-3/4 text-surface-900 dark:text-white min-h-[56px] flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
7208
- PropertyPreview,
7209
- {
7210
- propertyKey: key,
7211
- value,
7212
- property,
7213
- size: "medium"
7214
- }
7215
- ) })
7216
- ] }, `reference_previews_${key}`);
7217
- })
7218
- ] }) });
7388
+ function buildPropertyLabelAndGetProperty(properties, key) {
7389
+ if (!key) return {
7390
+ label: "",
7391
+ property: void 0
7392
+ };
7393
+ const segments = [];
7394
+ const re = /([^[.\]]+)|\[(\d+)\]/g;
7395
+ let m;
7396
+ while ((m = re.exec(key)) !== null) {
7397
+ if (m[1] !== void 0) segments.push(m[1]);
7398
+ else if (m[2] !== void 0) segments.push(Number(m[2]));
7399
+ }
7400
+ let currentProps = properties;
7401
+ let currentProp;
7402
+ let lastLabel = "";
7403
+ const getArrayOfProp = (p) => {
7404
+ if (!p || p.dataType !== "array") return void 0;
7405
+ return Array.isArray(p.of) ? p.of[0] : p.of;
7406
+ };
7407
+ for (const seg of segments) {
7408
+ if (typeof seg === "number") {
7409
+ lastLabel = `[${seg}]`;
7410
+ if (currentProp?.dataType === "array") {
7411
+ currentProp = getArrayOfProp(currentProp);
7412
+ if (currentProp?.dataType === "map" && currentProp.properties) {
7413
+ currentProps = currentProp.properties;
7414
+ } else {
7415
+ currentProps = void 0;
7416
+ }
7417
+ } else {
7418
+ currentProp = void 0;
7419
+ currentProps = void 0;
7420
+ }
7421
+ continue;
7422
+ }
7423
+ if (currentProps && currentProps[seg]) {
7424
+ const nextProp = currentProps[seg];
7425
+ currentProp = nextProp;
7426
+ lastLabel = nextProp.name || String(seg);
7427
+ if (nextProp.dataType === "map" && nextProp.properties) {
7428
+ currentProps = nextProp.properties;
7429
+ } else if (nextProp.dataType === "array") {
7430
+ currentProps = void 0;
7431
+ } else {
7432
+ currentProps = void 0;
7433
+ }
7434
+ } else {
7435
+ currentProp = void 0;
7436
+ currentProps = void 0;
7437
+ lastLabel = String(seg);
7438
+ }
7439
+ }
7440
+ return {
7441
+ label: lastLabel,
7442
+ property: currentProp
7443
+ };
7219
7444
  }
7220
- function VirtualTableInput(props) {
7221
- const $ = reactCompilerRuntime.c(22);
7222
- const ref = React.useRef(null);
7445
+ const pathEndsWithIndex = (p) => /\[\d+\]$/.test(p);
7446
+ const PropertyCollectionView = (t0) => {
7447
+ const $ = reactCompilerRuntime.c(89);
7223
7448
  const {
7224
- value,
7225
- multiline,
7226
- updateValue,
7227
- focused
7228
- } = props;
7229
- const prevValue = React.useRef(value);
7230
- const [internalValue, setInternalValue] = React.useState(value);
7231
- const focusedState = React.useRef(false);
7232
- let t0;
7233
- if ($[0] !== internalValue || $[1] !== value) {
7234
- t0 = () => {
7235
- if (prevValue.current !== value && value !== internalValue) {
7236
- setInternalValue(value);
7449
+ data,
7450
+ properties,
7451
+ baseKey: t1,
7452
+ suppressHeader: t2,
7453
+ size: t3
7454
+ } = t0;
7455
+ const baseKey = t1 === void 0 ? "" : t1;
7456
+ const suppressHeader = t2 === void 0 ? false : t2;
7457
+ const size = t3 === void 0 ? "small" : t3;
7458
+ const isTopLevel = !!baseKey && !baseKey.includes(".") && !baseKey.includes("[");
7459
+ if (Array.isArray(data)) {
7460
+ let t4;
7461
+ if ($[0] !== baseKey || $[1] !== properties) {
7462
+ t4 = baseKey ? buildPropertyLabelAndGetProperty(properties, baseKey) : {
7463
+ label: "",
7464
+ property: void 0
7465
+ };
7466
+ $[0] = baseKey;
7467
+ $[1] = properties;
7468
+ $[2] = t4;
7469
+ } else {
7470
+ t4 = $[2];
7471
+ }
7472
+ const {
7473
+ label: arrayLabel,
7474
+ property
7475
+ } = t4;
7476
+ const ofProp = property?.dataType === "array" ? Array.isArray(property.of) ? property.of[0] : property.of : void 0;
7477
+ const isArrayOfMaps = ofProp?.dataType === "map";
7478
+ const isArrayOfPrimitives = property?.dataType === "array" && ofProp && ofProp.dataType !== "map";
7479
+ if (baseKey && property && isArrayOfPrimitives) {
7480
+ const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${ui.defaultBorderMixin} last:border-b-0` : ""}`;
7481
+ let t62;
7482
+ if ($[3] !== arrayLabel) {
7483
+ t62 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-4 pr-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", className: "break-words", children: arrayLabel }) });
7484
+ $[3] = arrayLabel;
7485
+ $[4] = t62;
7486
+ } else {
7487
+ t62 = $[4];
7237
7488
  }
7238
- prevValue.current = value;
7239
- };
7240
- $[0] = internalValue;
7241
- $[1] = value;
7242
- $[2] = t0;
7243
- } else {
7244
- t0 = $[2];
7245
- }
7246
- let t1;
7247
- if ($[3] !== value) {
7248
- t1 = [value];
7249
- $[3] = value;
7250
- $[4] = t1;
7251
- } else {
7252
- t1 = $[4];
7253
- }
7254
- React.useEffect(t0, t1);
7255
- let t2;
7256
- if ($[5] !== internalValue || $[6] !== updateValue || $[7] !== value) {
7257
- t2 = () => {
7258
- const emptyInitialValue = !value;
7259
- if (emptyInitialValue && !internalValue) {
7260
- return;
7489
+ let t72;
7490
+ if ($[5] !== baseKey || $[6] !== data || $[7] !== property || $[8] !== size) {
7491
+ t72 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-8", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: baseKey, value: data, property, size }) });
7492
+ $[5] = baseKey;
7493
+ $[6] = data;
7494
+ $[7] = property;
7495
+ $[8] = size;
7496
+ $[9] = t72;
7497
+ } else {
7498
+ t72 = $[9];
7261
7499
  }
7262
- if (internalValue !== value) {
7263
- prevValue.current = internalValue;
7264
- updateValue(internalValue);
7500
+ let t82;
7501
+ if ($[10] !== t52 || $[11] !== t62 || $[12] !== t72) {
7502
+ t82 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t52, children: [
7503
+ t62,
7504
+ t72
7505
+ ] });
7506
+ $[10] = t52;
7507
+ $[11] = t62;
7508
+ $[12] = t72;
7509
+ $[13] = t82;
7510
+ } else {
7511
+ t82 = $[13];
7265
7512
  }
7266
- };
7267
- $[5] = internalValue;
7513
+ return t82;
7514
+ }
7515
+ const t5 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${ui.defaultBorderMixin} last:border-b-0` : ""}`;
7516
+ let t6;
7517
+ if ($[14] !== arrayLabel || $[15] !== baseKey || $[16] !== suppressHeader) {
7518
+ t6 = baseKey && arrayLabel && !suppressHeader && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", children: arrayLabel });
7519
+ $[14] = arrayLabel;
7520
+ $[15] = baseKey;
7521
+ $[16] = suppressHeader;
7522
+ $[17] = t6;
7523
+ } else {
7524
+ t6 = $[17];
7525
+ }
7526
+ const t7 = baseKey ? `pl-4 mt-1 border-l ${ui.defaultBorderMixin}` : "";
7527
+ let t8;
7528
+ if ($[18] !== baseKey || $[19] !== data || $[20] !== isArrayOfMaps || $[21] !== ofProp || $[22] !== properties || $[23] !== size) {
7529
+ let t92;
7530
+ if ($[25] !== baseKey || $[26] !== isArrayOfMaps || $[27] !== ofProp || $[28] !== properties || $[29] !== size) {
7531
+ t92 = (item, index) => {
7532
+ if (item === null || item === void 0) {
7533
+ return null;
7534
+ }
7535
+ const currentKey = baseKey ? `${baseKey}[${index}]` : `[${index}]`;
7536
+ const itemHeader = isArrayOfMaps && ofProp?.name ? `${ofProp.name} [${index}]` : `[${index}]`;
7537
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1", children: [
7538
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", children: itemHeader }),
7539
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `pl-4 mt-1 border-l ${ui.defaultBorderMixin}`, children: /* @__PURE__ */ jsxRuntime.jsx(PropertyCollectionView, { data: item, properties, baseKey: currentKey, suppressHeader: true, size }) })
7540
+ ] }, currentKey);
7541
+ };
7542
+ $[25] = baseKey;
7543
+ $[26] = isArrayOfMaps;
7544
+ $[27] = ofProp;
7545
+ $[28] = properties;
7546
+ $[29] = size;
7547
+ $[30] = t92;
7548
+ } else {
7549
+ t92 = $[30];
7550
+ }
7551
+ t8 = data.map(t92);
7552
+ $[18] = baseKey;
7553
+ $[19] = data;
7554
+ $[20] = isArrayOfMaps;
7555
+ $[21] = ofProp;
7556
+ $[22] = properties;
7557
+ $[23] = size;
7558
+ $[24] = t8;
7559
+ } else {
7560
+ t8 = $[24];
7561
+ }
7562
+ let t9;
7563
+ if ($[31] !== t7 || $[32] !== t8) {
7564
+ t9 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: t7, children: t8 });
7565
+ $[31] = t7;
7566
+ $[32] = t8;
7567
+ $[33] = t9;
7568
+ } else {
7569
+ t9 = $[33];
7570
+ }
7571
+ let t10;
7572
+ if ($[34] !== t5 || $[35] !== t6 || $[36] !== t9) {
7573
+ t10 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t5, children: [
7574
+ t6,
7575
+ t9
7576
+ ] });
7577
+ $[34] = t5;
7578
+ $[35] = t6;
7579
+ $[36] = t9;
7580
+ $[37] = t10;
7581
+ } else {
7582
+ t10 = $[37];
7583
+ }
7584
+ return t10;
7585
+ }
7586
+ if (typeof data === "object" && data !== null) {
7587
+ let t4;
7588
+ if ($[38] !== baseKey || $[39] !== properties) {
7589
+ t4 = baseKey ? buildPropertyLabelAndGetProperty(properties, baseKey) : {
7590
+ label: "",
7591
+ property: void 0
7592
+ };
7593
+ $[38] = baseKey;
7594
+ $[39] = properties;
7595
+ $[40] = t4;
7596
+ } else {
7597
+ t4 = $[40];
7598
+ }
7599
+ const {
7600
+ label,
7601
+ property: property_0
7602
+ } = t4;
7603
+ if (baseKey && (!property_0 || property_0.dataType !== "map" || !property_0.properties)) {
7604
+ if (!property_0) {
7605
+ return null;
7606
+ }
7607
+ const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${ui.defaultBorderMixin} last:border-b-0` : ""}`;
7608
+ let t62;
7609
+ if ($[41] !== label) {
7610
+ t62 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-4 pr-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", className: "break-words", children: label }) });
7611
+ $[41] = label;
7612
+ $[42] = t62;
7613
+ } else {
7614
+ t62 = $[42];
7615
+ }
7616
+ let t72;
7617
+ if ($[43] !== baseKey || $[44] !== data || $[45] !== property_0 || $[46] !== size) {
7618
+ t72 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-8", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: baseKey, value: data, property: property_0, size }) });
7619
+ $[43] = baseKey;
7620
+ $[44] = data;
7621
+ $[45] = property_0;
7622
+ $[46] = size;
7623
+ $[47] = t72;
7624
+ } else {
7625
+ t72 = $[47];
7626
+ }
7627
+ let t82;
7628
+ if ($[48] !== t52 || $[49] !== t62 || $[50] !== t72) {
7629
+ t82 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t52, children: [
7630
+ t62,
7631
+ t72
7632
+ ] });
7633
+ $[48] = t52;
7634
+ $[49] = t62;
7635
+ $[50] = t72;
7636
+ $[51] = t82;
7637
+ } else {
7638
+ t82 = $[51];
7639
+ }
7640
+ return t82;
7641
+ }
7642
+ let t5;
7643
+ if ($[52] !== baseKey || $[53] !== property_0 || $[54] !== suppressHeader) {
7644
+ t5 = baseKey && !suppressHeader && property_0?.dataType === "map" && (property_0.name || !pathEndsWithIndex(baseKey));
7645
+ $[52] = baseKey;
7646
+ $[53] = property_0;
7647
+ $[54] = suppressHeader;
7648
+ $[55] = t5;
7649
+ } else {
7650
+ t5 = $[55];
7651
+ }
7652
+ const showMapHeader = t5;
7653
+ const headerText = property_0?.name || label;
7654
+ const t6 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${ui.defaultBorderMixin} last:border-b-0` : ""}`;
7655
+ let t7;
7656
+ if ($[56] !== headerText || $[57] !== showMapHeader) {
7657
+ t7 = showMapHeader && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", children: headerText });
7658
+ $[56] = headerText;
7659
+ $[57] = showMapHeader;
7660
+ $[58] = t7;
7661
+ } else {
7662
+ t7 = $[58];
7663
+ }
7664
+ const t8 = baseKey ? `pl-4 mt-1 border-l ${ui.defaultBorderMixin}` : "";
7665
+ let t9;
7666
+ if ($[59] !== baseKey || $[60] !== data || $[61] !== properties || $[62] !== size) {
7667
+ let t102;
7668
+ if ($[64] !== baseKey || $[65] !== properties || $[66] !== size) {
7669
+ t102 = (t112) => {
7670
+ const [key, value] = t112;
7671
+ if (value === null || value === void 0) {
7672
+ return null;
7673
+ }
7674
+ const currentKey_0 = baseKey ? `${baseKey}.${key}` : key;
7675
+ return /* @__PURE__ */ jsxRuntime.jsx(PropertyCollectionView, { data: value, properties, baseKey: currentKey_0, size }, currentKey_0);
7676
+ };
7677
+ $[64] = baseKey;
7678
+ $[65] = properties;
7679
+ $[66] = size;
7680
+ $[67] = t102;
7681
+ } else {
7682
+ t102 = $[67];
7683
+ }
7684
+ t9 = Object.entries(data).map(t102);
7685
+ $[59] = baseKey;
7686
+ $[60] = data;
7687
+ $[61] = properties;
7688
+ $[62] = size;
7689
+ $[63] = t9;
7690
+ } else {
7691
+ t9 = $[63];
7692
+ }
7693
+ let t10;
7694
+ if ($[68] !== t8 || $[69] !== t9) {
7695
+ t10 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: t8, children: t9 });
7696
+ $[68] = t8;
7697
+ $[69] = t9;
7698
+ $[70] = t10;
7699
+ } else {
7700
+ t10 = $[70];
7701
+ }
7702
+ let t11;
7703
+ if ($[71] !== t10 || $[72] !== t6 || $[73] !== t7) {
7704
+ t11 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t6, children: [
7705
+ t7,
7706
+ t10
7707
+ ] });
7708
+ $[71] = t10;
7709
+ $[72] = t6;
7710
+ $[73] = t7;
7711
+ $[74] = t11;
7712
+ } else {
7713
+ t11 = $[74];
7714
+ }
7715
+ return t11;
7716
+ }
7717
+ if (baseKey) {
7718
+ let t4;
7719
+ if ($[75] !== baseKey || $[76] !== properties) {
7720
+ t4 = buildPropertyLabelAndGetProperty(properties, baseKey);
7721
+ $[75] = baseKey;
7722
+ $[76] = properties;
7723
+ $[77] = t4;
7724
+ } else {
7725
+ t4 = $[77];
7726
+ }
7727
+ const {
7728
+ label: label_0,
7729
+ property: property_1
7730
+ } = t4;
7731
+ if (!property_1) {
7732
+ return null;
7733
+ }
7734
+ const t5 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${ui.defaultBorderMixin} last:border-b-0` : ""}`;
7735
+ let t6;
7736
+ if ($[78] !== label_0) {
7737
+ t6 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-4 pr-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", className: "break-words", children: label_0 }) });
7738
+ $[78] = label_0;
7739
+ $[79] = t6;
7740
+ } else {
7741
+ t6 = $[79];
7742
+ }
7743
+ let t7;
7744
+ if ($[80] !== baseKey || $[81] !== data || $[82] !== property_1 || $[83] !== size) {
7745
+ t7 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-8", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: baseKey, value: data, property: property_1, size }) });
7746
+ $[80] = baseKey;
7747
+ $[81] = data;
7748
+ $[82] = property_1;
7749
+ $[83] = size;
7750
+ $[84] = t7;
7751
+ } else {
7752
+ t7 = $[84];
7753
+ }
7754
+ let t8;
7755
+ if ($[85] !== t5 || $[86] !== t6 || $[87] !== t7) {
7756
+ t8 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t5, children: [
7757
+ t6,
7758
+ t7
7759
+ ] });
7760
+ $[85] = t5;
7761
+ $[86] = t6;
7762
+ $[87] = t7;
7763
+ $[88] = t8;
7764
+ } else {
7765
+ t8 = $[88];
7766
+ }
7767
+ return t8;
7768
+ }
7769
+ return null;
7770
+ };
7771
+ function EntityView({
7772
+ entity,
7773
+ collection,
7774
+ path,
7775
+ className
7776
+ }) {
7777
+ const authController = useAuthController();
7778
+ const customizationController = useCustomizationController();
7779
+ const resolvedCollection = React.useMemo(() => resolveCollection({
7780
+ collection,
7781
+ path,
7782
+ entityId: entity.id,
7783
+ values: entity.values,
7784
+ propertyConfigs: customizationController.propertyConfigs,
7785
+ authController
7786
+ }), [collection, path, entity, customizationController.propertyConfigs]);
7787
+ const properties = resolvedCollection.properties;
7788
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full " + className, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full mb-4 p-4", children: [
7789
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `grid grid-cols-12 gap-x-4 py-4 items-start border-b ${ui.defaultBorderMixin}`, children: [
7790
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-4 pr-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", className: "break-words", children: "Id" }) }),
7791
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow text-surface-900 dark:text-white flex items-center", children: [
7792
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-grow mr-2", children: entity.id }),
7793
+ customizationController?.entityLinkBuilder && /* @__PURE__ */ jsxRuntime.jsx("a", { href: customizationController.entityLinkBuilder({
7794
+ entity
7795
+ }), rel: "noopener noreferrer", target: "_blank", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.OpenInNewIcon, { size: "small" }) }) })
7796
+ ] }) })
7797
+ ] }),
7798
+ /* @__PURE__ */ jsxRuntime.jsx(PropertyCollectionView, { data: entity.values, properties, size: "medium" })
7799
+ ] }) });
7800
+ }
7801
+ function VirtualTableInput(props) {
7802
+ const $ = reactCompilerRuntime.c(22);
7803
+ const ref = React.useRef(null);
7804
+ const {
7805
+ value,
7806
+ multiline,
7807
+ updateValue,
7808
+ focused
7809
+ } = props;
7810
+ const prevValue = React.useRef(value);
7811
+ const [internalValue, setInternalValue] = React.useState(value);
7812
+ const focusedState = React.useRef(false);
7813
+ let t0;
7814
+ if ($[0] !== internalValue || $[1] !== value) {
7815
+ t0 = () => {
7816
+ if (prevValue.current !== value && value !== internalValue) {
7817
+ setInternalValue(value);
7818
+ }
7819
+ prevValue.current = value;
7820
+ };
7821
+ $[0] = internalValue;
7822
+ $[1] = value;
7823
+ $[2] = t0;
7824
+ } else {
7825
+ t0 = $[2];
7826
+ }
7827
+ let t1;
7828
+ if ($[3] !== value) {
7829
+ t1 = [value];
7830
+ $[3] = value;
7831
+ $[4] = t1;
7832
+ } else {
7833
+ t1 = $[4];
7834
+ }
7835
+ React.useEffect(t0, t1);
7836
+ let t2;
7837
+ if ($[5] !== internalValue || $[6] !== updateValue || $[7] !== value) {
7838
+ t2 = () => {
7839
+ const emptyInitialValue = !value;
7840
+ if (emptyInitialValue && !internalValue) {
7841
+ return;
7842
+ }
7843
+ if (internalValue !== value) {
7844
+ prevValue.current = internalValue;
7845
+ updateValue(internalValue);
7846
+ }
7847
+ };
7848
+ $[5] = internalValue;
7268
7849
  $[6] = updateValue;
7269
7850
  $[7] = value;
7270
7851
  $[8] = t2;
@@ -7401,7 +7982,7 @@
7401
7982
  console.trace("onChange");
7402
7983
  if (valueType === "number") {
7403
7984
  if (multiple) {
7404
- const newValue = updatedValue.map(_temp$l);
7985
+ const newValue = updatedValue.map(_temp$n);
7405
7986
  updateValue(newValue);
7406
7987
  } else {
7407
7988
  updateValue(parseFloat(updatedValue));
@@ -7438,7 +8019,7 @@
7438
8019
  const renderValue = t3;
7439
8020
  let t4;
7440
8021
  if ($[10] !== disabled || $[11] !== enumValues || $[12] !== internalValue || $[13] !== multiple || $[14] !== onChange || $[15] !== renderValue || $[16] !== small || $[17] !== validValue) {
7441
- t4 = multiple ? /* @__PURE__ */ jsxRuntime.jsx(ui.MultiSelect, { inputRef: ref, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, includeClear: false, useChips: false, value: validValue ? internalValue.map(_temp2$a) : [], onValueChange: onChange, children: enumValues?.map((enumConfig) => /* @__PURE__ */ jsxRuntime.jsx(ui.MultiSelectItem, { value: String(enumConfig.id), children: /* @__PURE__ */ jsxRuntime.jsx(EnumValuesChip, { enumKey: enumConfig.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig.id)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { inputRef: ref, size: "large", fullWidth: true, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, padding: false, value: validValue ? internalValue?.toString() : "", onValueChange: onChange, renderValue, children: enumValues?.map((enumConfig_0) => /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: String(enumConfig_0.id), children: /* @__PURE__ */ jsxRuntime.jsx(EnumValuesChip, { enumKey: enumConfig_0.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig_0.id)) });
8022
+ t4 = multiple ? /* @__PURE__ */ jsxRuntime.jsx(ui.MultiSelect, { inputRef: ref, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, includeClear: false, useChips: false, value: validValue ? internalValue.map(_temp2$b) : [], onValueChange: onChange, children: enumValues?.map((enumConfig) => /* @__PURE__ */ jsxRuntime.jsx(ui.MultiSelectItem, { value: String(enumConfig.id), children: /* @__PURE__ */ jsxRuntime.jsx(EnumValuesChip, { enumKey: enumConfig.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig.id)) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { inputRef: ref, size: "large", fullWidth: true, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, padding: false, value: validValue ? internalValue?.toString() : "", onValueChange: onChange, renderValue, children: enumValues?.map((enumConfig_0) => /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: String(enumConfig_0.id), children: /* @__PURE__ */ jsxRuntime.jsx(EnumValuesChip, { enumKey: enumConfig_0.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig_0.id)) });
7442
8023
  $[10] = disabled;
7443
8024
  $[11] = enumValues;
7444
8025
  $[12] = internalValue;
@@ -7453,10 +8034,10 @@
7453
8034
  }
7454
8035
  return t4;
7455
8036
  }
7456
- function _temp2$a(v_0) {
8037
+ function _temp2$b(v_0) {
7457
8038
  return v_0.toString();
7458
8039
  }
7459
- function _temp$l(v) {
8040
+ function _temp$n(v) {
7460
8041
  return parseFloat(v);
7461
8042
  }
7462
8043
  function VirtualTableNumberInput(props) {
@@ -7587,6 +8168,89 @@
7587
8168
  }
7588
8169
  return t4;
7589
8170
  }
8171
+ function VirtualTableUserSelect(props) {
8172
+ const $ = reactCompilerRuntime.c(15);
8173
+ const {
8174
+ internalValue,
8175
+ disabled,
8176
+ focused,
8177
+ updateValue,
8178
+ multiple
8179
+ } = props;
8180
+ const {
8181
+ users,
8182
+ getUser
8183
+ } = useInternalUserManagementController();
8184
+ const validValue = Array.isArray(internalValue) && multiple || !Array.isArray(internalValue) && !multiple;
8185
+ const ref = React.useRef(null);
8186
+ let t0;
8187
+ let t1;
8188
+ if ($[0] !== focused) {
8189
+ t0 = () => {
8190
+ if (ref.current && focused) {
8191
+ ref.current?.focus({
8192
+ preventScroll: true
8193
+ });
8194
+ }
8195
+ };
8196
+ t1 = [focused, ref];
8197
+ $[0] = focused;
8198
+ $[1] = t0;
8199
+ $[2] = t1;
8200
+ } else {
8201
+ t0 = $[1];
8202
+ t1 = $[2];
8203
+ }
8204
+ React.useEffect(t0, t1);
8205
+ let t2;
8206
+ if ($[3] !== updateValue) {
8207
+ t2 = (updatedValue) => {
8208
+ if (!updatedValue) {
8209
+ updateValue(null);
8210
+ } else {
8211
+ updateValue(updatedValue);
8212
+ }
8213
+ };
8214
+ $[3] = updateValue;
8215
+ $[4] = t2;
8216
+ } else {
8217
+ t2 = $[4];
8218
+ }
8219
+ const onChange = t2;
8220
+ let t3;
8221
+ if ($[5] !== getUser) {
8222
+ t3 = (userId) => {
8223
+ const user = getUser(userId);
8224
+ return /* @__PURE__ */ jsxRuntime.jsx(UserDisplay, { user });
8225
+ };
8226
+ $[5] = getUser;
8227
+ $[6] = t3;
8228
+ } else {
8229
+ t3 = $[6];
8230
+ }
8231
+ const renderValue = t3;
8232
+ let t4;
8233
+ if ($[7] !== disabled || $[8] !== internalValue || $[9] !== multiple || $[10] !== onChange || $[11] !== renderValue || $[12] !== users || $[13] !== validValue) {
8234
+ t4 = multiple ? /* @__PURE__ */ jsxRuntime.jsx(ui.MultiSelect, { inputRef: ref, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, includeClear: false, useChips: false, value: validValue ? internalValue : [], onValueChange: onChange, children: users?.map(_temp$m) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { inputRef: ref, size: "large", fullWidth: true, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, padding: false, value: validValue ? internalValue : "", onValueChange: onChange, renderValue, children: users?.map(_temp2$a) });
8235
+ $[7] = disabled;
8236
+ $[8] = internalValue;
8237
+ $[9] = multiple;
8238
+ $[10] = onChange;
8239
+ $[11] = renderValue;
8240
+ $[12] = users;
8241
+ $[13] = validValue;
8242
+ $[14] = t4;
8243
+ } else {
8244
+ t4 = $[14];
8245
+ }
8246
+ return t4;
8247
+ }
8248
+ function _temp2$a(user_1) {
8249
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: user_1.uid, children: /* @__PURE__ */ jsxRuntime.jsx(UserDisplay, { user: user_1 }) }, user_1.uid);
8250
+ }
8251
+ function _temp$m(user_0) {
8252
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.MultiSelectItem, { value: user_0.uid, children: /* @__PURE__ */ jsxRuntime.jsx(UserDisplay, { user: user_0 }) }, user_0.uid);
8253
+ }
7590
8254
  class ErrorBoundary extends React.Component {
7591
8255
  constructor(props) {
7592
8256
  super(props);
@@ -7634,7 +8298,8 @@
7634
8298
  const processFile = storage?.processFile;
7635
8299
  const metadata = storage?.metadata;
7636
8300
  const size = multipleFilesSupported ? "medium" : "large";
7637
- const compression = storage?.imageCompression;
8301
+ const imageResize = storage?.imageResize;
8302
+ const legacyCompression = storage?.imageCompression;
7638
8303
  const internalInitialValue = getInternalInitialValue(multipleFilesSupported, value, metadata, size);
7639
8304
  const [initialValue, setInitialValue] = React.useState(value);
7640
8305
  const [internalValue, setInternalValue] = React.useState(internalInitialValue);
@@ -7706,6 +8371,11 @@
7706
8371
  onChange(fieldValue ? fieldValue[0] : null);
7707
8372
  }
7708
8373
  }, [internalValue, multipleFilesSupported, onChange, storage, storageSource]);
8374
+ const onFileUploadError = React.useCallback((entry_0) => {
8375
+ console.debug("onFileUploadError", entry_0);
8376
+ const newValue_0 = internalValue.filter((item) => item.id !== entry_0.id);
8377
+ setInternalValue(newValue_0);
8378
+ }, [internalValue]);
7709
8379
  const onFilesAdded = React.useCallback(async (acceptedFiles) => {
7710
8380
  if (!acceptedFiles.length || disabled) return;
7711
8381
  if (processFile) {
@@ -7724,8 +8394,8 @@
7724
8394
  let newInternalValue;
7725
8395
  if (multipleFilesSupported) {
7726
8396
  newInternalValue = [...internalValue, ...await Promise.all(acceptedFiles.map(async (file_2) => {
7727
- if (compression && compressionFormat(file_2)) {
7728
- file_2 = await resizeAndCompressImage(file_2, compression);
8397
+ if ((imageResize || legacyCompression) && isImageFile(file_2)) {
8398
+ file_2 = await resizeImage(file_2, imageResize, legacyCompression);
7729
8399
  }
7730
8400
  return {
7731
8401
  id: getRandomId$2(),
@@ -7737,8 +8407,8 @@
7737
8407
  }))];
7738
8408
  } else {
7739
8409
  let file_3 = acceptedFiles[0];
7740
- if (compression && compressionFormat(file_3)) {
7741
- file_3 = await resizeAndCompressImage(file_3, compression);
8410
+ if ((imageResize || legacyCompression) && isImageFile(file_3)) {
8411
+ file_3 = await resizeImage(file_3, imageResize, legacyCompression);
7742
8412
  }
7743
8413
  newInternalValue = [{
7744
8414
  id: getRandomId$2(),
@@ -7750,7 +8420,7 @@
7750
8420
  }
7751
8421
  newInternalValue = removeDuplicates(newInternalValue);
7752
8422
  setInternalValue(newInternalValue);
7753
- }, [disabled, fileNameBuilder, internalValue, metadata, multipleFilesSupported, size]);
8423
+ }, [disabled, fileNameBuilder, internalValue, metadata, multipleFilesSupported, size, imageResize, legacyCompression]);
7754
8424
  return {
7755
8425
  internalValue,
7756
8426
  setInternalValue,
@@ -7758,6 +8428,7 @@
7758
8428
  fileNameBuilder,
7759
8429
  storagePathBuilder,
7760
8430
  onFileUploadComplete,
8431
+ onFileUploadError,
7761
8432
  onFilesAdded,
7762
8433
  multipleFilesSupported
7763
8434
  };
@@ -7788,22 +8459,42 @@
7788
8459
  function getRandomId$2() {
7789
8460
  return Math.floor(Math.random() * Math.floor(Number.MAX_SAFE_INTEGER));
7790
8461
  }
7791
- const supportedTypes = {
7792
- "image/jpeg": "JPEG",
7793
- "image/png": "PNG",
7794
- "image/webp": "WEBP"
7795
- };
7796
- const compressionFormat = (file) => supportedTypes[file.type] ? supportedTypes[file.type] : null;
7797
- const defaultQuality = 100;
7798
- const resizeAndCompressImage = (file, compression) => new Promise((resolve) => {
7799
- const inputQuality = compression.quality === void 0 ? defaultQuality : compression.quality;
7800
- const quality = inputQuality >= 0 ? inputQuality <= 100 ? inputQuality : 100 : 100;
7801
- const format = compressionFormat(file);
7802
- if (!format) {
7803
- throw Error("resizeAndCompressImage: Unsupported image format");
7804
- }
7805
- Resizer.imageFileResizer(file, compression.maxWidth || Number.MAX_VALUE, compression.maxHeight || Number.MAX_VALUE, format, quality, 0, (file2) => resolve(file2), "file");
7806
- });
8462
+ function isImageFile(file) {
8463
+ return file.type === "image/jpeg" || file.type === "image/png" || file.type === "image/webp";
8464
+ }
8465
+ async function resizeImage(file, imageResize, legacyCompression) {
8466
+ const maxWidth = imageResize?.maxWidth ?? legacyCompression?.maxWidth;
8467
+ const maxHeight = imageResize?.maxHeight ?? legacyCompression?.maxHeight;
8468
+ const quality = (imageResize?.quality ?? legacyCompression?.quality ?? 80) / 100;
8469
+ const mode = imageResize?.mode ?? "contain";
8470
+ let mimeType = file.type;
8471
+ if (imageResize?.format && imageResize.format !== "original") {
8472
+ mimeType = `image/${imageResize.format}`;
8473
+ }
8474
+ return new Promise((resolve, reject) => {
8475
+ new Compressor(file, {
8476
+ quality,
8477
+ maxWidth,
8478
+ maxHeight,
8479
+ mimeType,
8480
+ // Use cover mode if specified (crops to fit)
8481
+ // Otherwise use contain mode (scales to fit)
8482
+ ...mode === "cover" || mode === void 0 ? {
8483
+ width: maxWidth,
8484
+ height: maxHeight,
8485
+ resize: "cover"
8486
+ } : {},
8487
+ success: (result) => {
8488
+ const compressedFile = new File([result], file.name, {
8489
+ type: result.type,
8490
+ lastModified: Date.now()
8491
+ });
8492
+ resolve(compressedFile);
8493
+ },
8494
+ error: reject
8495
+ });
8496
+ });
8497
+ }
7807
8498
  function StorageUploadProgress({
7808
8499
  storagePath,
7809
8500
  entry,
@@ -8015,7 +8706,7 @@
8015
8706
  const snackbarContext = useSnackbarController();
8016
8707
  let t1;
8017
8708
  if ($[0] !== storage.acceptedFiles) {
8018
- t1 = storage.acceptedFiles ? storage.acceptedFiles.map(_temp$k).reduce(_temp2$9, {}) : void 0;
8709
+ t1 = storage.acceptedFiles ? storage.acceptedFiles.map(_temp$l).reduce(_temp2$9, {}) : void 0;
8019
8710
  $[0] = storage.acceptedFiles;
8020
8711
  $[1] = t1;
8021
8712
  } else {
@@ -8244,7 +8935,7 @@
8244
8935
  ...b
8245
8936
  };
8246
8937
  }
8247
- function _temp$k(e) {
8938
+ function _temp$l(e) {
8248
8939
  return {
8249
8940
  [e]: []
8250
8941
  };
@@ -8351,7 +9042,7 @@
8351
9042
  let t1;
8352
9043
  if ($[2] !== updateValue) {
8353
9044
  t1 = (entities) => {
8354
- updateValue(entities.map(_temp$j));
9045
+ updateValue(entities.map(_temp$k));
8355
9046
  };
8356
9047
  $[2] = updateValue;
8357
9048
  $[3] = t1;
@@ -8512,7 +9203,7 @@
8512
9203
  }
8513
9204
  return t10;
8514
9205
  }, equal);
8515
- function _temp$j(e) {
9206
+ function _temp$k(e) {
8516
9207
  return getReferenceFrom(e);
8517
9208
  }
8518
9209
  function _temp2$8(ref) {
@@ -9374,6 +10065,9 @@
9374
10065
  if (stringProperty_0.enumValues) {
9375
10066
  innerComponent = /* @__PURE__ */ jsxRuntime.jsx(VirtualTableSelect, { name: propertyKey, multiple: false, focused: selected, disabled, valueType: "string", small: getPreviewSizeFrom(size) !== "medium", enumValues: stringProperty_0.enumValues, error: validationError ?? error, internalValue, updateValue });
9376
10067
  fullHeight = true;
10068
+ } else if (stringProperty_0.userSelect) {
10069
+ innerComponent = /* @__PURE__ */ jsxRuntime.jsx(VirtualTableUserSelect, { name: propertyKey, multiple: false, focused: selected, disabled, small: getPreviewSizeFrom(size) !== "medium", error: validationError ?? error, internalValue, updateValue });
10070
+ fullHeight = true;
9377
10071
  } else if (stringProperty_0.markdown || !stringProperty_0.storage || !stringProperty_0.reference) {
9378
10072
  const multiline = Boolean(stringProperty_0.multiline) || Boolean(stringProperty_0.markdown);
9379
10073
  innerComponent = /* @__PURE__ */ jsxRuntime.jsx(VirtualTableInput, { error: validationError ?? error, disabled, multiline, focused: selected, value: internalValue, updateValue });
@@ -9438,7 +10132,8 @@
9438
10132
  return {
9439
10133
  __type: "EntityReference",
9440
10134
  id: value.id,
9441
- path: value.path
10135
+ path: value.path,
10136
+ databaseId: value.databaseId
9442
10137
  };
9443
10138
  }
9444
10139
  if (value instanceof GeoPoint) {
@@ -9462,7 +10157,7 @@
9462
10157
  case "Date":
9463
10158
  return new Date(value.value);
9464
10159
  case "EntityReference":
9465
- return new EntityReference(value.id, value.path);
10160
+ return new EntityReference(value.id, value.path, value.databaseId);
9466
10161
  case "GeoPoint":
9467
10162
  return new GeoPoint(value.latitude, value.longitude);
9468
10163
  case "Vector":
@@ -9473,50 +10168,41 @@
9473
10168
  }
9474
10169
  return value;
9475
10170
  }
9476
- if (isLocalStorageAvailable) {
9477
- try {
9478
- for (let i = 0; i < localStorage.length; i++) {
9479
- const fullKey = localStorage.key(i);
9480
- if (fullKey && fullKey.startsWith(LOCAL_STORAGE_PREFIX)) {
9481
- const path = fullKey.substring(LOCAL_STORAGE_PREFIX.length);
9482
- const entityString = localStorage.getItem(fullKey);
9483
- if (entityString) {
9484
- try {
9485
- const entity = JSON.parse(entityString, customReviver);
9486
- entityCache.set(path, entity);
9487
- } catch (parseError) {
9488
- console.error(`Failed to parse entity for path "${path}" from localStorage:`, parseError);
9489
- }
9490
- }
9491
- }
9492
- }
9493
- } catch (error) {
9494
- console.error("Error accessing localStorage during initialization:", error);
9495
- }
9496
- }
9497
10171
  function saveEntityToCache(path, data) {
9498
- entityCache.set(path, data);
9499
10172
  if (isLocalStorageAvailable) {
9500
10173
  try {
9501
10174
  const key = LOCAL_STORAGE_PREFIX + path;
9502
10175
  const entityString = JSON.stringify(data, customReplacer);
10176
+ console.log("Saving entity to localStorage:", {
10177
+ key,
10178
+ entityString
10179
+ });
9503
10180
  localStorage.setItem(key, entityString);
9504
10181
  } catch (error) {
9505
10182
  console.error(`Failed to save entity for path "${path}" to localStorage:`, error);
9506
10183
  }
9507
10184
  }
9508
10185
  }
10186
+ function removeEntityFromMemoryCache(path) {
10187
+ entityCache.delete(path);
10188
+ }
10189
+ function saveEntityToMemoryCache(path, data) {
10190
+ entityCache.set(path, data);
10191
+ }
10192
+ function getEntityFromMemoryCache(path) {
10193
+ return entityCache.get(path);
10194
+ }
9509
10195
  function getEntityFromCache(path) {
9510
- if (entityCache.has(path)) {
9511
- return entityCache.get(path);
9512
- }
9513
10196
  if (isLocalStorageAvailable) {
9514
10197
  try {
9515
10198
  const key = LOCAL_STORAGE_PREFIX + path;
9516
10199
  const entityString = localStorage.getItem(key);
9517
10200
  if (entityString) {
9518
10201
  const entity = JSON.parse(entityString, customReviver);
9519
- entityCache.set(path, entity);
10202
+ console.log("Loaded entity from localStorage:", {
10203
+ key,
10204
+ entity
10205
+ });
9520
10206
  return entity;
9521
10207
  }
9522
10208
  } catch (error) {
@@ -9525,12 +10211,7 @@
9525
10211
  }
9526
10212
  return void 0;
9527
10213
  }
9528
- function hasEntityInCache(path) {
9529
- return entityCache.has(path);
9530
- }
9531
10214
  function removeEntityFromCache(path) {
9532
- console.debug("Removing entity from cache", path);
9533
- entityCache.delete(path);
9534
10215
  if (isLocalStorageAvailable) {
9535
10216
  try {
9536
10217
  const key = LOCAL_STORAGE_PREFIX + path;
@@ -9540,6 +10221,26 @@
9540
10221
  }
9541
10222
  }
9542
10223
  }
10224
+ function flattenKeys(obj, prefix = "", result = []) {
10225
+ if (isObject(obj) || Array.isArray(obj)) {
10226
+ const plainObject = isPlainObject(obj);
10227
+ if (!plainObject && prefix) {
10228
+ result.push(prefix);
10229
+ } else {
10230
+ for (const key in obj) {
10231
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
10232
+ const newKey = prefix ? Array.isArray(obj) ? `${prefix}[${key}]` : `${prefix}.${key}` : key;
10233
+ if (isObject(obj[key]) || Array.isArray(obj[key])) {
10234
+ flattenKeys(obj[key], newKey, result);
10235
+ } else {
10236
+ result.push(newKey);
10237
+ }
10238
+ }
10239
+ }
10240
+ }
10241
+ }
10242
+ return result;
10243
+ }
9543
10244
  const EntityCollectionRowActions = function EntityCollectionRowActions2({
9544
10245
  entity,
9545
10246
  collection,
@@ -9567,7 +10268,9 @@
9567
10268
  const hasCollapsedActions = actions.some((a) => a.collapsed || a.collapsed === void 0);
9568
10269
  const collapsedActions = actions.filter((a_0) => a_0.collapsed || a_0.collapsed === void 0);
9569
10270
  const uncollapsedActions = actions.filter((a_1) => a_1.collapsed === false);
9570
- const hasDraft = hasEntityInCache(fullPath + "/" + entity.id);
10271
+ const enableLocalChangesBackup = collection ? getLocalChangesBackup(collection) : false;
10272
+ const hasDraft = enableLocalChangesBackup ? getEntityFromCache(fullPath + "/" + entity.id) : false;
10273
+ const iconSize = largeLayout && (size === "m" || size === "l" || size == "xl") ? "medium" : "small";
9571
10274
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("h-full flex items-center justify-center flex-col bg-surface-50 dark:bg-surface-900 bg-opacity-90 dark:bg-opacity-90 z-10", frozen ? "sticky left-0" : ""), onClick: React.useCallback((event) => {
9572
10275
  event.stopPropagation();
9573
10276
  }, []), style: {
@@ -9577,23 +10280,31 @@
9577
10280
  contain: "strict"
9578
10281
  }, children: [
9579
10282
  (hasActions || selectionEnabled) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-34 flex justify-center", children: [
9580
- uncollapsedActions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: action.name, asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: (event_0) => {
9581
- event_0.stopPropagation();
9582
- action.onClick({
9583
- view: "collection",
9584
- entity,
9585
- fullPath,
9586
- fullIdPath,
9587
- collection,
9588
- context,
9589
- selectionController,
9590
- highlightEntity,
9591
- unhighlightEntity,
9592
- onCollectionChange,
9593
- openEntityMode: openEntityMode ?? collection?.openEntityMode
9594
- });
9595
- }, size: largeLayout ? "medium" : "small", children: action.icon }) }, index)),
9596
- hasCollapsedActions && /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { trigger: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: largeLayout ? "medium" : "small", children: /* @__PURE__ */ jsxRuntime.jsx(ui.MoreVertIcon, {}) }), children: collapsedActions.map((action_0, index_0) => /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { onClick: (e) => {
10283
+ uncollapsedActions.map((action, index) => {
10284
+ const isEditAction = action.key === "edit";
10285
+ const tooltip = isEditAction && hasDraft ? "Local unsaved changes" : action.name;
10286
+ let iconButton = /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: (event_0) => {
10287
+ event_0.stopPropagation();
10288
+ action.onClick({
10289
+ view: "collection",
10290
+ entity,
10291
+ fullPath,
10292
+ fullIdPath,
10293
+ collection,
10294
+ context,
10295
+ selectionController,
10296
+ highlightEntity,
10297
+ unhighlightEntity,
10298
+ onCollectionChange,
10299
+ openEntityMode: openEntityMode ?? collection?.openEntityMode
10300
+ });
10301
+ }, size: iconSize, children: action.icon });
10302
+ if (isEditAction && hasDraft) {
10303
+ iconButton = /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "warning", children: iconButton });
10304
+ }
10305
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: tooltip, asChild: true, children: iconButton }, index);
10306
+ }),
10307
+ hasCollapsedActions && /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, { trigger: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: iconSize, children: /* @__PURE__ */ jsxRuntime.jsx(ui.MoreVertIcon, {}) }), children: collapsedActions.map((action_0, index_0) => /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { onClick: (e) => {
9597
10308
  e.stopPropagation();
9598
10309
  action_0.onClick({
9599
10310
  view: "collection",
@@ -9612,14 +10323,11 @@
9612
10323
  action_0.icon,
9613
10324
  action_0.name
9614
10325
  ] }, index_0)) }),
9615
- selectionEnabled && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: `Select ${entity.id}`, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { size: largeLayout ? "medium" : "small", checked: Boolean(isSelected), onCheckedChange }) })
10326
+ selectionEnabled && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: `Select ${entity.id}`, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { size: iconSize, checked: Boolean(isSelected), onCheckedChange }) })
9616
10327
  ] }),
9617
- !hideId && size !== "xs" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-[138px] overflow-hidden truncate font-mono text-xs text-text-secondary dark:text-text-secondary-dark max-w-full text-ellipsis px-2 align-center justify-center flex items-center gap-1", onClick: (event_1) => {
10328
+ !hideId && size !== "xs" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[138px] overflow-hidden truncate font-mono text-xs text-text-secondary dark:text-text-secondary-dark max-w-full text-ellipsis px-2 align-center justify-center flex items-center gap-1", onClick: (event_1) => {
9618
10329
  event_1.stopPropagation();
9619
- }, children: [
9620
- hasDraft && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Local unsaved changes", className: "inline", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { colorScheme: "orangeDarker", className: "p-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(ui.EditIcon, { size: 12 }) }) }),
9621
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-center", children: entity ? entity.id : /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, {}) })
9622
- ] })
10330
+ }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-center", children: entity ? entity.id : /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, {}) }) })
9623
10331
  ] });
9624
10332
  };
9625
10333
  function CollectionTableToolbar(t0) {
@@ -9674,7 +10382,7 @@
9674
10382
  }
9675
10383
  let t6;
9676
10384
  if ($[6] !== t3 || $[7] !== t4) {
9677
- t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Table row size", side: "right", sideOffset: 4, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { value: t3, className: "w-16 ml-2", size: "small", onValueChange: t4, renderValue: _temp$i, children: t5 }) });
10385
+ t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Table row size", side: "right", sideOffset: 4, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { value: t3, className: "w-16 ml-2", size: "small", onValueChange: t4, renderValue: _temp$j, children: t5 }) });
9678
10386
  $[6] = t3;
9679
10387
  $[7] = t4;
9680
10388
  $[8] = t6;
@@ -9761,7 +10469,7 @@
9761
10469
  function _temp2$7(size_0) {
9762
10470
  return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: size_0, className: "w-12 font-medium text-center", children: size_0.toUpperCase() }, size_0);
9763
10471
  }
9764
- function _temp$i(v_0) {
10472
+ function _temp$j(v_0) {
9765
10473
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: v_0.toUpperCase() });
9766
10474
  }
9767
10475
  function getTableCellAlignment(property) {
@@ -9833,21 +10541,15 @@
9833
10541
  let t0;
9834
10542
  bb0: {
9835
10543
  if (collection.propertiesOrder) {
9836
- let propertyColumnConfigs;
10544
+ let t12;
9837
10545
  if ($[0] !== collection) {
9838
- propertyColumnConfigs = hideAndExpandKeys(collection, collection.propertiesOrder);
9839
- if (collection.collectionGroup) {
9840
- propertyColumnConfigs.push({
9841
- key: COLLECTION_GROUP_PARENT_ID,
9842
- disabled: true
9843
- });
9844
- }
10546
+ t12 = hideAndExpandKeys(collection, collection.propertiesOrder);
9845
10547
  $[0] = collection;
9846
- $[1] = propertyColumnConfigs;
10548
+ $[1] = t12;
9847
10549
  } else {
9848
- propertyColumnConfigs = $[1];
10550
+ t12 = $[1];
9849
10551
  }
9850
- t0 = propertyColumnConfigs;
10552
+ t0 = t12;
9851
10553
  break bb0;
9852
10554
  }
9853
10555
  let t1;
@@ -10881,7 +11583,7 @@
10881
11583
  let t1;
10882
11584
  if ($[0] !== text) {
10883
11585
  const urlRegex = /https?:\/\/[^\s]+/g;
10884
- t1 = text.replace(urlRegex, _temp$h);
11586
+ t1 = text.replace(urlRegex, _temp$i);
10885
11587
  $[0] = text;
10886
11588
  $[1] = t1;
10887
11589
  } else {
@@ -10900,7 +11602,7 @@
10900
11602
  }
10901
11603
  return t2;
10902
11604
  };
10903
- function _temp$h(url) {
11605
+ function _temp$i(url) {
10904
11606
  return `<a href="${url}" class="underline" target="_blank">Link</a><br/>`;
10905
11607
  }
10906
11608
  const operationLabels$2 = {
@@ -11108,7 +11810,7 @@
11108
11810
  }
11109
11811
  let t6;
11110
11812
  if ($[16] !== operation || $[17] !== t4 || $[18] !== t5) {
11111
- t6 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { value: operation, fullWidth: true, position: "item-aligned", onValueChange: t4, renderValue: _temp$g, children: t5 }) });
11813
+ t6 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { value: operation, fullWidth: true, position: "item-aligned", onValueChange: t4, renderValue: _temp$h, children: t5 }) });
11112
11814
  $[16] = operation;
11113
11815
  $[17] = t4;
11114
11816
  $[18] = t5;
@@ -11121,7 +11823,7 @@
11121
11823
  t7 = !enumValues && /* @__PURE__ */ jsxRuntime.jsx(ui.TextField, { type: dataType === "number" ? "number" : void 0, value: internalValue !== void 0 && internalValue != null ? String(internalValue) : "", onChange: (evt) => {
11122
11824
  const val_0 = dataType === "number" ? parseFloat(evt.target.value) : evt.target.value;
11123
11825
  updateFilter(operation, val_0);
11124
- }, endAdornment: internalValue && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: (e) => updateFilter(operation, void 0), children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, {}) }) });
11826
+ }, endAdornment: internalValue !== void 0 && internalValue != null && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: (e) => updateFilter(operation, void 0), children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, {}) }) });
11125
11827
  $[20] = dataType;
11126
11828
  $[21] = enumValues;
11127
11829
  $[22] = internalValue;
@@ -11137,7 +11839,7 @@
11137
11839
  if (value_1 !== "") {
11138
11840
  updateFilter(operation, dataType === "number" ? parseInt(value_1) : value_1);
11139
11841
  }
11140
- }, endAdornment: internalValue && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "absolute right-2 top-3", onClick: (e_0) => updateFilter(operation, void 0), children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, {}) }), renderValue: (enumKey) => {
11842
+ }, endAdornment: internalValue && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: (e_0) => updateFilter(operation, void 0), children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, {}) }), renderValue: (enumKey) => {
11141
11843
  if (enumKey === null) {
11142
11844
  return "Filter for null values";
11143
11845
  }
@@ -11232,7 +11934,7 @@
11232
11934
  function _temp2$6(op_1) {
11233
11935
  return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: op_1, children: operationLabels$1[op_1] }, op_1);
11234
11936
  }
11235
- function _temp$g(op_0) {
11937
+ function _temp$h(op_0) {
11236
11938
  return operationLabels$1[op_0];
11237
11939
  }
11238
11940
  function BooleanFilterField(t0) {
@@ -11294,7 +11996,7 @@
11294
11996
  };
11295
11997
  const multipleSelectOperations = ["array-contains-any", "in"];
11296
11998
  function DateTimeFilterField(t0) {
11297
- const $ = reactCompilerRuntime.c(38);
11999
+ const $ = reactCompilerRuntime.c(39);
11298
12000
  const {
11299
12001
  isArray,
11300
12002
  mode,
@@ -11335,7 +12037,7 @@
11335
12037
  newValue = newOpIsArray ? val ? [val] : [] : "";
11336
12038
  }
11337
12039
  setOperation(op);
11338
- setInternalValue(newValue === null ? void 0 : newValue);
12040
+ setInternalValue(newValue);
11339
12041
  const hasNewValue = newValue !== null && Array.isArray(newValue) ? newValue.length > 0 : newValue !== void 0;
11340
12042
  if (op && hasNewValue) {
11341
12043
  setValue([op, newValue]);
@@ -11371,7 +12073,7 @@
11371
12073
  }
11372
12074
  let t6;
11373
12075
  if ($[13] !== operation || $[14] !== t4 || $[15] !== t5) {
11374
- t6 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { value: operation, size: "large", fullWidth: true, onValueChange: t4, renderValue: _temp$f, children: t5 }) });
12076
+ t6 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { value: operation, size: "large", fullWidth: true, onValueChange: t4, renderValue: _temp$g, children: t5 }) });
11375
12077
  $[13] = operation;
11376
12078
  $[14] = t4;
11377
12079
  $[15] = t5;
@@ -11379,88 +12081,90 @@
11379
12081
  } else {
11380
12082
  t6 = $[16];
11381
12083
  }
11382
- const t7 = internalValue ?? void 0;
11383
- let t8;
12084
+ const t7 = internalValue === null;
12085
+ const t8 = internalValue ?? void 0;
12086
+ let t9;
11384
12087
  if ($[17] !== operation || $[18] !== updateFilter) {
11385
- t8 = (dateValue) => {
12088
+ t9 = (dateValue) => {
11386
12089
  updateFilter(operation, dateValue === null ? void 0 : dateValue);
11387
12090
  };
11388
12091
  $[17] = operation;
11389
12092
  $[18] = updateFilter;
11390
- $[19] = t8;
12093
+ $[19] = t9;
11391
12094
  } else {
11392
- t8 = $[19];
12095
+ t9 = $[19];
11393
12096
  }
11394
- let t9;
11395
- if ($[20] !== locale || $[21] !== mode || $[22] !== t7 || $[23] !== t8) {
11396
- t9 = /* @__PURE__ */ jsxRuntime.jsx(ui.DateTimeField, { mode, size: "large", locale, value: t7, onChange: t8, clearable: true });
12097
+ let t10;
12098
+ if ($[20] !== locale || $[21] !== mode || $[22] !== t7 || $[23] !== t8 || $[24] !== t9) {
12099
+ t10 = /* @__PURE__ */ jsxRuntime.jsx(ui.DateTimeField, { mode, size: "large", locale, disabled: t7, value: t8, onChange: t9, clearable: true });
11397
12100
  $[20] = locale;
11398
12101
  $[21] = mode;
11399
12102
  $[22] = t7;
11400
12103
  $[23] = t8;
11401
12104
  $[24] = t9;
12105
+ $[25] = t10;
11402
12106
  } else {
11403
- t9 = $[24];
12107
+ t10 = $[25];
11404
12108
  }
11405
- const t10 = internalValue === null;
11406
- let t11;
11407
- if ($[25] !== internalValue || $[26] !== operation || $[27] !== updateFilter) {
11408
- t11 = (checked) => {
12109
+ const t11 = internalValue === null;
12110
+ let t12;
12111
+ if ($[26] !== internalValue || $[27] !== operation || $[28] !== updateFilter) {
12112
+ t12 = (checked) => {
11409
12113
  if (internalValue !== null) {
11410
12114
  updateFilter(operation, null);
11411
12115
  } else {
11412
12116
  updateFilter(operation, void 0);
11413
12117
  }
11414
12118
  };
11415
- $[25] = internalValue;
11416
- $[26] = operation;
11417
- $[27] = updateFilter;
11418
- $[28] = t11;
12119
+ $[26] = internalValue;
12120
+ $[27] = operation;
12121
+ $[28] = updateFilter;
12122
+ $[29] = t12;
11419
12123
  } else {
11420
- t11 = $[28];
12124
+ t12 = $[29];
11421
12125
  }
11422
- let t12;
11423
- if ($[29] !== t10 || $[30] !== t11) {
11424
- t12 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Label, { className: "border cursor-pointer rounded-md p-2 flex items-center gap-2 [&:has(:checked)]:bg-surface-100 dark:[&:has(:checked)]:bg-surface-800", htmlFor: "null-filter", children: [
11425
- /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { id: "null-filter", checked: t10, size: "small", onCheckedChange: t11 }),
12126
+ let t13;
12127
+ if ($[30] !== t11 || $[31] !== t12) {
12128
+ t13 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Label, { className: "border cursor-pointer rounded-md p-2 flex items-center gap-2 [&:has(:checked)]:bg-surface-100 dark:[&:has(:checked)]:bg-surface-800", htmlFor: "null-filter", children: [
12129
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { id: "null-filter", checked: t11, size: "small", onCheckedChange: t12 }),
11426
12130
  "Filter for null values"
11427
12131
  ] });
11428
- $[29] = t10;
11429
12132
  $[30] = t11;
11430
12133
  $[31] = t12;
12134
+ $[32] = t13;
11431
12135
  } else {
11432
- t12 = $[31];
12136
+ t13 = $[32];
11433
12137
  }
11434
- let t13;
11435
- if ($[32] !== t12 || $[33] !== t9) {
11436
- t13 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow ml-2 flex flex-col gap-2", children: [
11437
- t9,
11438
- t12
12138
+ let t14;
12139
+ if ($[33] !== t10 || $[34] !== t13) {
12140
+ t14 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow ml-2 flex flex-col gap-2", children: [
12141
+ t10,
12142
+ t13
11439
12143
  ] });
11440
- $[32] = t12;
11441
- $[33] = t9;
12144
+ $[33] = t10;
11442
12145
  $[34] = t13;
12146
+ $[35] = t14;
11443
12147
  } else {
11444
- t13 = $[34];
12148
+ t14 = $[35];
11445
12149
  }
11446
- let t14;
11447
- if ($[35] !== t13 || $[36] !== t6) {
11448
- t14 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-[440px]", children: [
12150
+ let t15;
12151
+ if ($[36] !== t14 || $[37] !== t6) {
12152
+ t15 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-[440px]", children: [
11449
12153
  t6,
11450
- t13
12154
+ t14
11451
12155
  ] });
11452
- $[35] = t13;
11453
- $[36] = t6;
11454
- $[37] = t14;
12156
+ $[36] = t14;
12157
+ $[37] = t6;
12158
+ $[38] = t15;
11455
12159
  } else {
11456
- t14 = $[37];
12160
+ t15 = $[38];
11457
12161
  }
11458
- return t14;
12162
+ return t15;
11459
12163
  }
11460
12164
  function _temp2$5(op_1) {
11461
12165
  return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: op_1, children: operationLabels[op_1] }, op_1);
11462
12166
  }
11463
- function _temp$f(op_0) {
12167
+ function _temp$g(op_0) {
11464
12168
  return operationLabels[op_0];
11465
12169
  }
11466
12170
  const SelectableTable = function SelectableTable2({
@@ -12164,7 +12868,7 @@
12164
12868
  const searchBlocked = t12;
12165
12869
  let t2;
12166
12870
  if ($[15] !== customizationController.plugins || $[16] !== dataSource?.initTextSearch) {
12167
- t2 = Boolean(dataSource?.initTextSearch) || customizationController.plugins?.find(_temp$e);
12871
+ t2 = Boolean(dataSource?.initTextSearch) || customizationController.plugins?.find(_temp$f);
12168
12872
  $[15] = customizationController.plugins;
12169
12873
  $[16] = dataSource?.initTextSearch;
12170
12874
  $[17] = t2;
@@ -12256,7 +12960,7 @@
12256
12960
  }
12257
12961
  return t1;
12258
12962
  }
12259
- function _temp$e(p_0) {
12963
+ function _temp$f(p_0) {
12260
12964
  return Boolean(p_0.collectionView?.onTextSearchClick);
12261
12965
  }
12262
12966
  function DeleteEntityDialog({
@@ -12849,7 +13553,7 @@
12849
13553
  T0 = ui.Collapse;
12850
13554
  t4 = favouriteCollections.length > 0;
12851
13555
  t2 = "flex flex-row flex-wrap gap-2 pb-2 min-h-[32px]";
12852
- t3 = favouriteCollections.map(_temp$d);
13556
+ t3 = favouriteCollections.map(_temp$e);
12853
13557
  $[2] = navigationController;
12854
13558
  $[3] = t1;
12855
13559
  $[4] = T0;
@@ -12883,7 +13587,7 @@
12883
13587
  }
12884
13588
  return t6;
12885
13589
  }
12886
- function _temp$d(entry_0) {
13590
+ function _temp$e(entry_0) {
12887
13591
  return /* @__PURE__ */ jsxRuntime.jsx(NavigationChip, { entry: entry_0 }, entry_0.path);
12888
13592
  }
12889
13593
  const scrollsMap = {};
@@ -13100,7 +13804,7 @@
13100
13804
  }
13101
13805
  let t4;
13102
13806
  if ($[4] !== actions) {
13103
- t4 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", onClick: _temp$c, children: actions });
13807
+ t4 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", onClick: _temp$d, children: actions });
13104
13808
  $[4] = actions;
13105
13809
  $[5] = t4;
13106
13810
  } else {
@@ -13187,7 +13891,7 @@
13187
13891
  }
13188
13892
  return t12;
13189
13893
  });
13190
- function _temp$c(event) {
13894
+ function _temp$d(event) {
13191
13895
  event.preventDefault();
13192
13896
  event.stopPropagation();
13193
13897
  }
@@ -13600,14 +14304,16 @@
13600
14304
  return t5;
13601
14305
  }
13602
14306
  function useHomePageDnd({
13603
- items: dndItems,
13604
- setItems: setDndItems,
14307
+ items,
14308
+ setItems,
13605
14309
  disabled,
13606
14310
  onCardMovedBetweenGroups,
13607
14311
  onGroupMoved,
13608
14312
  onNewGroupDrop,
13609
14313
  onPersist
13610
14314
  }) {
14315
+ const dndItems = items;
14316
+ const setDndItems = setItems;
13611
14317
  const [activeId, setActiveId] = React.useState(null);
13612
14318
  const [activeIsGroup, setActiveIsGroup] = React.useState(false);
13613
14319
  const [currentDraggingGroupId, setCurrentDraggingGroupId] = React.useState(null);
@@ -13615,6 +14321,9 @@
13615
14321
  const [isDraggingCardOnly, setIsDraggingCardOnly] = React.useState(false);
13616
14322
  const [dialogOpenForGroup, setDialogOpenForGroup] = React.useState(null);
13617
14323
  const [isHoveringNewGroupDropZone, setIsHoveringNewGroupDropZone] = React.useState(false);
14324
+ const [pendingNewGroupName, setPendingNewGroupName] = React.useState(null);
14325
+ const [stateBeforeNewGroup, setStateBeforeNewGroup] = React.useState(null);
14326
+ const preDragItemsRef = React.useRef(null);
13618
14327
  const interimItemsRef = React.useRef(null);
13619
14328
  React.useEffect(() => {
13620
14329
  interimItemsRef.current = dndItems;
@@ -13649,32 +14358,6 @@
13649
14358
  if (activeIsGroup) {
13650
14359
  const groups = args.droppableContainers.filter((c) => dndItems.some((g_2) => g_2.name === c.id));
13651
14360
  if (!groups.length) return [];
13652
- if (groups.length > 0) {
13653
- const firstGroup = groups[0];
13654
- const firstGroupRect = firstGroup.rect.current;
13655
- const {
13656
- x,
13657
- y
13658
- } = args.pointerCoordinates || {
13659
- x: 0,
13660
- y: 0
13661
- };
13662
- if (firstGroupRect && y < firstGroupRect.top + 20) {
13663
- return [{
13664
- id: firstGroup.id,
13665
- data: {
13666
- insertBefore: true
13667
- }
13668
- }];
13669
- }
13670
- }
13671
- const cornersResult = core.closestCorners({
13672
- ...args,
13673
- droppableContainers: groups
13674
- });
13675
- if (cornersResult.length) {
13676
- return cornersResult;
13677
- }
13678
14361
  return core.closestCenter({
13679
14362
  ...args,
13680
14363
  droppableContainers: groups
@@ -13732,6 +14415,7 @@
13732
14415
  }) => {
13733
14416
  setDndKitActiveNode(active);
13734
14417
  if (disabled) return;
14418
+ preDragItemsRef.current = cloneItemsForDnd(dndItems);
13735
14419
  const isGroup = dndItems.some((g_7) => g_7.name === active.id);
13736
14420
  if (!active.data.current) active.data.current = {};
13737
14421
  active.data.current.type = isGroup ? "group" : "item";
@@ -13755,18 +14439,30 @@
13755
14439
  if (!activeCont) return;
13756
14440
  if (overCont && activeCont !== overCont) {
13757
14441
  recentlyMovedToNewContainer.current = true;
13758
- const newState = cloneItemsForDnd(dndItems);
13759
- const srcIdx = newState.findIndex((g_8) => g_8.name === activeCont);
13760
- const tgtIdx = newState.findIndex((g_9) => g_9.name === overCont);
13761
- if (srcIdx === -1 || tgtIdx === -1) return;
13762
- const src = newState[srcIdx];
13763
- const tgt = newState[tgtIdx];
13764
- const idxInSrc = src.entries.findIndex((e_2) => e_2.url === activeIdNow);
13765
- if (idxInSrc === -1) return;
13766
- const [moved] = src.entries.splice(idxInSrc, 1);
13767
- tgt.entries.push(moved);
13768
- interimItemsRef.current = newState;
13769
- setDndItems(newState);
14442
+ lastOverId.current = overIdNow;
14443
+ setDndItems((current) => {
14444
+ const newState = cloneItemsForDnd(current);
14445
+ const srcIdx = newState.findIndex((g_8) => g_8.name === activeCont);
14446
+ const tgtIdx = newState.findIndex((g_9) => g_9.name === overCont);
14447
+ if (srcIdx === -1 || tgtIdx === -1) return current;
14448
+ const src = newState[srcIdx];
14449
+ const tgt = newState[tgtIdx];
14450
+ const idxInSrc = src.entries.findIndex((e_2) => e_2.url === activeIdNow);
14451
+ if (idxInSrc === -1) return current;
14452
+ const [moved] = src.entries.splice(idxInSrc, 1);
14453
+ const overIsContainer_0 = overIdNow === overCont;
14454
+ if (overIsContainer_0) {
14455
+ tgt.entries.push(moved);
14456
+ } else {
14457
+ const overIdx = tgt.entries.findIndex((e_3) => e_3.url === overIdNow);
14458
+ if (overIdx !== -1) {
14459
+ tgt.entries.splice(overIdx, 0, moved);
14460
+ } else {
14461
+ tgt.entries.push(moved);
14462
+ }
14463
+ }
14464
+ return newState;
14465
+ });
13770
14466
  } else if (activeCont === overCont) {
13771
14467
  recentlyMovedToNewContainer.current = false;
13772
14468
  }
@@ -13782,75 +14478,112 @@
13782
14478
  const activeIdNow_0 = active_1.id;
13783
14479
  const overIdNow_0 = over_0.id;
13784
14480
  if (activeIsGroup) {
13785
- const insertBefore = over_0.data?.current?.insertBefore;
13786
- if (insertBefore && activeIdNow_0 !== overIdNow_0) {
14481
+ if (activeIdNow_0 !== overIdNow_0 && dndItems.some((g_12) => g_12.name === overIdNow_0)) {
13787
14482
  const from = dndItems.findIndex((g_10) => g_10.name === activeIdNow_0);
13788
- if (from !== -1 && from !== 0) {
13789
- const newState_0 = sortable.arrayMove(dndItems, from, 0);
14483
+ const to = dndItems.findIndex((g_11) => g_11.name === overIdNow_0);
14484
+ if (from !== -1 && to !== -1) {
14485
+ const newState_0 = sortable.arrayMove(dndItems, from, to);
13790
14486
  setDndItems(newState_0);
13791
14487
  onPersist?.(newState_0);
13792
- onGroupMoved?.(activeIdNow_0, from, 0);
13793
- }
13794
- } else if (activeIdNow_0 !== overIdNow_0 && dndItems.some((g_13) => g_13.name === overIdNow_0)) {
13795
- const from_0 = dndItems.findIndex((g_11) => g_11.name === activeIdNow_0);
13796
- const to = dndItems.findIndex((g_12) => g_12.name === overIdNow_0);
13797
- if (from_0 !== -1 && to !== -1) {
13798
- const newState_1 = sortable.arrayMove(dndItems, from_0, to);
13799
- setDndItems(newState_1);
13800
- onPersist?.(newState_1);
13801
- onGroupMoved?.(activeIdNow_0, from_0, to);
14488
+ onGroupMoved?.(activeIdNow_0, from, to);
13802
14489
  }
13803
14490
  }
13804
14491
  } else {
13805
- const activeCont_0 = findDndContainer(activeIdNow_0);
14492
+ const findContainerInState = (id_0, state) => {
14493
+ const group_0 = state.find((g_13) => g_13.name === id_0);
14494
+ if (group_0) return group_0.name;
14495
+ for (const g_14 of state) {
14496
+ if (g_14.entries.some((e_4) => e_4.url === id_0)) return g_14.name;
14497
+ }
14498
+ return void 0;
14499
+ };
14500
+ const sourceState = preDragItemsRef.current || dndItems;
14501
+ const activeCont_0 = findContainerInState(activeIdNow_0, sourceState);
14502
+ findDndContainer(overIdNow_0);
13806
14503
  if (overIdNow_0 === "new-group-drop-zone") {
13807
14504
  if (activeCont_0) {
13808
- const newState_2 = cloneItemsForDnd(dndItems);
13809
- const srcIdx_0 = newState_2.findIndex((g_14) => g_14.name === activeCont_0);
14505
+ setStateBeforeNewGroup(cloneItemsForDnd(dndItems));
14506
+ const newState_1 = cloneItemsForDnd(dndItems);
14507
+ const srcIdx_0 = newState_1.findIndex((g_15) => g_15.name === activeCont_0);
13810
14508
  if (srcIdx_0 !== -1) {
13811
- const src_0 = newState_2[srcIdx_0];
13812
- const idxInSrc_0 = src_0.entries.findIndex((e_3) => e_3.url === activeIdNow_0);
14509
+ const src_0 = newState_1[srcIdx_0];
14510
+ const idxInSrc_0 = src_0.entries.findIndex((e_5) => e_5.url === activeIdNow_0);
13813
14511
  if (idxInSrc_0 !== -1) {
13814
14512
  const [dragged] = src_0.entries.splice(idxInSrc_0, 1);
13815
- if (src_0.entries.length === 0) newState_2.splice(srcIdx_0, 1);
14513
+ if (src_0.entries.length === 0) newState_1.splice(srcIdx_0, 1);
13816
14514
  let tentative = "New Group";
13817
14515
  let counter = 1;
13818
- while (newState_2.some((g_15) => g_15.name === tentative)) tentative = `New Group ${counter++}`;
13819
- newState_2.push({
14516
+ while (newState_1.some((g_16) => g_16.name === tentative)) tentative = `New Group ${counter++}`;
14517
+ newState_1.push({
13820
14518
  name: tentative,
13821
14519
  entries: [dragged]
13822
14520
  });
13823
- setDndItems(newState_2);
13824
- onPersist?.(newState_2);
14521
+ setDndItems(newState_1);
14522
+ setPendingNewGroupName(tentative);
13825
14523
  setDialogOpenForGroup(tentative);
13826
14524
  onNewGroupDrop?.();
13827
14525
  }
13828
14526
  }
13829
14527
  }
13830
14528
  } else {
13831
- const overCont_0 = findDndContainer(overIdNow_0);
13832
- if (activeCont_0 === overCont_0) {
13833
- const grpIdx = dndItems.findIndex((g_16) => g_16.name === activeCont_0);
14529
+ const overCont_1 = findDndContainer(overIdNow_0);
14530
+ if (activeCont_0 === overCont_1) {
14531
+ const grpIdx = dndItems.findIndex((g_17) => g_17.name === activeCont_0);
13834
14532
  if (grpIdx !== -1) {
13835
- const group_0 = dndItems[grpIdx];
13836
- const oldIdx = group_0.entries.findIndex((e_4) => e_4.url === activeIdNow_0);
13837
- let newIdx = group_0.entries.findIndex((e_5) => e_5.url === overIdNow_0);
13838
- if (newIdx === -1 && overIdNow_0 === activeCont_0) newIdx = group_0.entries.length - 1;
14533
+ const group_1 = dndItems[grpIdx];
14534
+ const oldIdx = group_1.entries.findIndex((e_6) => e_6.url === activeIdNow_0);
14535
+ let newIdx = group_1.entries.findIndex((e_7) => e_7.url === overIdNow_0);
14536
+ if (newIdx === -1 && overIdNow_0 === activeCont_0) newIdx = group_1.entries.length - 1;
13839
14537
  if (oldIdx !== -1 && newIdx !== -1 && oldIdx !== newIdx) {
13840
- const reordered = sortable.arrayMove(group_0.entries, oldIdx, newIdx);
13841
- const newState_3 = [...dndItems];
13842
- newState_3[grpIdx] = {
13843
- ...group_0,
14538
+ const reordered = sortable.arrayMove(group_1.entries, oldIdx, newIdx);
14539
+ const newState_2 = [...dndItems];
14540
+ newState_2[grpIdx] = {
14541
+ ...group_1,
13844
14542
  entries: reordered
13845
14543
  };
13846
- setDndItems(newState_3);
13847
- onPersist?.(newState_3);
14544
+ setDndItems(newState_2);
14545
+ onPersist?.(newState_2);
14546
+ }
14547
+ }
14548
+ } else if (overCont_1 && activeCont_0 !== overCont_1) {
14549
+ const finalState = cloneItemsForDnd(sourceState);
14550
+ const finalOverId = lastOverId.current || overIdNow_0;
14551
+ const cleanOverCont = findContainerInState(finalOverId, sourceState) || overCont_1;
14552
+ const srcIdx_1 = finalState.findIndex((g_18) => g_18.name === activeCont_0);
14553
+ const tgtIdx_0 = finalState.findIndex((g_19) => g_19.name === cleanOverCont);
14554
+ if (srcIdx_1 !== -1 && tgtIdx_0 !== -1) {
14555
+ const src_1 = finalState[srcIdx_1];
14556
+ const tgt_0 = finalState[tgtIdx_0];
14557
+ const idxInSrc_1 = src_1.entries.findIndex((e_8) => e_8.url === activeIdNow_0);
14558
+ if (idxInSrc_1 !== -1) {
14559
+ const [moved_0] = src_1.entries.splice(idxInSrc_1, 1);
14560
+ const overIsContainer_1 = finalOverId === cleanOverCont;
14561
+ if (overIsContainer_1) {
14562
+ tgt_0.entries.push(moved_0);
14563
+ } else {
14564
+ const overIdx_0 = tgt_0.entries.findIndex((e_9) => e_9.url === finalOverId);
14565
+ if (overIdx_0 !== -1) {
14566
+ tgt_0.entries.splice(overIdx_0, 0, moved_0);
14567
+ } else {
14568
+ tgt_0.entries.push(moved_0);
14569
+ }
14570
+ }
14571
+ if (src_1.entries.length === 0) {
14572
+ finalState.splice(srcIdx_1, 1);
14573
+ }
14574
+ setDndItems(finalState);
14575
+ onPersist?.(finalState);
14576
+ onCardMovedBetweenGroups?.(moved_0);
13848
14577
  }
13849
14578
  }
13850
- } else if (recentlyMovedToNewContainer.current && interimItemsRef.current) {
13851
- onPersist?.(interimItemsRef.current);
14579
+ } else if (recentlyMovedToNewContainer.current) {
14580
+ console.error("Move between containers detected but conditions not met", {
14581
+ activeCont: activeCont_0,
14582
+ overCont: overCont_1,
14583
+ activeIdNow: activeIdNow_0,
14584
+ overIdNow: overIdNow_0
14585
+ });
13852
14586
  }
13853
- onCardMovedBetweenGroups?.(dndItems.flatMap((g_17) => g_17.entries).find((e_6) => e_6.url === activeIdNow_0));
13854
14587
  }
13855
14588
  }
13856
14589
  resetDragState();
@@ -13863,15 +14596,13 @@
13863
14596
  setIsDraggingCardOnly(false);
13864
14597
  recentlyMovedToNewContainer.current = false;
13865
14598
  };
13866
- const handleDragCancel = () => {
13867
- resetDragState();
13868
- };
14599
+ const handleDragCancel = () => resetDragState();
13869
14600
  const handleRenameGroup = (oldName, newName) => {
13870
- setDndItems((current) => {
13871
- const idx = current.findIndex((g_18) => g_18.name === oldName);
13872
- if (idx === -1) return current;
13873
- if (current.some((g_19) => g_19.name === newName && g_19.name !== oldName)) return current;
13874
- const updated = [...current];
14601
+ setDndItems((current_0) => {
14602
+ const idx = current_0.findIndex((g_20) => g_20.name === oldName);
14603
+ if (idx === -1) return current_0;
14604
+ if (current_0.some((g_21) => g_21.name === newName && g_21.name !== oldName)) return current_0;
14605
+ const updated = [...current_0];
13875
14606
  updated[idx] = {
13876
14607
  ...updated[idx],
13877
14608
  name: newName
@@ -13879,9 +14610,20 @@
13879
14610
  onPersist?.(updated);
13880
14611
  return updated;
13881
14612
  });
14613
+ setPendingNewGroupName(null);
14614
+ setStateBeforeNewGroup(null);
14615
+ setDialogOpenForGroup(null);
13882
14616
  };
13883
- const activeItemForOverlay = disabled || !activeId || activeIsGroup ? null : dndItems.flatMap((g_20) => g_20.entries).find((e_7) => e_7.url === activeId) || null;
13884
- const activeGroupData = disabled || !activeId || !activeIsGroup ? null : dndItems.find((g_21) => g_21.name === activeId) || null;
14617
+ const handleDialogClose = () => {
14618
+ if (pendingNewGroupName && dialogOpenForGroup === pendingNewGroupName && stateBeforeNewGroup) {
14619
+ setDndItems(stateBeforeNewGroup);
14620
+ }
14621
+ setPendingNewGroupName(null);
14622
+ setStateBeforeNewGroup(null);
14623
+ setDialogOpenForGroup(null);
14624
+ };
14625
+ const activeItemForOverlay = disabled || !activeId || activeIsGroup ? null : dndItems.flatMap((g_22) => g_22.entries).find((e_10) => e_10.url === activeId) || null;
14626
+ const activeGroupData = disabled || !activeId || !activeIsGroup ? null : dndItems.find((g_23) => g_23.name === activeId) || null;
13885
14627
  return {
13886
14628
  sensors,
13887
14629
  collisionDetection,
@@ -13899,6 +14641,7 @@
13899
14641
  dialogOpenForGroup,
13900
14642
  setDialogOpenForGroup,
13901
14643
  handleRenameGroup,
14644
+ handleDialogClose,
13902
14645
  isHoveringNewGroupDropZone,
13903
14646
  setIsHoveringNewGroupDropZone
13904
14647
  };
@@ -13999,7 +14742,7 @@
13999
14742
  return t8;
14000
14743
  }
14001
14744
  function RenameGroupDialog(t0) {
14002
- const $ = reactCompilerRuntime.c(41);
14745
+ const $ = reactCompilerRuntime.c(40);
14003
14746
  const {
14004
14747
  open,
14005
14748
  initialName,
@@ -14191,19 +14934,18 @@
14191
14934
  t15 = $[35];
14192
14935
  }
14193
14936
  let t16;
14194
- if ($[36] !== onClose || $[37] !== open || $[38] !== t11 || $[39] !== t15) {
14195
- t16 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Dialog, { open, onOpenChange: onClose, children: [
14937
+ if ($[36] !== open || $[37] !== t11 || $[38] !== t15) {
14938
+ t16 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Dialog, { open, children: [
14196
14939
  t6,
14197
14940
  t11,
14198
14941
  t15
14199
14942
  ] });
14200
- $[36] = onClose;
14201
- $[37] = open;
14202
- $[38] = t11;
14203
- $[39] = t15;
14204
- $[40] = t16;
14943
+ $[36] = open;
14944
+ $[37] = t11;
14945
+ $[38] = t15;
14946
+ $[39] = t16;
14205
14947
  } else {
14206
- t16 = $[40];
14948
+ t16 = $[39];
14207
14949
  }
14208
14950
  return t16;
14209
14951
  }
@@ -14277,7 +15019,7 @@
14277
15019
  entries: []
14278
15020
  });
14279
15021
  }
14280
- allProcessed = allProcessed.filter((g_4) => g_4.entries.length || groupOrderFromNavController.includes(g_4.name) || g_4.name === DEFAULT_GROUP_NAME && hasPluginAdditionalCards);
15022
+ allProcessed = allProcessed.filter((g_4) => g_4.entries.length || g_4.name === DEFAULT_GROUP_NAME && hasPluginAdditionalCards);
14281
15023
  }
14282
15024
  const admin = allProcessed.find((g_5) => g_5.name === ADMIN_GROUP_NAME);
14283
15025
  return {
@@ -14303,16 +15045,11 @@
14303
15045
  }] : draggable;
14304
15046
  onNavigationEntriesUpdate(all);
14305
15047
  };
14306
- const [collapsedGroups, setCollapsedGroups] = React.useState({});
14307
- const isGroupCollapsed = React.useCallback((name_0) => {
14308
- return !!collapsedGroups[name_0];
14309
- }, [collapsedGroups]);
14310
- const toggleGroupCollapsed = React.useCallback((name_1) => {
14311
- setCollapsedGroups((prev) => ({
14312
- ...prev,
14313
- [name_1]: !prev[name_1]
14314
- }));
14315
- }, []);
15048
+ const groupNames = React.useMemo(() => [...items.map((item) => item.name), ...adminGroupData ? [adminGroupData.name] : []], [items, adminGroupData]);
15049
+ const {
15050
+ isGroupCollapsed,
15051
+ toggleGroupCollapsed
15052
+ } = useCollapsedGroups(groupNames);
14316
15053
  const {
14317
15054
  sensors,
14318
15055
  collisionDetection,
@@ -14330,6 +15067,7 @@
14330
15067
  dialogOpenForGroup,
14331
15068
  setDialogOpenForGroup,
14332
15069
  handleRenameGroup,
15070
+ handleDialogClose,
14333
15071
  isHoveringNewGroupDropZone,
14334
15072
  setIsHoveringNewGroupDropZone
14335
15073
  } = useHomePageDnd({
@@ -14337,22 +15075,12 @@
14337
15075
  setItems: updateItems,
14338
15076
  disabled: !allowDragAndDrop || performingSearch,
14339
15077
  onPersist: persistNavigationGroups,
14340
- // ——► persistence here
14341
15078
  onGroupMoved: (g_8) => context.analyticsController?.onAnalyticsEvent?.("home_move_group", {
14342
15079
  name: g_8
14343
15080
  }),
14344
- onCardMovedBetweenGroups: (card) => {
14345
- let targetGroup = items.find((group) => group.entries.some((entry) => entry.url === card.url));
14346
- if (!targetGroup && adminGroupData?.entries.some((entry_0) => entry_0.url === card.url)) {
14347
- targetGroup = adminGroupData;
14348
- }
14349
- if (targetGroup && isGroupCollapsed(targetGroup.name)) {
14350
- toggleGroupCollapsed(targetGroup.name);
14351
- }
14352
- context.analyticsController?.onAnalyticsEvent?.("home_move_card", {
14353
- id: card.id
14354
- });
14355
- },
15081
+ onCardMovedBetweenGroups: (card) => context.analyticsController?.onAnalyticsEvent?.("home_move_card", {
15082
+ id: card.id
15083
+ }),
14356
15084
  onNewGroupDrop: () => context.analyticsController?.onAnalyticsEvent?.("home_drop_new_group")
14357
15085
  });
14358
15086
  const {
@@ -14392,7 +15120,7 @@
14392
15120
  frequency: 500
14393
15121
  }
14394
15122
  }, onDragStart, onDragOver, onDragEnd, onDragCancel, modifiers: dndModifiers, children: [
14395
- /* @__PURE__ */ jsxRuntime.jsx(sortable.SortableContext, { items: containers, strategy: sortable.verticalListSortingStrategy, children: items.map((groupData) => {
15123
+ /* @__PURE__ */ jsxRuntime.jsx(sortable.SortableContext, { items: containers, strategy: sortable.verticalListSortingStrategy, children: items.map((groupData, groupIndex) => {
14396
15124
  const groupKey = groupData.name;
14397
15125
  const entriesInGroup = groupData.entries;
14398
15126
  const AdditionalCards = [];
@@ -14403,22 +15131,22 @@
14403
15131
  group: groupKey === DEFAULT_GROUP_NAME ? void 0 : groupKey,
14404
15132
  context
14405
15133
  };
14406
- if (entriesInGroup.length === 0 && (AdditionalCards.length === 0 || performingSearch) && !groupOrderFromNavController.includes(groupKey)) return null;
15134
+ if (entriesInGroup.length === 0 && (AdditionalCards.length === 0 || performingSearch)) return null;
14407
15135
  return /* @__PURE__ */ jsxRuntime.jsx(SortableNavigationGroup, { groupName: groupKey, disabled: dndDisabled, children: /* @__PURE__ */ jsxRuntime.jsx(NavigationGroup, { group: groupKey === DEFAULT_GROUP_NAME ? void 0 : groupKey, minimised: draggingGroupId === groupKey && !isDraggingCardOnly, isPotentialCardDropTarget: isDraggingCardOnly, dndDisabled, onEditGroup: () => {
14408
15136
  if (dndDisabled) return;
14409
15137
  setDialogOpenForGroup(groupKey);
14410
15138
  }, collapsed: isGroupCollapsed(groupKey), onToggleCollapsed: () => toggleGroupCollapsed(groupKey), children: /* @__PURE__ */ jsxRuntime.jsx(NavigationGroupDroppable, { id: groupKey, itemIds: entriesInGroup.map((e_4) => e_4.url), isPotentialCardDropTarget: isDraggingCardOnly, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 ", children: [
14411
- entriesInGroup.map((entry_1) => /* @__PURE__ */ jsxRuntime.jsx(SortableNavigationCard, { entry: entry_1, onClick: () => {
15139
+ entriesInGroup.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(SortableNavigationCard, { entry, onClick: () => {
14412
15140
  let event = "unmapped_event";
14413
- if (entry_1.type === "collection") event = "home_navigate_to_collection";
14414
- else if (entry_1.type === "view") event = "home_navigate_to_view";
14415
- else if (entry_1.type === "admin") event = "home_navigate_to_admin_view";
15141
+ if (entry.type === "collection") event = "home_navigate_to_collection";
15142
+ else if (entry.type === "view") event = "home_navigate_to_view";
15143
+ else if (entry.type === "admin") event = "home_navigate_to_admin_view";
14416
15144
  context.analyticsController?.onAnalyticsEvent?.(event, {
14417
- path: entry_1.path
15145
+ path: entry.path
14418
15146
  });
14419
- } }, entry_1.url)),
15147
+ } }, entry.url)),
14420
15148
  !performingSearch && groupKey.toLowerCase() !== ADMIN_GROUP_NAME.toLowerCase() && AdditionalCards.map((C, i_1) => /* @__PURE__ */ jsxRuntime.jsx(C, { ...actionProps }, `extra_${groupKey}_${i_1}`))
14421
- ] }) }) }) }, groupKey);
15149
+ ] }) }) }) }, `group-${groupIndex}`);
14422
15150
  }) }, JSON.stringify(containers)),
14423
15151
  /* @__PURE__ */ jsxRuntime.jsx(NewGroupDropZone, { disabled: dndDisabled, setIsHovering: setIsHoveringNewGroupDropZone }),
14424
15152
  /* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { adjustScale: false, dropAnimation, children: activeGroupData && draggingGroupId === activeGroupData.name ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-transparent", style: {
@@ -14426,22 +15154,21 @@
14426
15154
  margin: 0
14427
15155
  }, children: /* @__PURE__ */ jsxRuntime.jsx(NavigationGroup, { group: activeGroupData.name === DEFAULT_GROUP_NAME ? void 0 : activeGroupData.name, isPreview: false, minimised: true }) }) : activeItemForOverlay ? /* @__PURE__ */ jsxRuntime.jsx(NavigationCardBinding, { ...activeItemForOverlay, shrink: isHoveringNewGroupDropZone }) : null })
14428
15156
  ] }),
14429
- !performingSearch && adminGroupData && /* @__PURE__ */ jsxRuntime.jsx(NavigationGroup, { group: adminGroupData.name, collapsed: isGroupCollapsed(adminGroupData.name), onToggleCollapsed: () => toggleGroupCollapsed(adminGroupData.name), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 ", children: adminGroupData.entries.map((entry_2) => /* @__PURE__ */ jsxRuntime.jsx(NavigationCardBinding, { ...entry_2, onClick: () => {
15157
+ !performingSearch && adminGroupData && /* @__PURE__ */ jsxRuntime.jsx(NavigationGroup, { group: adminGroupData.name, collapsed: isGroupCollapsed(adminGroupData.name), onToggleCollapsed: () => toggleGroupCollapsed(adminGroupData.name), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 ", children: adminGroupData.entries.map((entry_0) => /* @__PURE__ */ jsxRuntime.jsx(NavigationCardBinding, { ...entry_0, onClick: () => {
14430
15158
  let event_0 = "unmapped_event";
14431
- if (entry_2.type === "collection") event_0 = "home_navigate_to_collection";
14432
- else if (entry_2.type === "view") event_0 = "home_navigate_to_view";
14433
- else if (entry_2.type === "admin") event_0 = "home_navigate_to_admin_view";
15159
+ if (entry_0.type === "collection") event_0 = "home_navigate_to_collection";
15160
+ else if (entry_0.type === "view") event_0 = "home_navigate_to_view";
15161
+ else if (entry_0.type === "admin") event_0 = "home_navigate_to_admin_view";
14434
15162
  context.analyticsController?.onAnalyticsEvent?.(event_0, {
14435
- path: entry_2.path
15163
+ path: entry_0.path
14436
15164
  });
14437
- } }, entry_2.url)) }) }),
15165
+ } }, entry_0.url)) }) }),
14438
15166
  additionalPluginSections,
14439
15167
  additionalPluginChildrenEnd,
14440
15168
  additionalChildrenEnd
14441
15169
  ] }),
14442
- dialogOpenForGroup && /* @__PURE__ */ jsxRuntime.jsx(RenameGroupDialog, { open: true, initialName: dialogOpenForGroup, existingGroupNames: items.map((g_9) => g_9.name).filter((n) => n !== dialogOpenForGroup), onClose: () => setDialogOpenForGroup(null), onRename: (newName) => {
15170
+ dialogOpenForGroup && /* @__PURE__ */ jsxRuntime.jsx(RenameGroupDialog, { open: true, initialName: dialogOpenForGroup, existingGroupNames: items.map((g_9) => g_9.name).filter((n) => n !== dialogOpenForGroup), onClose: handleDialogClose, onRename: (newName) => {
14443
15171
  handleRenameGroup(dialogOpenForGroup, newName);
14444
- setDialogOpenForGroup(null);
14445
15172
  } })
14446
15173
  ] });
14447
15174
  }
@@ -14764,61 +15491,60 @@
14764
15491
  ] });
14765
15492
  }
14766
15493
  const ErrorFocus = (t0) => {
14767
- const $ = reactCompilerRuntime.c(6);
15494
+ const $ = reactCompilerRuntime.c(10);
14768
15495
  const {
14769
15496
  containerRef
14770
15497
  } = t0;
14771
15498
  const {
14772
- isSubmitting,
14773
15499
  isValidating,
14774
- errors
15500
+ errors,
15501
+ version
14775
15502
  } = formex.useFormex();
15503
+ const prevVersion = React.useRef(version);
14776
15504
  let t1;
14777
- let t2;
14778
- if ($[0] !== containerRef || $[1] !== errors || $[2] !== isSubmitting || $[3] !== isValidating) {
15505
+ if ($[0] !== containerRef?.current || $[1] !== errors || $[2] !== isValidating || $[3] !== version) {
14779
15506
  t1 = () => {
15507
+ if (version === prevVersion.current) {
15508
+ return;
15509
+ }
14780
15510
  const keys = Object.keys(errors);
14781
- if (keys.length > 0 && isSubmitting && !isValidating) {
15511
+ if (!isValidating && keys.length > 0) {
14782
15512
  const errorElement = containerRef?.current?.querySelector(`#form_field_${keys[0]}`);
14783
- if (errorElement && containerRef?.current) {
14784
- const scrollableParent = getScrollableParent(containerRef.current);
14785
- if (scrollableParent) {
14786
- const top = errorElement.getBoundingClientRect().top;
14787
- scrollableParent.scrollTo({
14788
- top: scrollableParent.scrollTop + top - 196,
14789
- behavior: "smooth"
14790
- });
14791
- }
15513
+ if (errorElement) {
15514
+ errorElement.scrollIntoView({
15515
+ behavior: "smooth",
15516
+ block: "center"
15517
+ });
14792
15518
  const input = errorElement.querySelector("input");
14793
15519
  if (input) {
14794
15520
  input.focus();
14795
15521
  }
14796
15522
  }
15523
+ prevVersion.current = version;
14797
15524
  }
14798
15525
  };
14799
- t2 = [isSubmitting, isValidating, errors, containerRef];
14800
- $[0] = containerRef;
15526
+ $[0] = containerRef?.current;
14801
15527
  $[1] = errors;
14802
- $[2] = isSubmitting;
14803
- $[3] = isValidating;
15528
+ $[2] = isValidating;
15529
+ $[3] = version;
14804
15530
  $[4] = t1;
14805
- $[5] = t2;
14806
15531
  } else {
14807
15532
  t1 = $[4];
14808
- t2 = $[5];
15533
+ }
15534
+ let t2;
15535
+ if ($[5] !== containerRef || $[6] !== errors || $[7] !== isValidating || $[8] !== version) {
15536
+ t2 = [isValidating, errors, containerRef, version];
15537
+ $[5] = containerRef;
15538
+ $[6] = errors;
15539
+ $[7] = isValidating;
15540
+ $[8] = version;
15541
+ $[9] = t2;
15542
+ } else {
15543
+ t2 = $[9];
14809
15544
  }
14810
15545
  React.useEffect(t1, t2);
14811
15546
  return null;
14812
15547
  };
14813
- const isScrollable = (ele) => {
14814
- const hasScrollableContent = ele && ele.scrollHeight > ele.clientHeight;
14815
- const overflowYStyle = ele ? window.getComputedStyle(ele).overflowY : null;
14816
- const isOverflowHidden = overflowYStyle && overflowYStyle.indexOf("hidden") !== -1;
14817
- return hasScrollableContent && !isOverflowHidden;
14818
- };
14819
- const getScrollableParent = (ele) => {
14820
- return !ele || ele === document.body ? document.body : isScrollable(ele) ? ele : getScrollableParent(ele.parentNode);
14821
- };
14822
15548
  function EntityFormActions(t0) {
14823
15549
  const $ = reactCompilerRuntime.c(16);
14824
15550
  const {
@@ -14839,7 +15565,7 @@
14839
15565
  const context = useFireCMSContext();
14840
15566
  const sideEntityController = useSideEntityController();
14841
15567
  let t1;
14842
- if ($[0] !== collection || $[1] !== context || $[2] !== disabled || $[3] !== entity || $[4] !== formContext || $[5] !== formex2.isSubmitting || $[6] !== fullIdPath || $[7] !== fullPath || $[8] !== layout || $[9] !== navigateBack || $[10] !== openEntityMode || $[11] !== pluginActions || $[12] !== savingError || $[13] !== sideEntityController || $[14] !== status) {
15568
+ if ($[0] !== collection || $[1] !== context || $[2] !== disabled || $[3] !== entity || $[4] !== formContext || $[5] !== formex2 || $[6] !== fullIdPath || $[7] !== fullPath || $[8] !== layout || $[9] !== navigateBack || $[10] !== openEntityMode || $[11] !== pluginActions || $[12] !== savingError || $[13] !== sideEntityController || $[14] !== status) {
14843
15569
  t1 = layout === "bottom" ? buildBottomActions$1({
14844
15570
  fullPath,
14845
15571
  fullIdPath,
@@ -14848,13 +15574,13 @@
14848
15574
  collection,
14849
15575
  context,
14850
15576
  sideEntityController,
14851
- isSubmitting: formex2.isSubmitting,
14852
15577
  disabled,
14853
15578
  status,
14854
15579
  pluginActions,
14855
15580
  openEntityMode,
14856
15581
  navigateBack,
14857
- formContext
15582
+ formContext,
15583
+ formex: formex2
14858
15584
  }) : buildSideActions$1({
14859
15585
  fullPath,
14860
15586
  fullIdPath,
@@ -14863,18 +15589,18 @@
14863
15589
  collection,
14864
15590
  context,
14865
15591
  sideEntityController,
14866
- isSubmitting: formex2.isSubmitting,
14867
15592
  disabled,
14868
15593
  status,
14869
15594
  pluginActions,
14870
- openEntityMode
15595
+ openEntityMode,
15596
+ formex: formex2
14871
15597
  });
14872
15598
  $[0] = collection;
14873
15599
  $[1] = context;
14874
15600
  $[2] = disabled;
14875
15601
  $[3] = entity;
14876
15602
  $[4] = formContext;
14877
- $[5] = formex2.isSubmitting;
15603
+ $[5] = formex2;
14878
15604
  $[6] = fullIdPath;
14879
15605
  $[7] = fullPath;
14880
15606
  $[8] = layout;
@@ -14899,14 +15625,15 @@
14899
15625
  collection,
14900
15626
  context,
14901
15627
  sideEntityController,
14902
- isSubmitting,
14903
15628
  disabled,
14904
15629
  status,
14905
15630
  pluginActions,
14906
15631
  openEntityMode,
14907
15632
  navigateBack,
14908
- formContext
15633
+ formContext,
15634
+ formex: formex2
14909
15635
  }) {
15636
+ const hasErrors = Object.keys(formex2.errors).length > 0 && formex2.submitCount > 0;
14910
15637
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { position: "absolute", children: [
14911
15638
  savingError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { color: "error", children: savingError.message }) }),
14912
15639
  entity && (formActions ?? []).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow flex overflow-auto no-scrollbar", children: (formActions ?? []).map((action) => /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { color: "primary", onClick: (event) => {
@@ -14925,39 +15652,361 @@
14925
15652
  });
14926
15653
  }, children: action.icon }, action.name)) }),
14927
15654
  pluginActions,
14928
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", disabled: disabled || isSubmitting, color: "primary", type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
14929
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "filled", color: "primary", type: "submit", disabled: disabled || isSubmitting, children: [
15655
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", disabled: disabled || formex2.isSubmitting, color: "primary", type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
15656
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "filled", color: "primary", type: "submit", disabled: disabled || formex2.isSubmitting, startIcon: hasErrors ? /* @__PURE__ */ jsxRuntime.jsx(ui.ErrorIcon, {}) : void 0, children: [
14930
15657
  status === "existing" && "Save",
14931
15658
  status === "copy" && "Create copy",
14932
15659
  status === "new" && "Create"
14933
15660
  ] })
14934
15661
  ] });
14935
15662
  }
14936
- function buildSideActions$1({
14937
- savingError,
14938
- entity,
14939
- formActions,
14940
- fullPath,
14941
- fullIdPath,
14942
- openEntityMode,
14943
- collection,
14944
- context,
14945
- sideEntityController,
14946
- isSubmitting,
14947
- disabled,
14948
- status,
14949
- pluginActions
14950
- }) {
14951
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", ui.defaultBorderMixin), children: [
14952
- /* @__PURE__ */ jsxRuntime.jsxs(ui.LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", disabled: disabled || isSubmitting, children: [
14953
- status === "existing" && "Save",
14954
- status === "copy" && "Create copy",
14955
- status === "new" && "Create"
14956
- ] }),
14957
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { fullWidth: true, variant: "text", disabled: disabled || isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
14958
- pluginActions,
14959
- savingError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { color: "error", children: savingError.message }) })
14960
- ] });
15663
+ function buildSideActions$1({
15664
+ savingError,
15665
+ entity,
15666
+ formActions,
15667
+ fullPath,
15668
+ fullIdPath,
15669
+ openEntityMode,
15670
+ collection,
15671
+ context,
15672
+ sideEntityController,
15673
+ disabled,
15674
+ status,
15675
+ pluginActions,
15676
+ formex: formex2
15677
+ }) {
15678
+ const hasErrors = Object.keys(formex2.errors).length > 0 && formex2.submitCount > 0;
15679
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", ui.defaultBorderMixin), children: [
15680
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", startIcon: hasErrors ? /* @__PURE__ */ jsxRuntime.jsx(ui.ErrorIcon, {}) : void 0, disabled: disabled || formex2.isSubmitting, children: [
15681
+ status === "existing" && "Save",
15682
+ status === "copy" && "Create copy",
15683
+ status === "new" && "Create"
15684
+ ] }),
15685
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { fullWidth: true, variant: "text", disabled: disabled || formex2.isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
15686
+ pluginActions,
15687
+ savingError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { color: "error", children: savingError.message }) })
15688
+ ] });
15689
+ }
15690
+ function LocalChangesMenu(t0) {
15691
+ const $ = reactCompilerRuntime.c(42);
15692
+ const {
15693
+ localChangesData,
15694
+ formex: formex2,
15695
+ onClearLocalChanges,
15696
+ cacheKey,
15697
+ properties
15698
+ } = t0;
15699
+ const snackbarController = useSnackbarController();
15700
+ const [previewDialogOpen, setPreviewDialogOpen] = React.useState(false);
15701
+ const [open, setOpen] = React.useState(false);
15702
+ let t1;
15703
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
15704
+ t1 = () => setOpen(true);
15705
+ $[0] = t1;
15706
+ } else {
15707
+ t1 = $[0];
15708
+ }
15709
+ const handleOpenMenu = t1;
15710
+ let t2;
15711
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
15712
+ t2 = () => setOpen(false);
15713
+ $[1] = t2;
15714
+ } else {
15715
+ t2 = $[1];
15716
+ }
15717
+ const handleCloseMenu = t2;
15718
+ let t3;
15719
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
15720
+ t3 = () => {
15721
+ setPreviewDialogOpen(true);
15722
+ handleCloseMenu();
15723
+ };
15724
+ $[2] = t3;
15725
+ } else {
15726
+ t3 = $[2];
15727
+ }
15728
+ const handlePreview = t3;
15729
+ let t4;
15730
+ if ($[3] !== formex2 || $[4] !== localChangesData || $[5] !== onClearLocalChanges || $[6] !== snackbarController) {
15731
+ t4 = () => {
15732
+ const mergedValues = mergeDeep(formex2.values, localChangesData);
15733
+ const touched = {
15734
+ ...formex2.touched
15735
+ };
15736
+ const previewKeys = flattenKeys(localChangesData);
15737
+ previewKeys.forEach((key) => {
15738
+ touched[key] = true;
15739
+ });
15740
+ formex2.setTouched(touched);
15741
+ formex2.setValues(mergedValues);
15742
+ snackbarController.open({
15743
+ type: "info",
15744
+ message: "Local changes applied to the form"
15745
+ });
15746
+ handleCloseMenu();
15747
+ onClearLocalChanges?.();
15748
+ };
15749
+ $[3] = formex2;
15750
+ $[4] = localChangesData;
15751
+ $[5] = onClearLocalChanges;
15752
+ $[6] = snackbarController;
15753
+ $[7] = t4;
15754
+ } else {
15755
+ t4 = $[7];
15756
+ }
15757
+ const handleApply = t4;
15758
+ let t5;
15759
+ if ($[8] !== cacheKey || $[9] !== onClearLocalChanges || $[10] !== snackbarController) {
15760
+ t5 = () => {
15761
+ removeEntityFromCache(cacheKey);
15762
+ snackbarController.open({
15763
+ type: "info",
15764
+ message: "Local changes discarded"
15765
+ });
15766
+ handleCloseMenu();
15767
+ onClearLocalChanges?.();
15768
+ };
15769
+ $[8] = cacheKey;
15770
+ $[9] = onClearLocalChanges;
15771
+ $[10] = snackbarController;
15772
+ $[11] = t5;
15773
+ } else {
15774
+ t5 = $[11];
15775
+ }
15776
+ const handleDiscard = t5;
15777
+ let t6;
15778
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
15779
+ t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.WarningIcon, { size: "smallest", className: "mr-1 text-yellow-600 dark:text-yellow-400" });
15780
+ $[12] = t6;
15781
+ } else {
15782
+ t6 = $[12];
15783
+ }
15784
+ let t7;
15785
+ if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
15786
+ t7 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", className: "font-semibold text-xs rounded-full px-4 py-1 bg-yellow-200 dark:bg-yellow-900 hover:bg-yellow-300 dark:hover:bg-yellow-800 text-yellow-800 dark:text-yellow-200", onClick: handleOpenMenu, children: [
15787
+ t6,
15788
+ "Unsaved Local changes",
15789
+ /* @__PURE__ */ jsxRuntime.jsx(ui.KeyboardArrowDownIcon, { size: "smallest" })
15790
+ ] });
15791
+ $[13] = t7;
15792
+ } else {
15793
+ t7 = $[13];
15794
+ }
15795
+ let t8;
15796
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
15797
+ t8 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xs px-4 py-4 text-sm text-gray-700 dark:text-gray-300", children: "This document was edited locally and has unsaved changes. These local changes will be lost if you don't apply them." });
15798
+ $[14] = t8;
15799
+ } else {
15800
+ t8 = $[14];
15801
+ }
15802
+ let t9;
15803
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
15804
+ t9 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handlePreview, children: [
15805
+ /* @__PURE__ */ jsxRuntime.jsx(ui.VisibilityIcon, { size: "small" }),
15806
+ "Preview Changes"
15807
+ ] });
15808
+ $[15] = t9;
15809
+ } else {
15810
+ t9 = $[15];
15811
+ }
15812
+ let t10;
15813
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
15814
+ t10 = /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "small" });
15815
+ $[16] = t10;
15816
+ } else {
15817
+ t10 = $[16];
15818
+ }
15819
+ let t11;
15820
+ if ($[17] !== handleApply) {
15821
+ t11 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handleApply, children: [
15822
+ t10,
15823
+ "Apply Changes"
15824
+ ] });
15825
+ $[17] = handleApply;
15826
+ $[18] = t11;
15827
+ } else {
15828
+ t11 = $[18];
15829
+ }
15830
+ let t12;
15831
+ if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
15832
+ t12 = /* @__PURE__ */ jsxRuntime.jsx(ui.CancelIcon, { size: "small" });
15833
+ $[19] = t12;
15834
+ } else {
15835
+ t12 = $[19];
15836
+ }
15837
+ let t13;
15838
+ if ($[20] !== handleDiscard) {
15839
+ t13 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handleDiscard, children: [
15840
+ t12,
15841
+ "Discard Local Changes"
15842
+ ] });
15843
+ $[20] = handleDiscard;
15844
+ $[21] = t13;
15845
+ } else {
15846
+ t13 = $[21];
15847
+ }
15848
+ let t14;
15849
+ if ($[22] !== open || $[23] !== t11 || $[24] !== t13) {
15850
+ t14 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Menu, { trigger: t7, open, onOpenChange: setOpen, children: [
15851
+ t8,
15852
+ t9,
15853
+ t11,
15854
+ t13
15855
+ ] });
15856
+ $[22] = open;
15857
+ $[23] = t11;
15858
+ $[24] = t13;
15859
+ $[25] = t14;
15860
+ } else {
15861
+ t14 = $[25];
15862
+ }
15863
+ let t15;
15864
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
15865
+ t15 = /* @__PURE__ */ jsxRuntime.jsx(ui.DialogTitle, { variant: "h6", children: "Preview Local Changes" });
15866
+ $[26] = t15;
15867
+ } else {
15868
+ t15 = $[26];
15869
+ }
15870
+ let t16;
15871
+ if ($[27] === Symbol.for("react.memo_cache_sentinel")) {
15872
+ t16 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", className: "mb-4", children: "These are the local changes that will be applied to the form." });
15873
+ $[27] = t16;
15874
+ } else {
15875
+ t16 = $[27];
15876
+ }
15877
+ let t17;
15878
+ if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
15879
+ t17 = {
15880
+ maxHeight: 520,
15881
+ overflow: "auto"
15882
+ };
15883
+ $[28] = t17;
15884
+ } else {
15885
+ t17 = $[28];
15886
+ }
15887
+ const t18 = properties;
15888
+ let t19;
15889
+ if ($[29] !== localChangesData || $[30] !== t18) {
15890
+ t19 = /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { className: "my-4", children: [
15891
+ t16,
15892
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `border rounded-lg ${ui.defaultBorderMixin}`, style: t17, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyCollectionView, { data: localChangesData, properties: t18 }) }) })
15893
+ ] });
15894
+ $[29] = localChangesData;
15895
+ $[30] = t18;
15896
+ $[31] = t19;
15897
+ } else {
15898
+ t19 = $[31];
15899
+ }
15900
+ let t20;
15901
+ if ($[32] === Symbol.for("react.memo_cache_sentinel")) {
15902
+ t20 = /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { onClick: () => setPreviewDialogOpen(false), children: "Close" });
15903
+ $[32] = t20;
15904
+ } else {
15905
+ t20 = $[32];
15906
+ }
15907
+ let t21;
15908
+ if ($[33] !== handleApply) {
15909
+ t21 = /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { children: [
15910
+ t20,
15911
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "filled", onClick: () => {
15912
+ handleApply();
15913
+ setPreviewDialogOpen(false);
15914
+ }, children: "Apply changes" })
15915
+ ] });
15916
+ $[33] = handleApply;
15917
+ $[34] = t21;
15918
+ } else {
15919
+ t21 = $[34];
15920
+ }
15921
+ let t22;
15922
+ if ($[35] !== previewDialogOpen || $[36] !== t19 || $[37] !== t21) {
15923
+ t22 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Dialog, { open: previewDialogOpen, onOpenChange: setPreviewDialogOpen, maxWidth: "4xl", children: [
15924
+ t15,
15925
+ t19,
15926
+ t21
15927
+ ] });
15928
+ $[35] = previewDialogOpen;
15929
+ $[36] = t19;
15930
+ $[37] = t21;
15931
+ $[38] = t22;
15932
+ } else {
15933
+ t22 = $[38];
15934
+ }
15935
+ let t23;
15936
+ if ($[39] !== t14 || $[40] !== t22) {
15937
+ t23 = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15938
+ t14,
15939
+ t22
15940
+ ] });
15941
+ $[39] = t14;
15942
+ $[40] = t22;
15943
+ $[41] = t23;
15944
+ } else {
15945
+ t23 = $[41];
15946
+ }
15947
+ return t23;
15948
+ }
15949
+ function extractTouchedValues(values, touched) {
15950
+ let acc = {};
15951
+ if (!touched || typeof touched !== "object") {
15952
+ return acc;
15953
+ }
15954
+ Object.entries(touched).forEach(([key, value]) => {
15955
+ if (value) {
15956
+ acc = formex.setIn(acc, key, formex.getIn(values, key));
15957
+ }
15958
+ });
15959
+ return acc;
15960
+ }
15961
+ function getChanges(source, comparison) {
15962
+ const changes = {};
15963
+ if (!source) {
15964
+ return {};
15965
+ }
15966
+ if (!comparison) {
15967
+ return source;
15968
+ }
15969
+ const allKeys = Array.from(/* @__PURE__ */ new Set([...Object.keys(source), ...Object.keys(comparison)]));
15970
+ for (const key of allKeys) {
15971
+ const sourceValue = source[key];
15972
+ const comparisonValue = comparison[key];
15973
+ if (equal(sourceValue, comparisonValue)) {
15974
+ continue;
15975
+ }
15976
+ const sourceHasKey = source && typeof source === "object" && Object.prototype.hasOwnProperty.call(source, key);
15977
+ const comparisonHasKey = comparison && typeof comparison === "object" && Object.prototype.hasOwnProperty.call(comparison, key);
15978
+ if (comparisonHasKey && !sourceHasKey) {
15979
+ changes[key] = void 0;
15980
+ } else if (Array.isArray(sourceValue)) {
15981
+ const comparisonArray = Array.isArray(comparisonValue) ? comparisonValue : [];
15982
+ if (sourceValue.length < comparisonArray.length) {
15983
+ changes[key] = sourceValue;
15984
+ continue;
15985
+ }
15986
+ const changedArray = sourceValue.map((item, index) => {
15987
+ const comparisonItem = comparisonArray[index];
15988
+ if (equal(item, comparisonItem)) {
15989
+ return null;
15990
+ }
15991
+ if (isObject(item) && item && isObject(comparisonItem) && comparisonItem) {
15992
+ const nestedChanges = getChanges(item, comparisonItem);
15993
+ return Object.keys(nestedChanges).length > 0 ? nestedChanges : item;
15994
+ }
15995
+ return item;
15996
+ });
15997
+ if (changedArray.some((item) => item !== null) || sourceValue.length > comparisonArray.length) {
15998
+ changes[key] = changedArray;
15999
+ }
16000
+ } else if (isObject(sourceValue) && sourceValue && isObject(comparisonValue) && comparisonValue) {
16001
+ const nestedChanges = getChanges(sourceValue, comparisonValue);
16002
+ if (Object.keys(nestedChanges).length > 0) {
16003
+ changes[key] = nestedChanges;
16004
+ }
16005
+ } else {
16006
+ changes[key] = sourceValue;
16007
+ }
16008
+ }
16009
+ return changes;
14961
16010
  }
14962
16011
  function EntityForm({
14963
16012
  path,
@@ -15016,7 +16065,7 @@
15016
16065
  const customizationController = useCustomizationController();
15017
16066
  const context = useFireCMSContext();
15018
16067
  const analyticsController = useAnalyticsController();
15019
- const [underlyingChanges, setUnderlyingChanges] = React.useState({});
16068
+ const [underlyingChanges] = React.useState({});
15020
16069
  const [customIdLoading, setCustomIdLoading] = React.useState(false);
15021
16070
  const mustSetCustomId = (status === "new" || status === "copy") && Boolean(collection.customId) && collection.customId !== "optional";
15022
16071
  const initialEntityId = React.useMemo(() => {
@@ -15034,6 +16083,12 @@
15034
16083
  const [entityIdError, setEntityIdError] = React.useState(false);
15035
16084
  const [savingError, setSavingError] = React.useState();
15036
16085
  const autoSave = collection.formAutoSave && !collection.customId;
16086
+ const baseInitialValues = React.useMemo(() => getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs), [authController, collection, path, status, entity, customizationController.propertyConfigs]);
16087
+ const localChangesDataRaw = React.useMemo(() => entityId ? getEntityFromCache(path + "/" + entityId) : getEntityFromCache(path + "#new"), [entityId, path]);
16088
+ const [localChangesCleared, setLocalChangesCleared] = React.useState(false);
16089
+ const localChangesBackup = getLocalChangesBackup(collection);
16090
+ const autoApplyLocalChanges = localChangesBackup === "auto_apply";
16091
+ const manualApplyLocalChanges = localChangesBackup === "manual_apply";
15037
16092
  const onSubmit = (values, formexController) => {
15038
16093
  if (mustSetCustomId && !entityId) {
15039
16094
  console.error("Missing custom Id");
@@ -15064,16 +16119,40 @@
15064
16119
  formexController.setSubmitting(false);
15065
16120
  });
15066
16121
  };
16122
+ const [initialValues_0, initialDirty_0] = React.useMemo(() => {
16123
+ const initialValuesWithLocalChanges = autoApplyLocalChanges && localChangesDataRaw ? mergeDeep(baseInitialValues, localChangesDataRaw) : baseInitialValues;
16124
+ const initialValues = initialDirtyValues ? mergeDeep(initialValuesWithLocalChanges, initialDirtyValues) : initialValuesWithLocalChanges;
16125
+ const initialDirty = Boolean(initialDirtyValues) && initialDirtyValues && Object.keys(initialDirtyValues).length > 0;
16126
+ return [initialValues, initialDirty];
16127
+ }, [autoApplyLocalChanges, localChangesDataRaw, baseInitialValues, initialDirtyValues]);
16128
+ const localChangesData = React.useMemo(() => {
16129
+ if (!localChangesDataRaw) {
16130
+ return void 0;
16131
+ }
16132
+ return getChanges(localChangesDataRaw, initialValues_0);
16133
+ }, [localChangesDataRaw, initialValues_0]);
16134
+ const hasLocalChanges = !localChangesCleared && localChangesData && Object.keys(localChangesData).length > 0;
15067
16135
  const formex$1 = formexProp ?? formex.useCreateFormex({
15068
- initialValues: initialDirtyValues ?? getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs),
15069
- initialDirty: Boolean(initialDirtyValues),
16136
+ initialValues: initialValues_0,
16137
+ initialDirty: initialDirty_0,
16138
+ initialTouched: initialDirtyValues ? flattenKeys(initialDirtyValues).reduce((previousValue, currentValue) => ({
16139
+ ...previousValue,
16140
+ [currentValue]: true
16141
+ }), {}) : {},
15070
16142
  onSubmit,
15071
16143
  onReset: () => {
15072
16144
  clearDirtyCache();
15073
- onValuesModified?.(false);
16145
+ onValuesModified?.(false, initialValues_0);
15074
16146
  },
15075
- validation: (values_0) => {
15076
- return validationSchema?.validate(values_0, {
16147
+ onValuesChangeDeferred: (values_0, controller) => {
16148
+ const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
16149
+ if (controller.dirty) {
16150
+ const touchedValues = extractTouchedValues(values_0, controller.touched);
16151
+ saveEntityToCache(key, touchedValues);
16152
+ }
16153
+ },
16154
+ validation: (values_1) => {
16155
+ return validationSchema?.validate(values_1, {
15077
16156
  abortEarly: false
15078
16157
  }).then(() => {
15079
16158
  return {};
@@ -15122,14 +16201,16 @@
15122
16201
  }, [snackbarController]);
15123
16202
  function clearDirtyCache() {
15124
16203
  if (status === "new" || status === "copy") {
16204
+ removeEntityFromMemoryCache(path + "#new");
15125
16205
  removeEntityFromCache(path + "#new");
15126
16206
  } else {
16207
+ removeEntityFromMemoryCache(path + "/" + entityId);
15127
16208
  removeEntityFromCache(path + "/" + entityId);
15128
16209
  }
15129
16210
  }
15130
16211
  const onSaveSuccess = (updatedEntity) => {
15131
16212
  clearDirtyCache();
15132
- onValuesModified?.(false);
16213
+ onValuesModified?.(false, updatedEntity.values);
15133
16214
  if (!autoSave) snackbarController.open({
15134
16215
  type: "success",
15135
16216
  message: `${collection.singularName ?? collection.name}: Saved correctly`
@@ -15156,7 +16237,7 @@
15156
16237
  console.error(e_3);
15157
16238
  }, [entityId, path, snackbarController]);
15158
16239
  const saveEntity = ({
15159
- values: values_1,
16240
+ values: values_2,
15160
16241
  previousValues,
15161
16242
  entityId: entityId_0,
15162
16243
  collection: collection_0,
@@ -15165,7 +16246,7 @@
15165
16246
  return saveEntityWithCallbacks({
15166
16247
  path: path_0,
15167
16248
  entityId: entityId_0,
15168
- values: values_1,
16249
+ values: values_2,
15169
16250
  previousValues,
15170
16251
  collection: collection_0,
15171
16252
  status,
@@ -15181,34 +16262,34 @@
15181
16262
  collection: collection_1,
15182
16263
  path: path_1,
15183
16264
  entityId: entityId_1,
15184
- values: values_2,
16265
+ values: values_3,
15185
16266
  previousValues: previousValues_0,
15186
16267
  autoSave: autoSave_0
15187
16268
  }) => {
15188
16269
  if (!status) return;
15189
16270
  if (autoSave_0) {
15190
- setValuesToBeSaved(values_2);
16271
+ setValuesToBeSaved(values_3);
15191
16272
  } else {
15192
16273
  return saveEntity({
15193
16274
  collection: collection_1,
15194
16275
  path: path_1,
15195
16276
  entityId: entityId_1,
15196
- values: values_2,
16277
+ values: values_3,
15197
16278
  previousValues: previousValues_0
15198
16279
  });
15199
16280
  }
15200
16281
  };
15201
16282
  const lastSavedValues = React.useRef(entity?.values);
15202
- const save = (values_3) => {
15203
- lastSavedValues.current = values_3;
16283
+ const save = (values_4) => {
16284
+ lastSavedValues.current = values_4;
15204
16285
  return onSaveEntityRequest({
15205
16286
  collection: resolvedCollection,
15206
16287
  path,
15207
16288
  entityId,
15208
- values: values_3,
16289
+ values: values_4,
15209
16290
  previousValues: entity?.values,
15210
16291
  autoSave: autoSave ?? false
15211
- }).then((res) => {
16292
+ }).then(() => {
15212
16293
  const eventName = status === "new" ? "new_entity_saved" : status === "copy" ? "entity_copied" : status === "existing" ? "entity_edited" : "unmapped_event";
15213
16294
  analyticsController.onAnalyticsEvent?.(eventName, {
15214
16295
  path
@@ -15242,7 +16323,8 @@
15242
16323
  type: "error",
15243
16324
  message: "Error updating id, check the console"
15244
16325
  });
15245
- }, []);
16326
+ console.error(error);
16327
+ }, [snackbarController]);
15246
16328
  const pluginActions = [];
15247
16329
  const plugins = customizationController.plugins;
15248
16330
  const actionsDisabled = disabled || formex$1.isSubmitting || status === "existing" && !formex$1.dirty || Boolean(disabledProp);
@@ -15288,23 +16370,15 @@
15288
16370
  }, [doOnIdUpdate]);
15289
16371
  React.useEffect(() => {
15290
16372
  if (!autoSave) {
15291
- onValuesModified?.(modified);
16373
+ onValuesModified?.(modified, formex$1.values);
15292
16374
  }
15293
16375
  }, [formex$1.dirty]);
15294
- const deferredValues = React.useDeferredValue(formex$1.values);
15295
16376
  const modified = formex$1.dirty;
15296
16377
  const uniqueFieldValidator = React.useCallback(({
15297
16378
  name,
15298
- value,
15299
- property
16379
+ value
15300
16380
  }) => dataSource.checkUniqueField(path, name, value, entityId, collection), [dataSource, path, entityId]);
15301
16381
  const validationSchema = React.useMemo(() => entityId ? getYupEntitySchema(entityId, resolvedCollection.properties, uniqueFieldValidator) : void 0, [entityId, resolvedCollection.properties, uniqueFieldValidator]);
15302
- React.useEffect(() => {
15303
- const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
15304
- if (modified) {
15305
- saveEntityToCache(key, deferredValues);
15306
- }
15307
- }, [deferredValues, modified, path, entityId, status]);
15308
16382
  useOnAutoSave(autoSave, formex$1, lastSavedValues, save);
15309
16383
  React.useEffect(() => {
15310
16384
  if (!autoSave && !formex$1.isSubmitting && underlyingChanges && entity) {
@@ -15323,18 +16397,18 @@
15323
16397
  return /* @__PURE__ */ jsxRuntime.jsx(Builder, { collection, entity, modifiedValues: formex$1.values, formContext });
15324
16398
  }
15325
16399
  return /* @__PURE__ */ jsxRuntime.jsx(FormLayout, { children: formFieldKeys.map((key_1) => {
15326
- const property_0 = resolvedCollection.properties[key_1];
15327
- if (property_0) {
16400
+ const property = resolvedCollection.properties[key_1];
16401
+ if (property) {
15328
16402
  const underlyingValueHasChanged = !!underlyingChanges && Object.keys(underlyingChanges).includes(key_1) && formex$1.touched[key_1];
15329
- const disabled_0 = disabledProp || !autoSave && formex$1.isSubmitting || isReadOnly(property_0) || Boolean(property_0.disabled);
15330
- const hidden = isHidden(property_0);
16403
+ const disabled_0 = disabledProp || !autoSave && formex$1.isSubmitting || isReadOnly(property) || Boolean(property.disabled);
16404
+ const hidden = isHidden(property);
15331
16405
  if (hidden) return null;
15332
- const widthPercentage = property_0.widthPercentage ?? 100;
16406
+ const widthPercentage = property.widthPercentage ?? 100;
15333
16407
  const cmsFormFieldProps = {
15334
16408
  propertyKey: key_1,
15335
16409
  disabled: disabled_0,
15336
- property: property_0,
15337
- includeDescription: property_0.description || property_0.longDescription,
16410
+ property,
16411
+ includeDescription: property.description || property.longDescription,
15338
16412
  underlyingValueHasChanged: underlyingValueHasChanged && !autoSave,
15339
16413
  context: formContext,
15340
16414
  partOfArray: false,
@@ -15390,10 +16464,13 @@
15390
16464
  }
15391
16465
  const dialogActions = /* @__PURE__ */ jsxRuntime.jsx(EntityFormActionsComponent, { collection: resolvedCollection, path, fullPath: path, fullIdPath, entity, layout: forceActionsAtTheBottom ? "bottom" : "side", savingError, formex: formex$1, disabled: actionsDisabled, status, pluginActions: pluginActions ?? [], openEntityMode, showDefaultActions, navigateBack, formContext });
15392
16466
  return /* @__PURE__ */ jsxRuntime.jsx(formex.Formex, { value: formex$1, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: formex$1.handleSubmit, onReset: () => formex$1.resetForm({
15393
- values: getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs)
16467
+ values: baseInitialValues
15394
16468
  }), noValidate: true, className: ui.cls("flex-1 flex flex-row w-full overflow-y-auto justify-center", className), children: [
15395
16469
  /* @__PURE__ */ jsxRuntime.jsx("div", { id: `form_${path}`, className: ui.cls("relative flex flex-row max-w-4xl lg:max-w-3xl xl:max-w-4xl 2xl:max-w-6xl w-full h-fit"), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("flex flex-col w-full pt-12 pb-16 px-4 sm:px-8 md:px-10"), children: [
15396
- formex$1.dirty ? /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Local unsaved changes", className: "self-end sticky top-4 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", colorScheme: "orangeDarker", children: /* @__PURE__ */ jsxRuntime.jsx(ui.EditIcon, { size: "smallest" }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "In sync with the database", className: "self-end sticky top-4 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest" }) }) }),
16470
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row gap-4 self-end sticky top-4 z-10", children: [
16471
+ manualApplyLocalChanges && hasLocalChanges && /* @__PURE__ */ jsxRuntime.jsx(LocalChangesMenu, { cacheKey: status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId, properties: resolvedCollection.properties, localChangesData, formex: formex$1, onClearLocalChanges: () => setLocalChangesCleared(true) }),
16472
+ formex$1.dirty ? /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "There are local unsaved changes", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", className: "py-1", colorScheme: "orangeDarker", children: /* @__PURE__ */ jsxRuntime.jsx(ui.EditIcon, { size: "smallest" }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "The current form is in sync with the database", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", className: "py-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest" }) }) })
16473
+ ] }),
15397
16474
  formView
15398
16475
  ] }) }),
15399
16476
  dialogActions
@@ -16113,7 +17190,7 @@
16113
17190
  }
16114
17191
  let t5;
16115
17192
  if ($[14] !== placeholder) {
16116
- t5 = placeholder && /* @__PURE__ */ jsxRuntime.jsx("div", { onClick: _temp$b, className: "flex flex-col items-center justify-center w-full h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.DescriptionIcon, { className: "text-surface-700 dark:text-surface-300" }) });
17193
+ t5 = placeholder && /* @__PURE__ */ jsxRuntime.jsx("div", { onClick: _temp$c, className: "flex flex-col items-center justify-center w-full h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.DescriptionIcon, { className: "text-surface-700 dark:text-surface-300" }) });
16117
17194
  $[14] = placeholder;
16118
17195
  $[15] = t5;
16119
17196
  } else {
@@ -16136,7 +17213,7 @@
16136
17213
  }
16137
17214
  return t6;
16138
17215
  }
16139
- function _temp$b(e) {
17216
+ function _temp$c(e) {
16140
17217
  return e.stopPropagation();
16141
17218
  }
16142
17219
  const dropZoneClasses = "box-border relative pt-[2px] items-center border border-transparent min-h-[254px] outline-none rounded-md duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid";
@@ -16354,7 +17431,7 @@
16354
17431
  t4 = $[7];
16355
17432
  }
16356
17433
  const style = t4;
16357
- const getImageSizeNumber = _temp$a;
17434
+ const getImageSizeNumber = _temp$b;
16358
17435
  let child;
16359
17436
  if (entry.storagePathOrDownloadUrl) {
16360
17437
  const t52 = `storage_preview_${entry.storagePathOrDownloadUrl}`;
@@ -16429,7 +17506,7 @@
16429
17506
  }
16430
17507
  return t6;
16431
17508
  }
16432
- function _temp$a(previewSize) {
17509
+ function _temp$b(previewSize) {
16433
17510
  switch (previewSize) {
16434
17511
  case "small": {
16435
17512
  return 40;
@@ -17574,6 +18651,13 @@
17574
18651
  } = t0;
17575
18652
  const authController = useAuthController();
17576
18653
  const customizationController = useCustomizationController();
18654
+ if (propertyKey === "created_by") {
18655
+ console.log("Rendering field for created_by", {
18656
+ propertyKey,
18657
+ property,
18658
+ context
18659
+ });
18660
+ }
17577
18661
  let t1;
17578
18662
  if ($[0] !== authController || $[1] !== autoFocus || $[2] !== context || $[3] !== customizationController.propertyConfigs || $[4] !== disabledProp || $[5] !== includeDescription || $[6] !== index || $[7] !== minimalistView || $[8] !== onPropertyChange || $[9] !== partOfArray || $[10] !== property || $[11] !== propertyKey || $[12] !== size || $[13] !== underlyingValueHasChanged) {
17579
18663
  t1 = (fieldProps) => {
@@ -17885,7 +18969,7 @@
17885
18969
  } else {
17886
18970
  t42 = $[20];
17887
18971
  }
17888
- t3 = Object.entries(mapProperties).filter(_temp$9).map(t42);
18972
+ t3 = Object.entries(mapProperties).filter(_temp$a).map(t42);
17889
18973
  $[6] = autoFocus;
17890
18974
  $[7] = context;
17891
18975
  $[8] = disabled;
@@ -17955,7 +19039,7 @@
17955
19039
  }
17956
19040
  return t10;
17957
19041
  }
17958
- function _temp$9(t0) {
19042
+ function _temp$a(t0) {
17959
19043
  const [, property_0] = t0;
17960
19044
  return !isHidden(property_0);
17961
19045
  }
@@ -19025,7 +20109,7 @@
19025
20109
  const property = t4;
19026
20110
  let t5;
19027
20111
  if ($[9] !== properties) {
19028
- t5 = Object.entries(properties).map(_temp$8);
20112
+ t5 = Object.entries(properties).map(_temp$9);
19029
20113
  $[9] = properties;
19030
20114
  $[10] = t5;
19031
20115
  } else {
@@ -19116,7 +20200,7 @@
19116
20200
  }
19117
20201
  return t11;
19118
20202
  }
19119
- function _temp$8(t0) {
20203
+ function _temp$9(t0) {
19120
20204
  const [key, property_0] = t0;
19121
20205
  return {
19122
20206
  id: key,
@@ -20053,6 +21137,11 @@
20053
21137
  console.error("Save failure");
20054
21138
  console.error(e_0);
20055
21139
  setError(e_0);
21140
+ },
21141
+ onPreSaveHookError: (e_1) => {
21142
+ console.error("Pre-save hook error");
21143
+ console.error(e_1);
21144
+ setError(e_1);
20056
21145
  }
20057
21146
  });
20058
21147
  };
@@ -20150,7 +21239,7 @@
20150
21239
  width: width_0,
20151
21240
  frozen
20152
21241
  }) => {
20153
- const isSelected = Boolean(usedSelectionController.selectedEntities.find((e_1) => e_1.id == entity_6.id && e_1.path == entity_6.path));
21242
+ const isSelected = Boolean(usedSelectionController.selectedEntities.find((e_2) => e_2.id == entity_6.id && e_2.path == entity_6.path));
20154
21243
  const customEntityActions_0 = (collection.entityActions ?? []).map((action) => resolveEntityAction(action, customizationController.entityActions)).filter(Boolean);
20155
21244
  const actions_0 = getActionsForEntity({
20156
21245
  entity: entity_6,
@@ -20159,9 +21248,9 @@
20159
21248
  return /* @__PURE__ */ jsxRuntime.jsx(EntityCollectionRowActions, { entity: entity_6, width: width_0, frozen, isSelected, selectionEnabled, size: size_0, highlightEntity: setHighlightedEntity, unhighlightEntity: unselectNavigatedEntity, collection, fullPath, fullIdPath, actions: actions_0, hideId: collection?.hideIdFromCollection, onCollectionChange: updateLastDeleteTimestamp, selectionController: usedSelectionController, openEntityMode });
20160
21249
  }, [updateLastDeleteTimestamp, usedSelectionController]);
20161
21250
  const title = /* @__PURE__ */ jsxRuntime.jsx(ui.Popover, { open: popOverOpen, onOpenChange: setPopOverOpen, enabled: Boolean(collection.description), trigger: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start", children: [
20162
- /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle1", className: `leading-none truncate max-w-[160px] lg:max-w-[240px] ${collection.description ? "cursor-pointer" : "cursor-auto"}`, onClick: collection.description ? (e_2) => {
21251
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle1", className: `leading-none truncate max-w-[160px] lg:max-w-[240px] ${collection.description ? "cursor-pointer" : "cursor-auto"}`, onClick: collection.description ? (e_3) => {
20163
21252
  setPopOverOpen(true);
20164
- e_2.stopPropagation();
21253
+ e_3.stopPropagation();
20165
21254
  } : void 0, children: `${collection.name}` }),
20166
21255
  /* @__PURE__ */ jsxRuntime.jsx(EntitiesCount, { fullPath, collection, filter: tableController.filterValues, sortBy: tableController.sortBy, onCountChange: setDocsCount })
20167
21256
  ] }), children: collection.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "m-4 text-surface-900 dark:text-white", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Markdown, { source: collection.description }) }) });
@@ -20196,7 +21285,7 @@
20196
21285
  /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", children: "So empty..." }),
20197
21286
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { color: "primary", variant: "outlined", onClick: onNewClick, className: "mt-4", children: [
20198
21287
  /* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, {}),
20199
- "Create your first entity"
21288
+ "Create your first entry"
20200
21289
  ] })
20201
21290
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "label", children: "No results with the applied filter/sort" }), hoverRow, inlineEditing: checkInlineEditing(), AdditionalHeaderWidget: buildAdditionalHeaderWidget, AddColumnComponent: addColumnComponentInternal, getIdColumnWidth, additionalIDHeaderWidget: /* @__PURE__ */ jsxRuntime.jsx(EntityIdHeaderWidget, { path: fullPath, fullIdPath: fullIdPath ?? fullPath, collection }), openEntityMode }, `collection_table_${fullPath}`),
20202
21291
  popupCell && /* @__PURE__ */ jsxRuntime.jsx(PopupFormField, { open: Boolean(popupCell), onClose: onPopupClose, cellRect: popupCell?.cellRect, propertyKey: popupCell?.propertyKey, collection, entityId: popupCell.entityId, tableKey: tableKey.current, customFieldValidator: uniqueFieldValidator, path: resolvedFullPath, onCellValueChange: onValueChange, container: containerRef.current }, `popup_form_${popupCell?.propertyKey}_${popupCell?.entityId}`),
@@ -20438,7 +21527,7 @@
20438
21527
  propertyConfig,
20439
21528
  disabled
20440
21529
  } = t0;
20441
- const classes = "h-8 w-8 p-1 rounded-full shadow text-white " + (disabled ? "bg-surface-400 dark:bg-surface-600" : "");
21530
+ const classes = "h-8 w-8 flex items-center justify-center rounded-full shadow text-white " + (disabled ? "bg-surface-400 dark:bg-surface-600" : "");
20442
21531
  let t1;
20443
21532
  if ($[0] !== classes || $[1] !== disabled || $[2] !== propertyConfig) {
20444
21533
  const defaultPropertyConfig = typeof propertyConfig?.property === "object" ? getDefaultFieldConfig(propertyConfig.property) : void 0;
@@ -20453,7 +21542,7 @@
20453
21542
  } else {
20454
21543
  t3 = $[5];
20455
21544
  }
20456
- t1 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes, style: t3, children: propertyConfig?.Icon ? getIconForWidget(propertyConfig, "medium") : getIconForWidget(defaultPropertyConfig, "medium") });
21545
+ t1 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes, style: t3, children: propertyConfig?.Icon ? getIconForWidget(propertyConfig, "small") : getIconForWidget(defaultPropertyConfig, "small") });
20457
21546
  $[0] = classes;
20458
21547
  $[1] = disabled;
20459
21548
  $[2] = propertyConfig;
@@ -20773,7 +21862,7 @@
20773
21862
  }
20774
21863
  let t7;
20775
21864
  if ($[18] !== breadcrumbs.breadcrumbs) {
20776
- t7 = (breadcrumbs.breadcrumbs ?? []).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mr-8 hidden lg:block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row gap-2", children: breadcrumbs.breadcrumbs.map(_temp$7) }) });
21865
+ t7 = (breadcrumbs.breadcrumbs ?? []).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mr-8 hidden lg:block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row gap-2", children: breadcrumbs.breadcrumbs.map(_temp$8) }) });
20777
21866
  $[18] = breadcrumbs.breadcrumbs;
20778
21867
  $[19] = t7;
20779
21868
  } else {
@@ -20885,7 +21974,7 @@
20885
21974
  }
20886
21975
  return t14;
20887
21976
  };
20888
- function _temp$7(breadcrumb, index) {
21977
+ function _temp$8(breadcrumb, index) {
20889
21978
  return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
20890
21979
  /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", children: "/" }),
20891
21980
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { className: "visited:text-inherit visited:dark:text-inherit block", to: breadcrumb.url, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", children: breadcrumb.title }) }, index)
@@ -21319,7 +22408,7 @@
21319
22408
  } else {
21320
22409
  const searchResult = iconsSearch.search(value);
21321
22410
  const limited = searchResult.slice(0, 50);
21322
- setKeys(limited.map(_temp$6));
22411
+ setKeys(limited.map(_temp$7));
21323
22412
  }
21324
22413
  }, UPDATE_SEARCH_INDEX_WAIT_MS);
21325
22414
  $[0] = t3;
@@ -21386,7 +22475,7 @@
21386
22475
  }
21387
22476
  return t8;
21388
22477
  }
21389
- function _temp$6(e) {
22478
+ function _temp$7(e) {
21390
22479
  return e.item.key;
21391
22480
  }
21392
22481
  function FieldCaption(t0) {
@@ -21470,7 +22559,7 @@
21470
22559
  }
21471
22560
  return t2;
21472
22561
  }
21473
- const fireCMSLogo = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAuDSURBVHgB7Z1fTFvXHcd/GDAk2RaHpmmTjMUVaE3bEJyHRO221OYp6VQJ8zaqSpg+beokHKnStIcKo0rrSyXgIdWeipFa8YjR+tA8YbKHTclDvJCp05QoZGuTaVsTp9vCf9j9XueCjX3te+17f+dc+3yki7EhIvbve35/zu+cc5u2NajOWHq4RenbW/R4eZsy97cou5x7Lbu8/fTnxW85sK9Ju4zH3BXsIAoe8lHvcR+FtAuv1RtNXheAYeyFO5uU+XpLv9wCAgjpYmiicFczRbqbPS8KzwkAozi1uKkbHI/GqBYFBBHp9lH/qRZdEF7DEwIwjD59fUMf4aKNbkawo0kXwdBZ74hBagGkb2/S3K0NSl4TP9LtAjEkLvgprHmHYIePZEVKAcDwY1fW9cd6IHauhUYvtEopBKkEkLy2oRl+rWSWXg/IKAQpBFDvht+LTEIQKoB6c/V2kUEIQgSAhA6Gn1hYp0bHSBaHNDGIgF0AqcUNGp5Z81xW7zYoG6cG/ezegE0AMDgMDwEoSoNZRXiDkTCfN2ARAGL88MxqwyR5tcKZG7gugMmrGxSfXSWFPZAbzL/b7roIXBMAXP6l1Jpe4imqZyLa5mpIcEUAcPUDn6y42plrJBIX/XpIcAPHBQDj911eVvHeYeLhVhqP+slpHBWAMr67IDmcGmwjJ3FMAMr4PER7WvT5AqcWojiSYirj84F5FCTXTlGzAJTx+UFlhXkVJ6hJAMr44oAInPAEVQsAdT5KPWV8caCZhqZaLVQtAPxhVeeLJ/FFbf2VqgSgWrlygSYblsdXg+0yEKP+zEfL5FUCLVkKND/Ofa894lpa+4H+fGn1BHkVLE9H78BueWhLAF5K+mDo0L5F7bpJvQdu6t8H/X/TXy9HdiNAmeUeym4epIVvz2vfn6b0f86TF6hmttCWAFB6yNzcgXFjHZ9R/6HPdYNXMrZVIIr0f39Cc4/e1B7PS+0p4AXs7EmwLAAna0+niQY+p5HnLlPku78nDlLZN2n632/rj7KBNvKN9/ZZDgWWBCCj68foHjnyMcW1y6mRbhd4grH7v6bkN2+TTNgJBZYEIJvrx2hPHP1QmOH3IqMQrIaCigLAqH/hgyckA3DxU8GfU7DtHslI5slpGrgzI0WOgFBw9/39FX+v4jwAXL9oMNLHO39F8y++Ia3xQWj/Tbrb8wqNHvsNiQYDd3Khstcu6wFkSPxg8Pkf/lRqw5cCpePw0m+FegMkgnffL58QlvUA2K4lkmjgd3TjpR97zvgA4Uq0cNGvmawwY2sqAIx+kVk/Er3Z7kFpEr1qgPFvvPwjvUwVxcTVjbKbcEwFIHL0I4ZOaDG/HsBU82z3z2jo8KckgkpeoKQARI5+GD8hQRLlNEmtehElgnJeoKQAcBSLCOrV+AYQAddsZT4w/rTJPE6RANDtE7FdGx9MPRvfAOFARGKYulXapkUCmLzK3+fHB4IJnkYAOQGqA6MlzQUGdamBXSQAnMbFjRfr/FrAex0XkOTOlVg5VCAAJH/c+/YR9xvJ+AYxLSGMa6UuJ8nrxaetFQgAR7JxAsM3Qtw3A+LnDAUw/t51nL78H3K7/9muQWpkYHzuvsHeamBHAAvMmX/smU/15kmjE2dcyAL2VgM+sx+4zeixD0mRg9MLwNPnVwM7AuCs/TH6GzHxMwMegNML5FcDugCQGHBO/Y489zEpChlhrAgy93dtvSMALqB0FfuLQceQqyKAtzfKQV0AOHufi6HDn5GiNJzzAsagf+oB+AQQ+Q5/M8QrhBnzgD8VCoAn/sP9q+TPHM7PZ8cDcMZ/5f4rw7V6CDfTAr57D/kEgH16ivJwlYNG1cfmAZDhquy/Mlx5AKoAbCn3cXX/lPGtgYHClQfgfoq+pUdKALLBFSpRCfiyTBt/sDdfYY1gG99n5VtiSgJ7lQewDNdg0XMAYoJ7DZyXOci0GQb5n4+rCaQEYB0uD6AngcSEl7d41TNsN6cJ/LVT+9pJCgs08X1ObALIpvspsLFCCgscDBK9TCywhYBsSzsp5MPn1LnzCm+iCYBYWPIHSGENrs8K5wixhYB77UoAVuH8rHxctyrNNqscwCqZA88TB7C9L3iIJwfIHDhKCmtkm3ni8gmEAK4cIP29ICmskdnP4wFQALCFgKW2gCoFLQD3z/U56UkgvnDBpWwvs8DkKTH6dQ/Qe9z60eK1MvfMSVKUJ9XxEnEQOpbz/LoH4JoMSh4+Qwpz4Pq5cqXQ8ZzNfbknTKUg4xv0IqlDfB4y/PQk8ZwAjvHlASoMmDN9hM9DGsm//tXOLUZqBWFAVQPFoEpKMyaAhtfXv4YZBQDjTx59lRSFjHVGiItI1669dQFAEaxe4FmVDOaD0c/5mUS6d3O+ne8iXWx9If0NKy+wC+foB/ke31fqRQ4S3+9TuQDxj36U/flV364H0ATAuThE5QI5uEd/9FThQC/w+7Gz/F6Aq/UpI8lnQ+z50NC51oLnBQLo72FbI7rDcPcANSJw/WOdfcTJXvcPCp4hDBhThFygQXQp+AY1GnD9EAEn8ddbi14rSv2jp/i9wISWC3DOgokGI19EKdzfUxziiwQwEm4lESuF4ycuNkQ+kOo4qeU+EeImdraFSq39KHoFxudOBgGqgoEXB9ndIicId8NdYnKeoXOlPXvJ2R8RySCA8fteGa5LEeA9DZwcFDL3geTPbKa3pADwy5Fufi8A6lEEGPlnTv9C2HsavWB+J3Gf+T9qJVHUkwgQ8/FeRM16YvTHzpl7dFMBiPQCAMbHqJk+EiKvMnn0NT2vETnlXW70g7I3j8YRcmc+En/38MRXaRr9+zx5BRgcyR5Gv0is3EK+rADApdlV/c6TogmuZmn+z1P6o8ykDwZ148sQvm68t6/icr+KAsA5Mi98sMx+NzEz4g/+SCMP/iCdEGBwzGiKHvUGqPun3mqr+HsVBQAmFtbpUkrsreTzgfETX83T0D8zJJpcV/M1mnj+VWna23D98++2k5VNP5YEAPourwi5pWw5IAR4hP6HX7J7BBkNbzA12FY288/HsgBwmhgSQllCwV5i/8pQ/6MvKfrNX8gtYGi4+GltHl/W5e1Y7zf/S+uCtCwAIFsoKAXOIYp8u0RRTQy9//sHhbSrFtCfwHYt7NjBhI7Mq5jsuH4DWwIAA5+sUmpRfFVgFQgi9EQTwpMHFFzJ0sHNlZLhAobFGQaPtQtb2WF4nNThpWVrdly/gW0BIAQgFHDeZUxRGczcJi76bf8720uB0S2cfaed1OFS8oBavxrjg6rWguMPjker+4MKZ0Hcn32ncr1vRtWbARBrRDaMFDlvbDfp20tNu0HgduKvi1k7oEDS56daT3ipeTvQ+ECb6WoThXsg4486sHDHkf1gSe0/I7J13Ggg9MYcGnSObQhEIqI8gfsg+a424y+F7XmASsRmVmn6mncmirxENRM9lXBcACDxxRqNXVknhTPk5l7cCbOu+GzDRSkR1E6uzm937RwnVzyAAXoGwzNr0nYQZQdGx8h38zBPVwUA0DPou6x6B3YZ0eZXJgaqn+GziusCMJBlbaHsIN5jgifKtDmHTQAgqVUHY1fWlDcwAYs5pt7yE9f5zYBVAADGH9OqhOR15Q0MMOoxuRMP8/dW2AVggAQRq4sa3Rtg9e74gF9Ye12YAAwaNSzA3Y9ebBU+hS5cAADGT15bp2ktLNS7EGQxvIEUAjCoZyHIZngDqQSQT72EBlkNbyCtAAywGQXNpdStTc/MKOJGXOiMxgUdt2MH6QWQDyqHucVNKcUAo0d7mvXTVby0NsJTAsgHnmFOE0Tm621K3+HfsqYfsK2593C3Tzc85+SNk3hWAPnAG+AsA1wLt7e0vEG7Hm075iUwumFgnKGIeyzhtG2vGnwvdSEAMwxh4BHJ5OOngjBLLI07qJ3QjIv7KaIbZ9xdq175P/vCeAzHXKL0AAAAAElFTkSuQmCC";
22562
+ const fireCMSLogo = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAa9SURBVHgB7Z1NbBNHFMf/a7uBEgMOHy2pSlnUql+oEG7lgNgcqZAgR9RKSU5tT9mcqp6SXNoj5tBzHAmk3ggSUo/Ziko9skXqoVIlJm3Von4IhzhAIIk7b9ab+COJvZ63610nP8netWx5Z//73syb2Zm3BjqJXc4BixaQMgHjDFCWW5iVb83aH5eL8jdC7lS2a/Ny3wGyLvJGER3CQJRsCHZBfrqCBpHaRkCJuXYb2O9EKWg0AtpKtDF5gnJr5BA+BSVm/sAsQiY8AZW1PSHR7IhE2wwhX1NAWlrlywIhwC9gPISrR8iyFJDvnQIzvALapRH5PgG+uo0bAbLIfLYAJngEtJ+awOq03LOQCAxZN6bGOdw6BV3GyV1X7iEx4hFlGQGs3qt4jBbtW6Cq65bIXW0km7x06XG0SXsCei57S+4NoDtwZUs91I5LBxfQE28O8W0o2kVIEQeDihhMwO4Vz0cEFbF1AbtfPB8RRMTWBNw54vmIVkVsMYxRDYaJnYOpztl+1LQn1VxAu3QN3dPaBkGe80sTzX60vQt7geY0IsDcMw8r+wPO9N6H2TOPXHpBbn9DcfWgehHu09OYf/YGnNJ5uE9OIyJkjyWb3+rLrQVU9R71MMIbELD238XlvjsYOXQTuUywIbziSg6zC5cw8+/HcBbPI0RkwdJnt6oPtxFw6ZbX5eFn5PANDB+5qQTkQCyfwNSfX6Lw3ycICTkclh3c7IvNBQzJdUmwide+YhOunpCFHN1sFGcrAR+AsdUl95zo/xr2q98gCkhAEpIEZUQAL6Qr99XUNY2tsL3EOp5HjcPc2x9FJh5BVQQdk47NiAlkGgZOai2QOWD2xWM+kZah1nvwl+84W2xpfS9OVlthnQWuWugS8QgKhebeuYiBfffBRK7eCutduGng2ApxEM+HX0RjrPrThoD2Y7b7tHERz4dEvPXmVbXl+DvvNq1HlQWmLoMBClPiJJ4PlWn65KfgIbVuhV4jojrNLz2CJlTIBx+cQpwZ+vVbzBYvQZP1xqRigWkLDEybnyHuXDv+BYcrS4PrsWinIqC++17J3Qmth8EJeQlPTErTVDbqQAuajEUYKOsyfPgm9DGU0Rkc9V8S6r56KMDWH8V50SctMKM9WErumzSGj9yAPj0WubAFTXhcIlp4LnrZTFVmhbYNtWiMXaXI4Cm3cUYKmNIa80mieD76UYOyQGgN2SdZQLrnovsXJKAJDRgK0TE4upzaFpjLsHTQO8JB/R6JmYEuyz3A4gEkkuW90EVfwLvyZtXffUgkB03gfWihP0N1h0MCCmhQTOu7QadY0C97UdsCxd64rGQIjtijXXahbYHuvn4kFbf3GDQhC1zTCobcfdqF6Bhur+7FN8gCUy40KGb2wjlgImmQ++pf/LV5skABTb6ncCBhMF10Rwq46kCT/LFzSBozr5yFPituqjJNQUCDpLkxuS9DeUXVXbnybWgydXwQSWHquAUGHHrzBXSgCV3RJFghWV/hKIf7GsroKgKqelB7mfzoW0OIO0zWJ3nu0LsnoKoH9a2Qru64eRFxpXB0gMn6UPCnuFV35a6DgXz/h7F0Zd6La6y3GXUTLEt0f1i7g2guFzH387TaxgESb/DUKEffV/0d8tmT/oe6wYQyixUyF1gLCrGG3r3KWZaavAt1Aq7QghIWs4mDiCQelYGxvy5UBpAqagX0GhMWK1RHq4jIMOrR1rHPnv6cebCjPFO/4KZxmYM3V4ZyIJhgZPIPBxO/zyEKrvefw+TrlrJARmrqPp9IF9qE3biQ1VEsGlIUEGChDWGXyFwshMDIPy7G/voRA0sPwQFVEddl+MQU422CMYt876a9hCaLDVfJlUNrBQaePIQthbywIAJbJbnnjAyMZw+9F3LcSVnjMm0sNiTsEq2JuIYIIDHNZ0VYjx/gxPMicivPar4nweZ7cmoUmSwuwpHw0e0yHTVf8m8v5uvXRuwcZESS379tXpwW7sqtTELlVdlxuM3EI5oLqGLDNFWgAjsHUTnnpuymPWlE8Kc98dlNvNNAMAGJ3dRPNQSf2qEOkKYbIN3UsLjtiEcEt8BquiLEocGT7GS7mX/1BCS8fjMF2wmbZaTyUk9tlxOmFfQFJLwcM1JE4wqSgSNddpQjBSiPgD67SWiZsBcn5V8PIzZCkrvSTTPprsxZzsMRkPDCHQsdtcjwhPMJT8BqvHwM8pUaRuiQaCkHWKOBAAchE42APusPI1Bi0gMJTPAgvPk9NDmgGx9GsBVK0NIA1Mg3rdlTCx9z3rYha5zY2NLjMMo/eXMboxWsnv8Br15XnnLWoGsAAAAASUVORK5CYII=";
21474
22563
  function useBrowserTitleAndIcon(name, logo) {
21475
22564
  const $ = reactCompilerRuntime.c(4);
21476
22565
  let t0;
@@ -21575,22 +22664,9 @@
21575
22664
  const buildUrlCollectionPath = React.useCallback((path_0) => `${removeInitialAndTrailingSlashes(baseCollectionPath)}/${encodePath(path_0)}`, [baseCollectionPath]);
21576
22665
  const allPluginGroups = plugins?.flatMap((plugin) => plugin.homePage?.navigationEntries ? plugin.homePage.navigationEntries.map((e) => e.name) : []) ?? [];
21577
22666
  const pluginGroups = [...new Set(allPluginGroups)];
21578
- const onNavigationEntriesOrderUpdate = React.useCallback((entries) => {
21579
- if (!plugins) {
21580
- return;
21581
- }
21582
- const filteredEntries = entries.filter((entry) => entry.entries.length > 0);
21583
- if (plugins.some((plugin_1) => plugin_1.homePage?.onNavigationEntriesUpdate)) {
21584
- plugins.forEach((plugin_0) => {
21585
- if (plugin_0.homePage?.onNavigationEntriesUpdate) {
21586
- plugin_0.homePage.onNavigationEntriesUpdate(filteredEntries);
21587
- }
21588
- });
21589
- }
21590
- }, [plugins]);
21591
- const computeTopNavigation = React.useCallback((collections, views, adminViews, viewsOrder_0) => {
22667
+ const computeTopNavigation = React.useCallback((collections, views, adminViews, viewsOrder_0, navigationGroupMappingsOverride, onNavigationEntriesUpdateCallback) => {
21592
22668
  const finalNavigationGroupMappings = computeNavigationGroups({
21593
- navigationGroupMappings,
22669
+ navigationGroupMappings: navigationGroupMappingsOverride ?? navigationGroupMappings,
21594
22670
  collections,
21595
22671
  views,
21596
22672
  plugins
@@ -21622,7 +22698,7 @@
21622
22698
  return acc;
21623
22699
  }, []), ...(views ?? []).reduce((acc_0, view) => {
21624
22700
  if (view.hideFromNavigation) return acc_0;
21625
- const pathKey_0 = Array.isArray(view.path) ? view.path[0] : view.path;
22701
+ const pathKey_0 = view.path;
21626
22702
  let groupName_0 = getGroup(view);
21627
22703
  if (finalNavigationGroupMappings) {
21628
22704
  for (const pluginGroupDef_0 of finalNavigationGroupMappings) {
@@ -21645,7 +22721,7 @@
21645
22721
  return acc_0;
21646
22722
  }, []), ...(adminViews ?? []).reduce((acc_1, view_0) => {
21647
22723
  if (view_0.hideFromNavigation) return acc_1;
21648
- const pathKey_1 = Array.isArray(view_0.path) ? view_0.path[0] : view_0.path;
22724
+ const pathKey_1 = view_0.path;
21649
22725
  const groupName_1 = NAVIGATION_ADMIN_GROUP_NAME;
21650
22726
  acc_1.push({
21651
22727
  id: `admin:${pathKey_1}`,
@@ -21679,21 +22755,43 @@
21679
22755
  });
21680
22756
  }
21681
22757
  const collectedGroupsFromEntries = navigationEntries.map((e_0) => e_0.group).filter(Boolean);
21682
- const allDefinedGroups = [...pluginGroups ?? [], ...collectedGroupsFromEntries];
21683
- const uniqueGroups = [...new Set(allDefinedGroups)].sort((a_1, b_1) => groupOrderValue(a_1) - groupOrderValue(b_1));
22758
+ const groupsFromMappings = finalNavigationGroupMappings.map((g_0) => g_0.name);
22759
+ const additionalGroups = collectedGroupsFromEntries.filter((g_1) => !groupsFromMappings.includes(g_1));
22760
+ const allDefinedGroups = [...pluginGroups ?? [], ...groupsFromMappings, ...additionalGroups];
22761
+ const uniqueGroupsArray = [...new Set(allDefinedGroups)];
22762
+ const adminGroups = uniqueGroupsArray.filter((g_2) => g_2 === NAVIGATION_ADMIN_GROUP_NAME);
22763
+ const nonAdminGroups = uniqueGroupsArray.filter((g_3) => g_3 !== NAVIGATION_ADMIN_GROUP_NAME);
22764
+ const uniqueGroups = [...nonAdminGroups, ...adminGroups];
21684
22765
  return {
21685
- allowDragAndDrop: plugins?.some((plugin_2) => plugin_2.homePage?.allowDragAndDrop) ?? false,
22766
+ allowDragAndDrop: plugins?.some((plugin_0) => plugin_0.homePage?.allowDragAndDrop) ?? false,
21686
22767
  navigationEntries,
21687
22768
  groups: uniqueGroups,
21688
- onNavigationEntriesUpdate: onNavigationEntriesOrderUpdate
22769
+ onNavigationEntriesUpdate: onNavigationEntriesUpdateCallback
21689
22770
  };
21690
- }, [navigationGroupMappings, buildCMSUrlPath, buildUrlCollectionPath, pluginGroups, onNavigationEntriesOrderUpdate]);
22771
+ }, [navigationGroupMappings, buildCMSUrlPath, buildUrlCollectionPath, pluginGroups]);
22772
+ const onNavigationEntriesOrderUpdate = React.useCallback((entries) => {
22773
+ if (!plugins) {
22774
+ return;
22775
+ }
22776
+ const filteredEntries = entries.filter((entry) => entry.entries.length > 0);
22777
+ if (collectionsRef.current && viewsRef.current) {
22778
+ const updatedNav = computeTopNavigation(collectionsRef.current, viewsRef.current, adminViewsRef.current ?? [], viewsOrder, filteredEntries, onNavigationEntriesOrderUpdate);
22779
+ setTopLevelNavigation(updatedNav);
22780
+ }
22781
+ if (plugins.some((plugin_2) => plugin_2.homePage?.onNavigationEntriesUpdate)) {
22782
+ plugins.forEach((plugin_1) => {
22783
+ if (plugin_1.homePage?.onNavigationEntriesUpdate) {
22784
+ plugin_1.homePage.onNavigationEntriesUpdate(filteredEntries);
22785
+ }
22786
+ });
22787
+ }
22788
+ }, [plugins, computeTopNavigation, viewsOrder]);
21691
22789
  const refreshNavigation = React.useCallback(async () => {
21692
22790
  if (disabled || authController.initialLoading) return;
21693
22791
  console.debug("Refreshing navigation");
21694
22792
  try {
21695
22793
  const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, plugins), resolveCMSViews(viewsProp, authController, dataSourceDelegate), resolveCMSViews(adminViewsProp, authController, dataSourceDelegate)]);
21696
- const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
22794
+ const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder, void 0, onNavigationEntriesOrderUpdate);
21697
22795
  let shouldUpdateTopLevelNav = false;
21698
22796
  if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
21699
22797
  collectionsRef.current = resolvedCollections;
@@ -21789,7 +22887,8 @@
21789
22887
  }, []);
21790
22888
  const isUrlCollectionPath = React.useCallback((path_1) => removeInitialAndTrailingSlashes(path_1 + "/").startsWith(removeInitialAndTrailingSlashes(fullCollectionPath) + "/"), [fullCollectionPath]);
21791
22889
  const urlPathToDataPath = React.useCallback((path_2) => {
21792
- if (path_2.startsWith(fullCollectionPath)) return path_2.replace(fullCollectionPath, "");
22890
+ const decodedPath = decodeURIComponent(path_2);
22891
+ if (decodedPath.startsWith(fullCollectionPath)) return decodedPath.replace(fullCollectionPath, "");
21793
22892
  throw Error("Expected path starting with " + fullCollectionPath);
21794
22893
  }, [fullCollectionPath]);
21795
22894
  const resolveIdsFrom = React.useCallback((path_3) => {
@@ -21977,6 +23076,42 @@
21977
23076
  }
21978
23077
  return acc;
21979
23078
  }, [...result ?? []]) : result;
23079
+ const assignedEntries = /* @__PURE__ */ new Set();
23080
+ if (result) {
23081
+ result.forEach((group) => {
23082
+ group.entries.forEach((entry) => assignedEntries.add(entry));
23083
+ });
23084
+ }
23085
+ const unassignedGroupMap = {};
23086
+ (collections ?? []).forEach((collection) => {
23087
+ const entry = collection.id ?? collection.path;
23088
+ if (!assignedEntries.has(entry)) {
23089
+ const groupName = getGroup(collection);
23090
+ if (!unassignedGroupMap[groupName]) unassignedGroupMap[groupName] = [];
23091
+ unassignedGroupMap[groupName].push(entry);
23092
+ }
23093
+ });
23094
+ (views ?? []).forEach((view) => {
23095
+ const entry = view.path;
23096
+ if (!assignedEntries.has(entry)) {
23097
+ const groupName = getGroup(view);
23098
+ if (!unassignedGroupMap[groupName]) unassignedGroupMap[groupName] = [];
23099
+ unassignedGroupMap[groupName].push(entry);
23100
+ }
23101
+ });
23102
+ Object.entries(unassignedGroupMap).forEach(([groupName, entries]) => {
23103
+ if (result) {
23104
+ const existingGroup = result.find((g) => g.name === groupName);
23105
+ if (existingGroup) {
23106
+ existingGroup.entries.push(...entries);
23107
+ } else {
23108
+ result.push({
23109
+ name: groupName,
23110
+ entries
23111
+ });
23112
+ }
23113
+ }
23114
+ });
21980
23115
  if (!result) {
21981
23116
  result = [];
21982
23117
  const groupMap = {};
@@ -21988,7 +23123,7 @@
21988
23123
  });
21989
23124
  (views ?? []).forEach((view) => {
21990
23125
  const name = getGroup(view);
21991
- const entry = Array.isArray(view.path) ? view.path[0] : view.path;
23126
+ const entry = view.path;
21992
23127
  if (!groupMap[name]) groupMap[name] = [];
21993
23128
  groupMap[name].push(entry);
21994
23129
  });
@@ -22012,7 +23147,7 @@
22012
23147
  t0 = $[0];
22013
23148
  }
22014
23149
  const configCache = React.useRef(t0);
22015
- const getCollectionFromStorage = _temp$5;
23150
+ const getCollectionFromStorage = _temp$6;
22016
23151
  let t1;
22017
23152
  if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
22018
23153
  t1 = (path) => {
@@ -22135,7 +23270,7 @@
22135
23270
  }
22136
23271
  return t11;
22137
23272
  }
22138
- function _temp$5(storageKey) {
23273
+ function _temp$6(storageKey) {
22139
23274
  const item = localStorage.getItem(storageKey);
22140
23275
  return item ? JSON.parse(item) : {};
22141
23276
  }
@@ -22595,14 +23730,14 @@
22595
23730
  collection,
22596
23731
  context,
22597
23732
  sideEntityController,
22598
- isSubmitting: formex2.isSubmitting,
22599
23733
  disabled,
22600
23734
  status,
22601
23735
  sideDialogContext,
22602
23736
  pluginActions,
22603
23737
  openEntityMode,
22604
23738
  navigateBack,
22605
- formContext
23739
+ formContext,
23740
+ formex: formex2
22606
23741
  }) : buildSideActions({
22607
23742
  savingError,
22608
23743
  entity,
@@ -22610,14 +23745,14 @@
22610
23745
  collection,
22611
23746
  context,
22612
23747
  sideEntityController,
22613
- isSubmitting: formex2.isSubmitting,
22614
23748
  sideDialogContext,
22615
23749
  disabled,
22616
23750
  status,
22617
23751
  pluginActions,
22618
23752
  openEntityMode,
22619
23753
  navigateBack,
22620
- formContext
23754
+ formContext,
23755
+ formex: formex2
22621
23756
  });
22622
23757
  }
22623
23758
  function buildBottomActions({
@@ -22627,15 +23762,16 @@
22627
23762
  collection,
22628
23763
  context,
22629
23764
  sideEntityController,
22630
- isSubmitting,
22631
23765
  disabled,
22632
23766
  status,
22633
23767
  sideDialogContext,
22634
23768
  pluginActions,
22635
23769
  openEntityMode,
22636
23770
  navigateBack,
22637
- formContext
23771
+ formContext,
23772
+ formex: formex2
22638
23773
  }) {
23774
+ const hasErrors = Object.keys(formex2.errors).length > 0 && formex2.submitCount > 0;
22639
23775
  const canClose = openEntityMode === "side_panel";
22640
23776
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { position: "absolute", children: [
22641
23777
  savingError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { color: "error", children: savingError.message }) }),
@@ -22655,15 +23791,16 @@
22655
23791
  return /* @__PURE__ */ jsxRuntime.jsx(EntityActionButton, { action, enabled: isEnabled, props }, action.key);
22656
23792
  }) }),
22657
23793
  pluginActions,
22658
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", color: "primary", disabled: disabled || isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
22659
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: canClose ? "text" : "filled", color: "primary", type: "submit", disabled: disabled || isSubmitting, onClick: () => {
23794
+ hasErrors ? /* @__PURE__ */ jsxRuntime.jsx(ErrorTooltip, { title: "This form has errors", children: /* @__PURE__ */ jsxRuntime.jsx(ui.ErrorIcon, { className: "ml-4", color: "error", size: "smallest" }) }) : null,
23795
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", color: "primary", disabled: disabled || formex2.isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
23796
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: canClose ? "text" : "filled", color: "primary", type: "submit", disabled: disabled || formex2.isSubmitting, onClick: () => {
22660
23797
  sideDialogContext.setPendingClose(false);
22661
23798
  }, children: [
22662
23799
  status === "existing" && "Save",
22663
23800
  status === "copy" && "Create copy",
22664
23801
  status === "new" && "Create"
22665
23802
  ] }),
22666
- canClose && /* @__PURE__ */ jsxRuntime.jsxs(ui.LoadingButton, { variant: "filled", color: "primary", type: "submit", loading: isSubmitting, disabled, onClick: () => {
23803
+ canClose && /* @__PURE__ */ jsxRuntime.jsxs(ui.LoadingButton, { variant: "filled", color: "primary", type: "submit", loading: formex2.isSubmitting, disabled, onClick: () => {
22667
23804
  sideDialogContext.setPendingClose?.(true);
22668
23805
  }, children: [
22669
23806
  status === "existing" && "Save and close",
@@ -22679,24 +23816,25 @@
22679
23816
  collection,
22680
23817
  context,
22681
23818
  sideEntityController,
22682
- isSubmitting,
22683
23819
  disabled,
22684
23820
  status,
22685
23821
  sideDialogContext,
22686
23822
  pluginActions,
22687
23823
  openEntityMode,
22688
23824
  navigateBack,
22689
- formContext
23825
+ formContext,
23826
+ formex: formex2
22690
23827
  }) {
23828
+ const hasErrors = Object.keys(formex2.errors).length > 0 && formex2.submitCount > 0;
22691
23829
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", ui.defaultBorderMixin), children: [
22692
- /* @__PURE__ */ jsxRuntime.jsxs(ui.LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", disabled: disabled || isSubmitting, onClick: () => {
23830
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", startIcon: hasErrors ? /* @__PURE__ */ jsxRuntime.jsx(ui.ErrorIcon, {}) : void 0, disabled: disabled || formex2.isSubmitting, onClick: () => {
22693
23831
  sideDialogContext.setPendingClose?.(false);
22694
23832
  }, children: [
22695
23833
  status === "existing" && "Save",
22696
23834
  status === "copy" && "Create copy",
22697
23835
  status === "new" && "Create"
22698
23836
  ] }),
22699
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { fullWidth: true, variant: "text", disabled: disabled || isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
23837
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { fullWidth: true, variant: "text", disabled: disabled || formex2.isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
22700
23838
  pluginActions,
22701
23839
  formActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row flex-wrap mt-2", children: formActions.map((action) => {
22702
23840
  const props = {
@@ -22851,6 +23989,7 @@
22851
23989
  function createFormexStub(values) {
22852
23990
  const errorMessage = "You are in a read-only context. You cannot modify the formex controller.";
22853
23991
  return {
23992
+ debugId: "",
22854
23993
  values,
22855
23994
  initialValues: values,
22856
23995
  touched: {},
@@ -22865,6 +24004,9 @@
22865
24004
  setValues: () => {
22866
24005
  throw new Error(errorMessage);
22867
24006
  },
24007
+ setTouched(touched) {
24008
+ throw new Error(errorMessage);
24009
+ },
22868
24010
  setFieldValue: () => {
22869
24011
  throw new Error(errorMessage);
22870
24012
  },
@@ -22924,7 +24066,7 @@
22924
24066
  databaseId: props.databaseId,
22925
24067
  useCache: false
22926
24068
  });
22927
- const cachedValues = entityId ? getEntityFromCache(props.path + "/" + entityId) : getEntityFromCache(props.path + "#new");
24069
+ const initialDirtyValues = entityId ? getEntityFromMemoryCache(props.path + "/" + entityId) : getEntityFromMemoryCache(props.path + "#new");
22928
24070
  const authController = useAuthController();
22929
24071
  const initialStatus = props.copy ? "copy" : entityId ? "existing" : "new";
22930
24072
  const [status, setStatus] = React.useState(initialStatus);
@@ -22935,13 +24077,13 @@
22935
24077
  return entity ? canEditEntity(props.collection, authController, props.path, entity ?? null) : void 0;
22936
24078
  }
22937
24079
  }, [authController, entity, status]);
22938
- if (dataLoading && !cachedValues || (!entity || canEdit === void 0) && (status === "existing" || status === "copy")) {
24080
+ if (dataLoading && !initialDirtyValues || (!entity || canEdit === void 0) && (status === "existing" || status === "copy")) {
22939
24081
  return /* @__PURE__ */ jsxRuntime.jsx(CircularProgressCenter, {});
22940
24082
  }
22941
- if (entityId && !entity && !cachedValues) {
24083
+ if (entityId && !entity && !initialDirtyValues) {
22942
24084
  console.error(`Entity with id ${entityId} not found in collection ${props.path}`);
22943
24085
  }
22944
- return /* @__PURE__ */ jsxRuntime.jsx(EntityEditViewInner, { ...props, entityId, entity, cachedDirtyValues: cachedValues, dataLoading, status, setStatus, canEdit });
24086
+ return /* @__PURE__ */ jsxRuntime.jsx(EntityEditViewInner, { ...props, entityId, entity, initialDirtyValues, dataLoading, status, setStatus, canEdit });
22945
24087
  }
22946
24088
  function EntityEditViewInner({
22947
24089
  path,
@@ -22954,7 +24096,7 @@
22954
24096
  onSaved,
22955
24097
  onTabChange,
22956
24098
  entity,
22957
- cachedDirtyValues,
24099
+ initialDirtyValues,
22958
24100
  dataLoading,
22959
24101
  layout = "side_panel",
22960
24102
  barActions,
@@ -23082,7 +24224,8 @@
23082
24224
  /* @__PURE__ */ jsxRuntime.jsx(EntityView, { className: "px-8 h-full overflow-auto", entity, path, collection }),
23083
24225
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-16" })
23084
24226
  ] }) }) : null;
23085
- const entityView = /* @__PURE__ */ jsxRuntime.jsx(EntityForm, { fullIdPath, collection, path, entityId: entityId ?? usedEntity?.id, onValuesModified, entity, initialDirtyValues: cachedDirtyValues, openEntityMode: layout, forceActionsAtTheBottom: actionsAtTheBottom, initialStatus: status, className: ui.cls((!mainViewVisible || !canEdit) && !selectedSecondaryForm ? "hidden" : "", formProps?.className), EntityFormActionsComponent: EntityEditViewFormActions, disabled: !canEdit, ...formProps, onEntityChange: (entity_0) => {
24227
+ const entityView = /* @__PURE__ */ jsxRuntime.jsx(EntityForm, { fullIdPath, collection, path, entityId: entityId ?? usedEntity?.id, onValuesModified, entity, initialDirtyValues, openEntityMode: layout, forceActionsAtTheBottom: actionsAtTheBottom, initialStatus: status, className: ui.cls((!mainViewVisible || !canEdit) && !selectedSecondaryForm ? "hidden" : "", formProps?.className), EntityFormActionsComponent: EntityEditViewFormActions, disabled: !canEdit, ...formProps, onEntityChange: (entity_0) => {
24228
+ console.log("333 EntityEditView onEntityChange:", entity_0);
23086
24229
  setUsedEntity(entity_0);
23087
24230
  formProps?.onEntityChange?.(entity_0);
23088
24231
  }, onStatusChange: (status_0) => {
@@ -23105,7 +24248,12 @@
23105
24248
  const shouldShowTopBar = Boolean(barActions) || hasAdditionalViews;
23106
24249
  let result = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col h-full w-full bg-white dark:bg-surface-900", children: [
23107
24250
  shouldShowTopBar && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("h-14 items-center flex overflow-visible overflow-x-scroll w-full no-scrollbar h-14 border-b pl-2 pr-2 pt-1 flex bg-surface-50 dark:bg-surface-900", ui.defaultBorderMixin), children: [
23108
- barActions,
24251
+ barActions?.({
24252
+ path: fullIdPath ?? path,
24253
+ entityId,
24254
+ values: formContext?.values ?? usedEntity?.values ?? {},
24255
+ status
24256
+ }),
23109
24257
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow" }),
23110
24258
  pluginActionsTop,
23111
24259
  globalLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "self-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CircularProgress, { size: "small" }) }),
@@ -23208,9 +24356,14 @@
23208
24356
  if (!props || !collection) {
23209
24357
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full" });
23210
24358
  }
23211
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(EntityEditView, { ...props, fullIdPath, layout: "side_panel", collection, parentCollectionIds, onValuesModified, onSaved: onUpdate, barActions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
24359
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(EntityEditView, { ...props, fullIdPath, layout: "side_panel", collection, parentCollectionIds, onValuesModified, onSaved: onUpdate, barActions: ({
24360
+ status,
24361
+ values
24362
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
23212
24363
  /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "self-center", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, { size: "small" }) }),
23213
24364
  allowFullScreen && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "self-center", onClick: () => {
24365
+ const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
24366
+ saveEntityToMemoryCache(key, values);
23214
24367
  if (entityId) navigate(location.pathname);
23215
24368
  else navigate(location.pathname + "#new");
23216
24369
  }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.OpenInFullIcon, { size: "small" }) })
@@ -23470,7 +24623,7 @@
23470
24623
  t3 = () => {
23471
24624
  const state = location.state;
23472
24625
  const panelKeys = state?.panels ?? [];
23473
- const newPanels_0 = panelKeys.map((key) => routesStore.current[key]).filter(_temp$4);
24626
+ const newPanels_0 = panelKeys.map((key) => routesStore.current[key]).filter(_temp$5);
23474
24627
  if (!equal(sidePanelsRef.current.map(_temp2$3), newPanels_0.map(_temp3$1))) {
23475
24628
  updateSidePanels(newPanels_0);
23476
24629
  }
@@ -23618,7 +24771,7 @@
23618
24771
  function _temp2$3(p_0) {
23619
24772
  return p_0.key;
23620
24773
  }
23621
- function _temp$4(p) {
24774
+ function _temp$5(p) {
23622
24775
  return Boolean(p);
23623
24776
  }
23624
24777
  function useBuildDataSource({
@@ -23913,7 +25066,7 @@
23913
25066
  const dataSourceKey = dataSourceDelegate.key;
23914
25067
  let t1;
23915
25068
  if ($[0] !== plugins) {
23916
- t1 = plugins?.map(_temp$3);
25069
+ t1 = plugins?.map(_temp$4);
23917
25070
  $[0] = plugins;
23918
25071
  $[1] = t1;
23919
25072
  } else {
@@ -23949,7 +25102,7 @@
23949
25102
  React.useEffect(t2, t3);
23950
25103
  return accessResponse;
23951
25104
  }
23952
- function _temp$3(plugin) {
25105
+ function _temp$4(plugin) {
23953
25106
  return plugin.key;
23954
25107
  }
23955
25108
  function FireCMS(props) {
@@ -23962,22 +25115,27 @@
23962
25115
  authController,
23963
25116
  storageSource,
23964
25117
  dataSourceDelegate,
23965
- plugins: pluginsProp,
25118
+ plugins: _pluginsProp,
23966
25119
  onAnalyticsEvent,
23967
25120
  propertyConfigs,
23968
25121
  entityViews,
23969
25122
  entityActions,
23970
25123
  components,
23971
25124
  navigationController,
23972
- apiKey
25125
+ apiKey,
25126
+ userManagement: _userManagement
23973
25127
  } = props;
23974
- if (pluginsProp) {
25128
+ if (_pluginsProp) {
23975
25129
  console.warn("The `plugins` prop is deprecated in the FireCMS component. You should pass your plugins to `useBuildNavigationController` instead.");
23976
25130
  }
23977
- const plugins = navigationController.plugins ?? pluginsProp;
25131
+ const plugins = navigationController.plugins ?? _pluginsProp;
25132
+ const userManagement = plugins?.find((p) => p.userManagement)?.userManagement ?? _userManagement ?? {
25133
+ users: [],
25134
+ getUser: (uid) => null
25135
+ };
23978
25136
  const sideDialogsController = useBuildSideDialogsController();
23979
25137
  const sideEntityController = useBuildSideEntityController(navigationController, sideDialogsController, authController);
23980
- const pluginsLoading = plugins?.some((p) => p.loading) ?? false;
25138
+ const pluginsLoading = plugins?.some((p_0) => p_0.loading) ?? false;
23981
25139
  const loading = authController.initialLoading || navigationController.loading || pluginsLoading;
23982
25140
  const customizationController = {
23983
25141
  dateTimeFormat,
@@ -24024,7 +25182,7 @@
24024
25182
  accessResponse?.message && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { children: accessResponse?.message })
24025
25183
  ] });
24026
25184
  }
24027
- return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsContext.Provider, { value: analyticsController, children: /* @__PURE__ */ jsxRuntime.jsx(CustomizationControllerContext.Provider, { value: customizationController, children: /* @__PURE__ */ jsxRuntime.jsx(UserConfigurationPersistenceContext.Provider, { value: userConfigPersistence, children: /* @__PURE__ */ jsxRuntime.jsx(StorageSourceContext.Provider, { value: storageSource, children: /* @__PURE__ */ jsxRuntime.jsx(DataSourceContext.Provider, { value: dataSource, children: /* @__PURE__ */ jsxRuntime.jsx(AuthControllerContext.Provider, { value: authController, children: /* @__PURE__ */ jsxRuntime.jsx(SideDialogsControllerContext.Provider, { value: sideDialogsController, children: /* @__PURE__ */ jsxRuntime.jsx(SideEntityControllerContext.Provider, { value: sideEntityController, children: /* @__PURE__ */ jsxRuntime.jsx(NavigationContext.Provider, { value: navigationController, children: /* @__PURE__ */ jsxRuntime.jsx(DialogsProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbsProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(FireCMSInternal, { loading, children }) }) }) }) }) }) }) }) }) }) }) });
25185
+ return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsContext.Provider, { value: analyticsController, children: /* @__PURE__ */ jsxRuntime.jsx(CustomizationControllerContext.Provider, { value: customizationController, children: /* @__PURE__ */ jsxRuntime.jsx(UserConfigurationPersistenceContext.Provider, { value: userConfigPersistence, children: /* @__PURE__ */ jsxRuntime.jsx(StorageSourceContext.Provider, { value: storageSource, children: /* @__PURE__ */ jsxRuntime.jsx(DataSourceContext.Provider, { value: dataSource, children: /* @__PURE__ */ jsxRuntime.jsx(AuthControllerContext.Provider, { value: authController, children: /* @__PURE__ */ jsxRuntime.jsx(SideDialogsControllerContext.Provider, { value: sideDialogsController, children: /* @__PURE__ */ jsxRuntime.jsx(SideEntityControllerContext.Provider, { value: sideEntityController, children: /* @__PURE__ */ jsxRuntime.jsx(NavigationContext.Provider, { value: navigationController, children: /* @__PURE__ */ jsxRuntime.jsx(InternalUserManagementContext.Provider, { value: userManagement, children: /* @__PURE__ */ jsxRuntime.jsx(DialogsProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbsProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(FireCMSInternal, { loading, children }) }) }) }) }) }) }) }) }) }) }) }) });
24028
25186
  }
24029
25187
  function FireCMSInternal(t0) {
24030
25188
  const $ = reactCompilerRuntime.c(7);
@@ -24194,7 +25352,7 @@
24194
25352
  } = navigation.topLevelNavigation;
24195
25353
  let t1;
24196
25354
  if ($[0] !== adminMenuOpen || $[1] !== analyticsController || $[2] !== className || $[3] !== closeDrawer || $[4] !== drawerOpen || $[5] !== groups || $[6] !== largeLayout || $[7] !== logo || $[8] !== navigate || $[9] !== navigationEntries || $[10] !== style || $[11] !== tooltipsOpen) {
24197
- const adminViews = navigationEntries.filter(_temp$2) ?? [];
25355
+ const adminViews = navigationEntries.filter(_temp$3) ?? [];
24198
25356
  let t2;
24199
25357
  let t3;
24200
25358
  let t4;
@@ -24347,7 +25505,7 @@
24347
25505
  function _temp2$2(g) {
24348
25506
  return g !== "Admin";
24349
25507
  }
24350
- function _temp$2(e) {
25508
+ function _temp$3(e) {
24351
25509
  return e.type === "admin";
24352
25510
  }
24353
25511
  function DrawerLogo(t0) {
@@ -24407,6 +25565,165 @@
24407
25565
  }
24408
25566
  return t6;
24409
25567
  }
25568
+ function UserSelectFieldBinding(t0) {
25569
+ const $ = reactCompilerRuntime.c(43);
25570
+ const {
25571
+ propertyKey,
25572
+ value,
25573
+ setValue,
25574
+ error,
25575
+ showError,
25576
+ disabled,
25577
+ property,
25578
+ includeDescription,
25579
+ size: t1
25580
+ } = t0;
25581
+ const size = t1 === void 0 ? "large" : t1;
25582
+ const {
25583
+ users,
25584
+ getUser
25585
+ } = useInternalUserManagementController();
25586
+ let t2;
25587
+ if ($[0] !== setValue) {
25588
+ t2 = (e) => {
25589
+ e.stopPropagation();
25590
+ e.preventDefault();
25591
+ setValue(null);
25592
+ };
25593
+ $[0] = setValue;
25594
+ $[1] = t2;
25595
+ } else {
25596
+ t2 = $[1];
25597
+ }
25598
+ const handleClearClick = t2;
25599
+ let t3;
25600
+ if ($[2] !== value) {
25601
+ t3 = value !== void 0 && value != null ? value.toString() : "";
25602
+ $[2] = value;
25603
+ $[3] = t3;
25604
+ } else {
25605
+ t3 = $[3];
25606
+ }
25607
+ let t4;
25608
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
25609
+ t4 = ui.cls("w-full");
25610
+ $[4] = t4;
25611
+ } else {
25612
+ t4 = $[4];
25613
+ }
25614
+ let t5;
25615
+ if ($[5] !== property) {
25616
+ t5 = getIconForProperty(property, "small");
25617
+ $[5] = property;
25618
+ $[6] = t5;
25619
+ } else {
25620
+ t5 = $[6];
25621
+ }
25622
+ const t6 = property.validation?.required;
25623
+ let t7;
25624
+ if ($[7] !== property.name || $[8] !== t5 || $[9] !== t6) {
25625
+ t7 = /* @__PURE__ */ jsxRuntime.jsx(LabelWithIcon, { icon: t5, required: t6, title: property.name, className: "h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5 my-0" });
25626
+ $[7] = property.name;
25627
+ $[8] = t5;
25628
+ $[9] = t6;
25629
+ $[10] = t7;
25630
+ } else {
25631
+ t7 = $[10];
25632
+ }
25633
+ let t8;
25634
+ if ($[11] !== propertyKey || $[12] !== t7) {
25635
+ t8 = /* @__PURE__ */ jsxRuntime.jsx(PropertyIdCopyTooltip, { propertyKey, children: t7 });
25636
+ $[11] = propertyKey;
25637
+ $[12] = t7;
25638
+ $[13] = t8;
25639
+ } else {
25640
+ t8 = $[13];
25641
+ }
25642
+ let t9;
25643
+ if ($[14] !== disabled || $[15] !== handleClearClick || $[16] !== property.clearable || $[17] !== value) {
25644
+ t9 = property.clearable && !disabled && value && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "small", onClick: handleClearClick, children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, { size: "small" }) });
25645
+ $[14] = disabled;
25646
+ $[15] = handleClearClick;
25647
+ $[16] = property.clearable;
25648
+ $[17] = value;
25649
+ $[18] = t9;
25650
+ } else {
25651
+ t9 = $[18];
25652
+ }
25653
+ let t10;
25654
+ if ($[19] !== setValue) {
25655
+ t10 = (updatedValue) => {
25656
+ const newValue = updatedValue || null;
25657
+ return setValue(newValue);
25658
+ };
25659
+ $[19] = setValue;
25660
+ $[20] = t10;
25661
+ } else {
25662
+ t10 = $[20];
25663
+ }
25664
+ let t11;
25665
+ if ($[21] !== getUser) {
25666
+ t11 = (userId) => {
25667
+ const user = getUser(userId);
25668
+ return /* @__PURE__ */ jsxRuntime.jsx(UserDisplay, { user });
25669
+ };
25670
+ $[21] = getUser;
25671
+ $[22] = t11;
25672
+ } else {
25673
+ t11 = $[22];
25674
+ }
25675
+ let t12;
25676
+ if ($[23] !== users) {
25677
+ t12 = users && users.map(_temp$2);
25678
+ $[23] = users;
25679
+ $[24] = t12;
25680
+ } else {
25681
+ t12 = $[24];
25682
+ }
25683
+ let t13;
25684
+ if ($[25] !== disabled || $[26] !== size || $[27] !== t10 || $[28] !== t11 || $[29] !== t12 || $[30] !== t3 || $[31] !== t8 || $[32] !== t9) {
25685
+ t13 = /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { value: t3, disabled, size, fullWidth: true, position: "item-aligned", inputClassName: t4, label: t8, endAdornment: t9, onValueChange: t10, renderValue: t11, children: t12 });
25686
+ $[25] = disabled;
25687
+ $[26] = size;
25688
+ $[27] = t10;
25689
+ $[28] = t11;
25690
+ $[29] = t12;
25691
+ $[30] = t3;
25692
+ $[31] = t8;
25693
+ $[32] = t9;
25694
+ $[33] = t13;
25695
+ } else {
25696
+ t13 = $[33];
25697
+ }
25698
+ let t14;
25699
+ if ($[34] !== disabled || $[35] !== error || $[36] !== includeDescription || $[37] !== property || $[38] !== showError) {
25700
+ t14 = /* @__PURE__ */ jsxRuntime.jsx(FieldHelperText, { includeDescription, showError, error, disabled, property });
25701
+ $[34] = disabled;
25702
+ $[35] = error;
25703
+ $[36] = includeDescription;
25704
+ $[37] = property;
25705
+ $[38] = showError;
25706
+ $[39] = t14;
25707
+ } else {
25708
+ t14 = $[39];
25709
+ }
25710
+ let t15;
25711
+ if ($[40] !== t13 || $[41] !== t14) {
25712
+ t15 = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
25713
+ t13,
25714
+ t14
25715
+ ] });
25716
+ $[40] = t13;
25717
+ $[41] = t14;
25718
+ $[42] = t15;
25719
+ } else {
25720
+ t15 = $[42];
25721
+ }
25722
+ return t15;
25723
+ }
25724
+ function _temp$2(user_0) {
25725
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: user_0.uid, children: /* @__PURE__ */ jsxRuntime.jsx(UserDisplay, { user: user_0 }) }, user_0.uid);
25726
+ }
24410
25727
  function isDefaultFieldConfigId(id) {
24411
25728
  return Object.keys(DEFAULT_FIELD_CONFIGS).includes(id);
24412
25729
  }
@@ -24508,6 +25825,16 @@
24508
25825
  Field: MultiSelectFieldBinding
24509
25826
  }
24510
25827
  },
25828
+ user_select: {
25829
+ key: "user_select",
25830
+ name: "User select",
25831
+ description: "Select a user from the user management system. Store the user ID.",
25832
+ Icon: ui.PersonIcon,
25833
+ property: {
25834
+ dataType: "string",
25835
+ Field: UserSelectFieldBinding
25836
+ }
25837
+ },
24511
25838
  number_input: {
24512
25839
  key: "number_input",
24513
25840
  name: "Number input",
@@ -24722,6 +26049,8 @@
24722
26049
  return "email";
24723
26050
  } else if (property.enumValues) {
24724
26051
  return "select";
26052
+ } else if (property.userSelect) {
26053
+ return "user_select";
24725
26054
  } else if (property.reference) {
24726
26055
  return "reference_as_string";
24727
26056
  } else {
@@ -25760,6 +27089,7 @@
25760
27089
  exports2.SwitchFieldBinding = SwitchFieldBinding;
25761
27090
  exports2.TextFieldBinding = TextFieldBinding;
25762
27091
  exports2.UrlComponentPreview = UrlComponentPreview;
27092
+ exports2.UserPreview = UserPreview;
25763
27093
  exports2.Vector = Vector;
25764
27094
  exports2.VirtualTable = VirtualTable;
25765
27095
  exports2.addInitialSlash = addInitialSlash;
@@ -25813,6 +27143,7 @@
25813
27143
  exports2.getIdIcon = getIdIcon;
25814
27144
  exports2.getLabelOrConfigFrom = getLabelOrConfigFrom;
25815
27145
  exports2.getLastSegment = getLastSegment;
27146
+ exports2.getLocalChangesBackup = getLocalChangesBackup;
25816
27147
  exports2.getPropertiesWithPropertiesOrder = getPropertiesWithPropertiesOrder;
25817
27148
  exports2.getPropertyInPath = getPropertyInPath;
25818
27149
  exports2.getRandomId = getRandomId;
@@ -25827,13 +27158,13 @@
25827
27158
  exports2.isEnumValueDisabled = isEnumValueDisabled;
25828
27159
  exports2.isHidden = isHidden;
25829
27160
  exports2.isObject = isObject;
27161
+ exports2.isPlainObject = isPlainObject;
25830
27162
  exports2.isPropertyBuilder = isPropertyBuilder;
25831
27163
  exports2.isReadOnly = isReadOnly;
25832
27164
  exports2.isReferenceProperty = isReferenceProperty;
25833
27165
  exports2.isValidRegExp = isValidRegExp;
25834
27166
  exports2.joinCollectionLists = joinCollectionLists;
25835
27167
  exports2.makePropertiesEditable = makePropertiesEditable;
25836
- exports2.makePropertiesNonEditable = makePropertiesNonEditable;
25837
27168
  exports2.mergeCallbacks = mergeCallbacks;
25838
27169
  exports2.mergeCollection = mergeCollection;
25839
27170
  exports2.mergeDeep = mergeDeep;
@@ -25894,6 +27225,7 @@
25894
27225
  exports2.useBuildNavigationController = useBuildNavigationController;
25895
27226
  exports2.useClearRestoreValue = useClearRestoreValue;
25896
27227
  exports2.useClipboard = useClipboard;
27228
+ exports2.useCollapsedGroups = useCollapsedGroups;
25897
27229
  exports2.useCollectionFetch = useCollectionFetch;
25898
27230
  exports2.useColumnIds = useColumnIds;
25899
27231
  exports2.useCustomizationController = useCustomizationController;
@@ -25904,6 +27236,7 @@
25904
27236
  exports2.useDialogsController = useDialogsController;
25905
27237
  exports2.useEntityFetch = useEntityFetch;
25906
27238
  exports2.useFireCMSContext = useFireCMSContext;
27239
+ exports2.useInternalUserManagementController = useInternalUserManagementController;
25907
27240
  exports2.useLargeLayout = useLargeLayout;
25908
27241
  exports2.useModeController = useModeController;
25909
27242
  exports2.useNavigationController = useNavigationController;