@firecms/core 3.0.0-canary.289 → 3.0.0-canary.290

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -19,7 +19,7 @@ import { useSortable, defaultAnimateLayoutChanges, arrayMove as arrayMove$1, Sor
19
19
  import { CSS } from "@dnd-kit/utilities";
20
20
  import { restrictToVerticalAxis, restrictToWindowEdges } from "@dnd-kit/modifiers";
21
21
  import { useDropzone } from "react-dropzone";
22
- import Resizer from "react-image-file-resizer";
22
+ import Compressor from "compressorjs";
23
23
  import { FireCMSEditor } from "@firecms/editor";
24
24
  import { themes, Highlight } from "prism-react-renderer";
25
25
  import { useLocation as useLocation$1, useBlocker } from "react-router";
@@ -3544,26 +3544,6 @@ function makePropertiesEditable(properties) {
3544
3544
  });
3545
3545
  return properties;
3546
3546
  }
3547
- function makePropertiesNonEditable(properties) {
3548
- return Object.entries(properties).reduce((acc, [key, property]) => {
3549
- if (!isPropertyBuilder(property) && property.dataType === "map" && property.properties) {
3550
- const updated = {
3551
- ...property,
3552
- properties: makePropertiesNonEditable(property.properties)
3553
- };
3554
- acc[key] = updated;
3555
- }
3556
- if (isPropertyBuilder(property)) {
3557
- acc[key] = property;
3558
- } else {
3559
- acc[key] = {
3560
- ...property,
3561
- editable: false
3562
- };
3563
- }
3564
- return acc;
3565
- }, {});
3566
- }
3567
3547
  function applyModifyFunction(modifyCollection, collection, parentPaths) {
3568
3548
  if (modifyCollection) {
3569
3549
  const modified = modifyCollection({
@@ -3645,8 +3625,8 @@ function mergePropertyOrBuilder(target, source) {
3645
3625
  return target;
3646
3626
  } else {
3647
3627
  const mergedProperty = mergeDeep(target, source);
3648
- const targetEditable = Boolean(target.editable);
3649
- const sourceEditable = Boolean(source.editable);
3628
+ const targetEditable = target.editable === void 0 ? true : Boolean(target.editable);
3629
+ const sourceEditable = source.editable === void 0 ? true : Boolean(source.editable);
3650
3630
  if (source.dataType === "map" && source.properties) {
3651
3631
  const targetProperties = "properties" in target ? target.properties : {};
3652
3632
  const sourceProperties = "properties" in source ? source.properties : {};
@@ -7499,7 +7479,7 @@ const PropertyCollectionView = (t0) => {
7499
7479
  const isArrayOfMaps = ofProp?.dataType === "map";
7500
7480
  const isArrayOfPrimitives = property?.dataType === "array" && ofProp && ofProp.dataType !== "map";
7501
7481
  if (baseKey && property && isArrayOfPrimitives) {
7502
- const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${defaultBorderMixin}` : ""}`;
7482
+ const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${defaultBorderMixin} last:border-b-0` : ""}`;
7503
7483
  let t62;
7504
7484
  if ($[3] !== arrayLabel) {
7505
7485
  t62 = /* @__PURE__ */ jsx("div", { className: "col-span-4 pr-2", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", component: "span", className: "break-words", children: arrayLabel }) });
@@ -7534,7 +7514,7 @@ const PropertyCollectionView = (t0) => {
7534
7514
  }
7535
7515
  return t82;
7536
7516
  }
7537
- const t5 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${defaultBorderMixin}` : ""}`;
7517
+ const t5 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${defaultBorderMixin} last:border-b-0` : ""}`;
7538
7518
  let t6;
7539
7519
  if ($[14] !== arrayLabel || $[15] !== baseKey || $[16] !== suppressHeader) {
7540
7520
  t6 = baseKey && arrayLabel && !suppressHeader && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", component: "span", children: arrayLabel });
@@ -7626,7 +7606,7 @@ const PropertyCollectionView = (t0) => {
7626
7606
  if (!property_0) {
7627
7607
  return null;
7628
7608
  }
7629
- const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${defaultBorderMixin}` : ""}`;
7609
+ const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${defaultBorderMixin} last:border-b-0` : ""}`;
7630
7610
  let t62;
7631
7611
  if ($[41] !== label) {
7632
7612
  t62 = /* @__PURE__ */ jsx("div", { className: "col-span-4 pr-2", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", component: "span", className: "break-words", children: label }) });
@@ -7673,7 +7653,7 @@ const PropertyCollectionView = (t0) => {
7673
7653
  }
7674
7654
  const showMapHeader = t5;
7675
7655
  const headerText = property_0?.name || label;
7676
- const t6 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${defaultBorderMixin}` : ""}`;
7656
+ const t6 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${defaultBorderMixin} last:border-b-0` : ""}`;
7677
7657
  let t7;
7678
7658
  if ($[56] !== headerText || $[57] !== showMapHeader) {
7679
7659
  t7 = showMapHeader && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", component: "span", children: headerText });
@@ -7753,7 +7733,7 @@ const PropertyCollectionView = (t0) => {
7753
7733
  if (!property_1) {
7754
7734
  return null;
7755
7735
  }
7756
- const t5 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${defaultBorderMixin}` : ""}`;
7736
+ const t5 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${defaultBorderMixin} last:border-b-0` : ""}`;
7757
7737
  let t6;
7758
7738
  if ($[78] !== label_0) {
7759
7739
  t6 = /* @__PURE__ */ jsx("div", { className: "col-span-4 pr-2", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", component: "span", className: "break-words", children: label_0 }) });
@@ -8320,7 +8300,8 @@ function useStorageUploadController({
8320
8300
  const processFile = storage?.processFile;
8321
8301
  const metadata = storage?.metadata;
8322
8302
  const size = multipleFilesSupported ? "medium" : "large";
8323
- const compression = storage?.imageCompression;
8303
+ const imageResize = storage?.imageResize;
8304
+ const legacyCompression = storage?.imageCompression;
8324
8305
  const internalInitialValue = getInternalInitialValue(multipleFilesSupported, value, metadata, size);
8325
8306
  const [initialValue, setInitialValue] = useState(value);
8326
8307
  const [internalValue, setInternalValue] = useState(internalInitialValue);
@@ -8392,6 +8373,11 @@ function useStorageUploadController({
8392
8373
  onChange(fieldValue ? fieldValue[0] : null);
8393
8374
  }
8394
8375
  }, [internalValue, multipleFilesSupported, onChange, storage, storageSource]);
8376
+ const onFileUploadError = useCallback((entry_0) => {
8377
+ console.debug("onFileUploadError", entry_0);
8378
+ const newValue_0 = internalValue.filter((item) => item.id !== entry_0.id);
8379
+ setInternalValue(newValue_0);
8380
+ }, [internalValue]);
8395
8381
  const onFilesAdded = useCallback(async (acceptedFiles) => {
8396
8382
  if (!acceptedFiles.length || disabled) return;
8397
8383
  if (processFile) {
@@ -8410,8 +8396,8 @@ function useStorageUploadController({
8410
8396
  let newInternalValue;
8411
8397
  if (multipleFilesSupported) {
8412
8398
  newInternalValue = [...internalValue, ...await Promise.all(acceptedFiles.map(async (file_2) => {
8413
- if (compression && compressionFormat(file_2)) {
8414
- file_2 = await resizeAndCompressImage(file_2, compression);
8399
+ if ((imageResize || legacyCompression) && isImageFile(file_2)) {
8400
+ file_2 = await resizeImage(file_2, imageResize, legacyCompression);
8415
8401
  }
8416
8402
  return {
8417
8403
  id: getRandomId$2(),
@@ -8423,8 +8409,8 @@ function useStorageUploadController({
8423
8409
  }))];
8424
8410
  } else {
8425
8411
  let file_3 = acceptedFiles[0];
8426
- if (compression && compressionFormat(file_3)) {
8427
- file_3 = await resizeAndCompressImage(file_3, compression);
8412
+ if ((imageResize || legacyCompression) && isImageFile(file_3)) {
8413
+ file_3 = await resizeImage(file_3, imageResize, legacyCompression);
8428
8414
  }
8429
8415
  newInternalValue = [{
8430
8416
  id: getRandomId$2(),
@@ -8436,7 +8422,7 @@ function useStorageUploadController({
8436
8422
  }
8437
8423
  newInternalValue = removeDuplicates(newInternalValue);
8438
8424
  setInternalValue(newInternalValue);
8439
- }, [disabled, fileNameBuilder, internalValue, metadata, multipleFilesSupported, size]);
8425
+ }, [disabled, fileNameBuilder, internalValue, metadata, multipleFilesSupported, size, imageResize, legacyCompression]);
8440
8426
  return {
8441
8427
  internalValue,
8442
8428
  setInternalValue,
@@ -8444,6 +8430,7 @@ function useStorageUploadController({
8444
8430
  fileNameBuilder,
8445
8431
  storagePathBuilder,
8446
8432
  onFileUploadComplete,
8433
+ onFileUploadError,
8447
8434
  onFilesAdded,
8448
8435
  multipleFilesSupported
8449
8436
  };
@@ -8474,22 +8461,42 @@ function removeDuplicates(items) {
8474
8461
  function getRandomId$2() {
8475
8462
  return Math.floor(Math.random() * Math.floor(Number.MAX_SAFE_INTEGER));
8476
8463
  }
8477
- const supportedTypes = {
8478
- "image/jpeg": "JPEG",
8479
- "image/png": "PNG",
8480
- "image/webp": "WEBP"
8481
- };
8482
- const compressionFormat = (file) => supportedTypes[file.type] ? supportedTypes[file.type] : null;
8483
- const defaultQuality = 100;
8484
- const resizeAndCompressImage = (file, compression) => new Promise((resolve) => {
8485
- const inputQuality = compression.quality === void 0 ? defaultQuality : compression.quality;
8486
- const quality = inputQuality >= 0 ? inputQuality <= 100 ? inputQuality : 100 : 100;
8487
- const format2 = compressionFormat(file);
8488
- if (!format2) {
8489
- throw Error("resizeAndCompressImage: Unsupported image format");
8490
- }
8491
- Resizer.imageFileResizer(file, compression.maxWidth || Number.MAX_VALUE, compression.maxHeight || Number.MAX_VALUE, format2, quality, 0, (file2) => resolve(file2), "file");
8492
- });
8464
+ function isImageFile(file) {
8465
+ return file.type === "image/jpeg" || file.type === "image/png" || file.type === "image/webp";
8466
+ }
8467
+ async function resizeImage(file, imageResize, legacyCompression) {
8468
+ const maxWidth = imageResize?.maxWidth ?? legacyCompression?.maxWidth;
8469
+ const maxHeight = imageResize?.maxHeight ?? legacyCompression?.maxHeight;
8470
+ const quality = (imageResize?.quality ?? legacyCompression?.quality ?? 80) / 100;
8471
+ const mode = imageResize?.mode ?? "contain";
8472
+ let mimeType = file.type;
8473
+ if (imageResize?.format && imageResize.format !== "original") {
8474
+ mimeType = `image/${imageResize.format}`;
8475
+ }
8476
+ return new Promise((resolve, reject) => {
8477
+ new Compressor(file, {
8478
+ quality,
8479
+ maxWidth,
8480
+ maxHeight,
8481
+ mimeType,
8482
+ // Use cover mode if specified (crops to fit)
8483
+ // Otherwise use contain mode (scales to fit)
8484
+ ...mode === "cover" || mode === void 0 ? {
8485
+ width: maxWidth,
8486
+ height: maxHeight,
8487
+ resize: "cover"
8488
+ } : {},
8489
+ success: (result) => {
8490
+ const compressedFile = new File([result], file.name, {
8491
+ type: result.type,
8492
+ lastModified: Date.now()
8493
+ });
8494
+ resolve(compressedFile);
8495
+ },
8496
+ error: reject
8497
+ });
8498
+ });
8499
+ }
8493
8500
  function StorageUploadProgress({
8494
8501
  storagePath,
8495
8502
  entry,
@@ -11834,7 +11841,7 @@ function StringNumberFilterField(t0) {
11834
11841
  if (value_1 !== "") {
11835
11842
  updateFilter(operation, dataType === "number" ? parseInt(value_1) : value_1);
11836
11843
  }
11837
- }, endAdornment: internalValue && /* @__PURE__ */ jsx(IconButton, { className: "absolute right-2 top-3", onClick: (e_0) => updateFilter(operation, void 0), children: /* @__PURE__ */ jsx(CloseIcon, {}) }), renderValue: (enumKey) => {
11844
+ }, endAdornment: internalValue && /* @__PURE__ */ jsx(IconButton, { onClick: (e_0) => updateFilter(operation, void 0), children: /* @__PURE__ */ jsx(CloseIcon, {}) }), renderValue: (enumKey) => {
11838
11845
  if (enumKey === null) {
11839
11846
  return "Filter for null values";
11840
11847
  }
@@ -11991,7 +11998,7 @@ const operationLabels = {
11991
11998
  };
11992
11999
  const multipleSelectOperations = ["array-contains-any", "in"];
11993
12000
  function DateTimeFilterField(t0) {
11994
- const $ = c(38);
12001
+ const $ = c(39);
11995
12002
  const {
11996
12003
  isArray,
11997
12004
  mode,
@@ -12032,7 +12039,7 @@ function DateTimeFilterField(t0) {
12032
12039
  newValue = newOpIsArray ? val ? [val] : [] : "";
12033
12040
  }
12034
12041
  setOperation(op);
12035
- setInternalValue(newValue === null ? void 0 : newValue);
12042
+ setInternalValue(newValue);
12036
12043
  const hasNewValue = newValue !== null && Array.isArray(newValue) ? newValue.length > 0 : newValue !== void 0;
12037
12044
  if (op && hasNewValue) {
12038
12045
  setValue([op, newValue]);
@@ -12076,83 +12083,85 @@ function DateTimeFilterField(t0) {
12076
12083
  } else {
12077
12084
  t6 = $[16];
12078
12085
  }
12079
- const t7 = internalValue ?? void 0;
12080
- let t8;
12086
+ const t7 = internalValue === null;
12087
+ const t8 = internalValue ?? void 0;
12088
+ let t9;
12081
12089
  if ($[17] !== operation || $[18] !== updateFilter) {
12082
- t8 = (dateValue) => {
12090
+ t9 = (dateValue) => {
12083
12091
  updateFilter(operation, dateValue === null ? void 0 : dateValue);
12084
12092
  };
12085
12093
  $[17] = operation;
12086
12094
  $[18] = updateFilter;
12087
- $[19] = t8;
12095
+ $[19] = t9;
12088
12096
  } else {
12089
- t8 = $[19];
12097
+ t9 = $[19];
12090
12098
  }
12091
- let t9;
12092
- if ($[20] !== locale || $[21] !== mode || $[22] !== t7 || $[23] !== t8) {
12093
- t9 = /* @__PURE__ */ jsx(DateTimeField, { mode, size: "large", locale, value: t7, onChange: t8, clearable: true });
12099
+ let t10;
12100
+ if ($[20] !== locale || $[21] !== mode || $[22] !== t7 || $[23] !== t8 || $[24] !== t9) {
12101
+ t10 = /* @__PURE__ */ jsx(DateTimeField, { mode, size: "large", locale, disabled: t7, value: t8, onChange: t9, clearable: true });
12094
12102
  $[20] = locale;
12095
12103
  $[21] = mode;
12096
12104
  $[22] = t7;
12097
12105
  $[23] = t8;
12098
12106
  $[24] = t9;
12107
+ $[25] = t10;
12099
12108
  } else {
12100
- t9 = $[24];
12109
+ t10 = $[25];
12101
12110
  }
12102
- const t10 = internalValue === null;
12103
- let t11;
12104
- if ($[25] !== internalValue || $[26] !== operation || $[27] !== updateFilter) {
12105
- t11 = (checked) => {
12111
+ const t11 = internalValue === null;
12112
+ let t12;
12113
+ if ($[26] !== internalValue || $[27] !== operation || $[28] !== updateFilter) {
12114
+ t12 = (checked) => {
12106
12115
  if (internalValue !== null) {
12107
12116
  updateFilter(operation, null);
12108
12117
  } else {
12109
12118
  updateFilter(operation, void 0);
12110
12119
  }
12111
12120
  };
12112
- $[25] = internalValue;
12113
- $[26] = operation;
12114
- $[27] = updateFilter;
12115
- $[28] = t11;
12121
+ $[26] = internalValue;
12122
+ $[27] = operation;
12123
+ $[28] = updateFilter;
12124
+ $[29] = t12;
12116
12125
  } else {
12117
- t11 = $[28];
12126
+ t12 = $[29];
12118
12127
  }
12119
- let t12;
12120
- if ($[29] !== t10 || $[30] !== t11) {
12121
- t12 = /* @__PURE__ */ jsxs(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: [
12122
- /* @__PURE__ */ jsx(Checkbox, { id: "null-filter", checked: t10, size: "small", onCheckedChange: t11 }),
12128
+ let t13;
12129
+ if ($[30] !== t11 || $[31] !== t12) {
12130
+ t13 = /* @__PURE__ */ jsxs(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: [
12131
+ /* @__PURE__ */ jsx(Checkbox, { id: "null-filter", checked: t11, size: "small", onCheckedChange: t12 }),
12123
12132
  "Filter for null values"
12124
12133
  ] });
12125
- $[29] = t10;
12126
12134
  $[30] = t11;
12127
12135
  $[31] = t12;
12136
+ $[32] = t13;
12128
12137
  } else {
12129
- t12 = $[31];
12138
+ t13 = $[32];
12130
12139
  }
12131
- let t13;
12132
- if ($[32] !== t12 || $[33] !== t9) {
12133
- t13 = /* @__PURE__ */ jsxs("div", { className: "flex-grow ml-2 flex flex-col gap-2", children: [
12134
- t9,
12135
- t12
12140
+ let t14;
12141
+ if ($[33] !== t10 || $[34] !== t13) {
12142
+ t14 = /* @__PURE__ */ jsxs("div", { className: "flex-grow ml-2 flex flex-col gap-2", children: [
12143
+ t10,
12144
+ t13
12136
12145
  ] });
12137
- $[32] = t12;
12138
- $[33] = t9;
12146
+ $[33] = t10;
12139
12147
  $[34] = t13;
12148
+ $[35] = t14;
12140
12149
  } else {
12141
- t13 = $[34];
12150
+ t14 = $[35];
12142
12151
  }
12143
- let t14;
12144
- if ($[35] !== t13 || $[36] !== t6) {
12145
- t14 = /* @__PURE__ */ jsxs("div", { className: "flex w-[440px]", children: [
12152
+ let t15;
12153
+ if ($[36] !== t14 || $[37] !== t6) {
12154
+ t15 = /* @__PURE__ */ jsxs("div", { className: "flex w-[440px]", children: [
12146
12155
  t6,
12147
- t13
12156
+ t14
12148
12157
  ] });
12149
- $[35] = t13;
12150
- $[36] = t6;
12151
- $[37] = t14;
12158
+ $[36] = t14;
12159
+ $[37] = t6;
12160
+ $[38] = t15;
12152
12161
  } else {
12153
- t14 = $[37];
12162
+ t15 = $[38];
12154
12163
  }
12155
- return t14;
12164
+ return t15;
12156
12165
  }
12157
12166
  function _temp2$5(op_1) {
12158
12167
  return /* @__PURE__ */ jsx(SelectItem, { value: op_1, children: operationLabels[op_1] }, op_1);
@@ -14297,14 +14306,16 @@ function SortableNavigationGroup(t0) {
14297
14306
  return t5;
14298
14307
  }
14299
14308
  function useHomePageDnd({
14300
- items: dndItems,
14301
- setItems: setDndItems,
14309
+ items,
14310
+ setItems,
14302
14311
  disabled,
14303
14312
  onCardMovedBetweenGroups,
14304
14313
  onGroupMoved,
14305
14314
  onNewGroupDrop,
14306
14315
  onPersist
14307
14316
  }) {
14317
+ const dndItems = items;
14318
+ const setDndItems = setItems;
14308
14319
  const [activeId, setActiveId] = useState(null);
14309
14320
  const [activeIsGroup, setActiveIsGroup] = useState(false);
14310
14321
  const [currentDraggingGroupId, setCurrentDraggingGroupId] = useState(null);
@@ -14312,6 +14323,9 @@ function useHomePageDnd({
14312
14323
  const [isDraggingCardOnly, setIsDraggingCardOnly] = useState(false);
14313
14324
  const [dialogOpenForGroup, setDialogOpenForGroup] = useState(null);
14314
14325
  const [isHoveringNewGroupDropZone, setIsHoveringNewGroupDropZone] = useState(false);
14326
+ const [pendingNewGroupName, setPendingNewGroupName] = useState(null);
14327
+ const [stateBeforeNewGroup, setStateBeforeNewGroup] = useState(null);
14328
+ const preDragItemsRef = useRef(null);
14315
14329
  const interimItemsRef = useRef(null);
14316
14330
  useEffect(() => {
14317
14331
  interimItemsRef.current = dndItems;
@@ -14403,6 +14417,7 @@ function useHomePageDnd({
14403
14417
  }) => {
14404
14418
  setDndKitActiveNode(active);
14405
14419
  if (disabled) return;
14420
+ preDragItemsRef.current = cloneItemsForDnd(dndItems);
14406
14421
  const isGroup = dndItems.some((g_7) => g_7.name === active.id);
14407
14422
  if (!active.data.current) active.data.current = {};
14408
14423
  active.data.current.type = isGroup ? "group" : "item";
@@ -14426,18 +14441,30 @@ function useHomePageDnd({
14426
14441
  if (!activeCont) return;
14427
14442
  if (overCont && activeCont !== overCont) {
14428
14443
  recentlyMovedToNewContainer.current = true;
14429
- const newState = cloneItemsForDnd(dndItems);
14430
- const srcIdx = newState.findIndex((g_8) => g_8.name === activeCont);
14431
- const tgtIdx = newState.findIndex((g_9) => g_9.name === overCont);
14432
- if (srcIdx === -1 || tgtIdx === -1) return;
14433
- const src = newState[srcIdx];
14434
- const tgt = newState[tgtIdx];
14435
- const idxInSrc = src.entries.findIndex((e_2) => e_2.url === activeIdNow);
14436
- if (idxInSrc === -1) return;
14437
- const [moved] = src.entries.splice(idxInSrc, 1);
14438
- tgt.entries.push(moved);
14439
- interimItemsRef.current = newState;
14440
- setDndItems(newState);
14444
+ lastOverId.current = overIdNow;
14445
+ setDndItems((current) => {
14446
+ const newState = cloneItemsForDnd(current);
14447
+ const srcIdx = newState.findIndex((g_8) => g_8.name === activeCont);
14448
+ const tgtIdx = newState.findIndex((g_9) => g_9.name === overCont);
14449
+ if (srcIdx === -1 || tgtIdx === -1) return current;
14450
+ const src = newState[srcIdx];
14451
+ const tgt = newState[tgtIdx];
14452
+ const idxInSrc = src.entries.findIndex((e_2) => e_2.url === activeIdNow);
14453
+ if (idxInSrc === -1) return current;
14454
+ const [moved] = src.entries.splice(idxInSrc, 1);
14455
+ const overIsContainer_0 = overIdNow === overCont;
14456
+ if (overIsContainer_0) {
14457
+ tgt.entries.push(moved);
14458
+ } else {
14459
+ const overIdx = tgt.entries.findIndex((e_3) => e_3.url === overIdNow);
14460
+ if (overIdx !== -1) {
14461
+ tgt.entries.splice(overIdx, 0, moved);
14462
+ } else {
14463
+ tgt.entries.push(moved);
14464
+ }
14465
+ }
14466
+ return newState;
14467
+ });
14441
14468
  } else if (activeCont === overCont) {
14442
14469
  recentlyMovedToNewContainer.current = false;
14443
14470
  }
@@ -14464,55 +14491,101 @@ function useHomePageDnd({
14464
14491
  }
14465
14492
  }
14466
14493
  } else {
14467
- const activeCont_0 = findDndContainer(activeIdNow_0);
14494
+ const findContainerInState = (id_0, state) => {
14495
+ const group_0 = state.find((g_13) => g_13.name === id_0);
14496
+ if (group_0) return group_0.name;
14497
+ for (const g_14 of state) {
14498
+ if (g_14.entries.some((e_4) => e_4.url === id_0)) return g_14.name;
14499
+ }
14500
+ return void 0;
14501
+ };
14502
+ const sourceState = preDragItemsRef.current || dndItems;
14503
+ const activeCont_0 = findContainerInState(activeIdNow_0, sourceState);
14504
+ findDndContainer(overIdNow_0);
14468
14505
  if (overIdNow_0 === "new-group-drop-zone") {
14469
14506
  if (activeCont_0) {
14507
+ setStateBeforeNewGroup(cloneItemsForDnd(dndItems));
14470
14508
  const newState_1 = cloneItemsForDnd(dndItems);
14471
- const srcIdx_0 = newState_1.findIndex((g_13) => g_13.name === activeCont_0);
14509
+ const srcIdx_0 = newState_1.findIndex((g_15) => g_15.name === activeCont_0);
14472
14510
  if (srcIdx_0 !== -1) {
14473
14511
  const src_0 = newState_1[srcIdx_0];
14474
- const idxInSrc_0 = src_0.entries.findIndex((e_3) => e_3.url === activeIdNow_0);
14512
+ const idxInSrc_0 = src_0.entries.findIndex((e_5) => e_5.url === activeIdNow_0);
14475
14513
  if (idxInSrc_0 !== -1) {
14476
14514
  const [dragged] = src_0.entries.splice(idxInSrc_0, 1);
14477
14515
  if (src_0.entries.length === 0) newState_1.splice(srcIdx_0, 1);
14478
14516
  let tentative = "New Group";
14479
14517
  let counter = 1;
14480
- while (newState_1.some((g_14) => g_14.name === tentative)) tentative = `New Group ${counter++}`;
14518
+ while (newState_1.some((g_16) => g_16.name === tentative)) tentative = `New Group ${counter++}`;
14481
14519
  newState_1.push({
14482
14520
  name: tentative,
14483
14521
  entries: [dragged]
14484
14522
  });
14485
14523
  setDndItems(newState_1);
14486
- onPersist?.(newState_1);
14524
+ setPendingNewGroupName(tentative);
14487
14525
  setDialogOpenForGroup(tentative);
14488
14526
  onNewGroupDrop?.();
14489
14527
  }
14490
14528
  }
14491
14529
  }
14492
14530
  } else {
14493
- const overCont_0 = findDndContainer(overIdNow_0);
14494
- if (activeCont_0 === overCont_0) {
14495
- const grpIdx = dndItems.findIndex((g_15) => g_15.name === activeCont_0);
14531
+ const overCont_1 = findDndContainer(overIdNow_0);
14532
+ if (activeCont_0 === overCont_1) {
14533
+ const grpIdx = dndItems.findIndex((g_17) => g_17.name === activeCont_0);
14496
14534
  if (grpIdx !== -1) {
14497
- const group_0 = dndItems[grpIdx];
14498
- const oldIdx = group_0.entries.findIndex((e_4) => e_4.url === activeIdNow_0);
14499
- let newIdx = group_0.entries.findIndex((e_5) => e_5.url === overIdNow_0);
14500
- if (newIdx === -1 && overIdNow_0 === activeCont_0) newIdx = group_0.entries.length - 1;
14535
+ const group_1 = dndItems[grpIdx];
14536
+ const oldIdx = group_1.entries.findIndex((e_6) => e_6.url === activeIdNow_0);
14537
+ let newIdx = group_1.entries.findIndex((e_7) => e_7.url === overIdNow_0);
14538
+ if (newIdx === -1 && overIdNow_0 === activeCont_0) newIdx = group_1.entries.length - 1;
14501
14539
  if (oldIdx !== -1 && newIdx !== -1 && oldIdx !== newIdx) {
14502
- const reordered = arrayMove$1(group_0.entries, oldIdx, newIdx);
14540
+ const reordered = arrayMove$1(group_1.entries, oldIdx, newIdx);
14503
14541
  const newState_2 = [...dndItems];
14504
14542
  newState_2[grpIdx] = {
14505
- ...group_0,
14543
+ ...group_1,
14506
14544
  entries: reordered
14507
14545
  };
14508
14546
  setDndItems(newState_2);
14509
14547
  onPersist?.(newState_2);
14510
14548
  }
14511
14549
  }
14512
- } else if (recentlyMovedToNewContainer.current && interimItemsRef.current) {
14513
- onPersist?.(interimItemsRef.current);
14550
+ } else if (overCont_1 && activeCont_0 !== overCont_1) {
14551
+ const finalState = cloneItemsForDnd(sourceState);
14552
+ const finalOverId = lastOverId.current || overIdNow_0;
14553
+ const cleanOverCont = findContainerInState(finalOverId, sourceState) || overCont_1;
14554
+ const srcIdx_1 = finalState.findIndex((g_18) => g_18.name === activeCont_0);
14555
+ const tgtIdx_0 = finalState.findIndex((g_19) => g_19.name === cleanOverCont);
14556
+ if (srcIdx_1 !== -1 && tgtIdx_0 !== -1) {
14557
+ const src_1 = finalState[srcIdx_1];
14558
+ const tgt_0 = finalState[tgtIdx_0];
14559
+ const idxInSrc_1 = src_1.entries.findIndex((e_8) => e_8.url === activeIdNow_0);
14560
+ if (idxInSrc_1 !== -1) {
14561
+ const [moved_0] = src_1.entries.splice(idxInSrc_1, 1);
14562
+ const overIsContainer_1 = finalOverId === cleanOverCont;
14563
+ if (overIsContainer_1) {
14564
+ tgt_0.entries.push(moved_0);
14565
+ } else {
14566
+ const overIdx_0 = tgt_0.entries.findIndex((e_9) => e_9.url === finalOverId);
14567
+ if (overIdx_0 !== -1) {
14568
+ tgt_0.entries.splice(overIdx_0, 0, moved_0);
14569
+ } else {
14570
+ tgt_0.entries.push(moved_0);
14571
+ }
14572
+ }
14573
+ if (src_1.entries.length === 0) {
14574
+ finalState.splice(srcIdx_1, 1);
14575
+ }
14576
+ setDndItems(finalState);
14577
+ onPersist?.(finalState);
14578
+ onCardMovedBetweenGroups?.(moved_0);
14579
+ }
14580
+ }
14581
+ } else if (recentlyMovedToNewContainer.current) {
14582
+ console.error("Move between containers detected but conditions not met", {
14583
+ activeCont: activeCont_0,
14584
+ overCont: overCont_1,
14585
+ activeIdNow: activeIdNow_0,
14586
+ overIdNow: overIdNow_0
14587
+ });
14514
14588
  }
14515
- onCardMovedBetweenGroups?.(dndItems.flatMap((g_16) => g_16.entries).find((e_6) => e_6.url === activeIdNow_0));
14516
14589
  }
14517
14590
  }
14518
14591
  resetDragState();
@@ -14527,11 +14600,11 @@ function useHomePageDnd({
14527
14600
  };
14528
14601
  const handleDragCancel = () => resetDragState();
14529
14602
  const handleRenameGroup = (oldName, newName) => {
14530
- setDndItems((current) => {
14531
- const idx = current.findIndex((g_17) => g_17.name === oldName);
14532
- if (idx === -1) return current;
14533
- if (current.some((g_18) => g_18.name === newName && g_18.name !== oldName)) return current;
14534
- const updated = [...current];
14603
+ setDndItems((current_0) => {
14604
+ const idx = current_0.findIndex((g_20) => g_20.name === oldName);
14605
+ if (idx === -1) return current_0;
14606
+ if (current_0.some((g_21) => g_21.name === newName && g_21.name !== oldName)) return current_0;
14607
+ const updated = [...current_0];
14535
14608
  updated[idx] = {
14536
14609
  ...updated[idx],
14537
14610
  name: newName
@@ -14539,10 +14612,20 @@ function useHomePageDnd({
14539
14612
  onPersist?.(updated);
14540
14613
  return updated;
14541
14614
  });
14615
+ setPendingNewGroupName(null);
14616
+ setStateBeforeNewGroup(null);
14542
14617
  setDialogOpenForGroup(null);
14543
14618
  };
14544
- const activeItemForOverlay = disabled || !activeId || activeIsGroup ? null : dndItems.flatMap((g_19) => g_19.entries).find((e_7) => e_7.url === activeId) || null;
14545
- const activeGroupData = disabled || !activeId || !activeIsGroup ? null : dndItems.find((g_20) => g_20.name === activeId) || null;
14619
+ const handleDialogClose = () => {
14620
+ if (pendingNewGroupName && dialogOpenForGroup === pendingNewGroupName && stateBeforeNewGroup) {
14621
+ setDndItems(stateBeforeNewGroup);
14622
+ }
14623
+ setPendingNewGroupName(null);
14624
+ setStateBeforeNewGroup(null);
14625
+ setDialogOpenForGroup(null);
14626
+ };
14627
+ const activeItemForOverlay = disabled || !activeId || activeIsGroup ? null : dndItems.flatMap((g_22) => g_22.entries).find((e_10) => e_10.url === activeId) || null;
14628
+ const activeGroupData = disabled || !activeId || !activeIsGroup ? null : dndItems.find((g_23) => g_23.name === activeId) || null;
14546
14629
  return {
14547
14630
  sensors,
14548
14631
  collisionDetection,
@@ -14560,6 +14643,7 @@ function useHomePageDnd({
14560
14643
  dialogOpenForGroup,
14561
14644
  setDialogOpenForGroup,
14562
14645
  handleRenameGroup,
14646
+ handleDialogClose,
14563
14647
  isHoveringNewGroupDropZone,
14564
14648
  setIsHoveringNewGroupDropZone
14565
14649
  };
@@ -14937,7 +15021,7 @@ function DefaultHomePage({
14937
15021
  entries: []
14938
15022
  });
14939
15023
  }
14940
- allProcessed = allProcessed.filter((g_4) => g_4.entries.length || groupOrderFromNavController.includes(g_4.name) || g_4.name === DEFAULT_GROUP_NAME && hasPluginAdditionalCards);
15024
+ allProcessed = allProcessed.filter((g_4) => g_4.entries.length || g_4.name === DEFAULT_GROUP_NAME && hasPluginAdditionalCards);
14941
15025
  }
14942
15026
  const admin = allProcessed.find((g_5) => g_5.name === ADMIN_GROUP_NAME);
14943
15027
  return {
@@ -14985,6 +15069,7 @@ function DefaultHomePage({
14985
15069
  dialogOpenForGroup,
14986
15070
  setDialogOpenForGroup,
14987
15071
  handleRenameGroup,
15072
+ handleDialogClose,
14988
15073
  isHoveringNewGroupDropZone,
14989
15074
  setIsHoveringNewGroupDropZone
14990
15075
  } = useHomePageDnd({
@@ -14992,7 +15077,6 @@ function DefaultHomePage({
14992
15077
  setItems: updateItems,
14993
15078
  disabled: !allowDragAndDrop || performingSearch,
14994
15079
  onPersist: persistNavigationGroups,
14995
- // ——► persistence here
14996
15080
  onGroupMoved: (g_8) => context.analyticsController?.onAnalyticsEvent?.("home_move_group", {
14997
15081
  name: g_8
14998
15082
  }),
@@ -15038,7 +15122,7 @@ function DefaultHomePage({
15038
15122
  frequency: 500
15039
15123
  }
15040
15124
  }, onDragStart, onDragOver, onDragEnd, onDragCancel, modifiers: dndModifiers, children: [
15041
- /* @__PURE__ */ jsx(SortableContext, { items: containers, strategy: verticalListSortingStrategy, children: items.map((groupData) => {
15125
+ /* @__PURE__ */ jsx(SortableContext, { items: containers, strategy: verticalListSortingStrategy, children: items.map((groupData, groupIndex) => {
15042
15126
  const groupKey = groupData.name;
15043
15127
  const entriesInGroup = groupData.entries;
15044
15128
  const AdditionalCards = [];
@@ -15049,7 +15133,7 @@ function DefaultHomePage({
15049
15133
  group: groupKey === DEFAULT_GROUP_NAME ? void 0 : groupKey,
15050
15134
  context
15051
15135
  };
15052
- if (entriesInGroup.length === 0 && (AdditionalCards.length === 0 || performingSearch) && !groupOrderFromNavController.includes(groupKey)) return null;
15136
+ if (entriesInGroup.length === 0 && (AdditionalCards.length === 0 || performingSearch)) return null;
15053
15137
  return /* @__PURE__ */ jsx(SortableNavigationGroup, { groupName: groupKey, disabled: dndDisabled, children: /* @__PURE__ */ jsx(NavigationGroup, { group: groupKey === DEFAULT_GROUP_NAME ? void 0 : groupKey, minimised: draggingGroupId === groupKey && !isDraggingCardOnly, isPotentialCardDropTarget: isDraggingCardOnly, dndDisabled, onEditGroup: () => {
15054
15138
  if (dndDisabled) return;
15055
15139
  setDialogOpenForGroup(groupKey);
@@ -15064,7 +15148,7 @@ function DefaultHomePage({
15064
15148
  });
15065
15149
  } }, entry.url)),
15066
15150
  !performingSearch && groupKey.toLowerCase() !== ADMIN_GROUP_NAME.toLowerCase() && AdditionalCards.map((C, i_1) => /* @__PURE__ */ jsx(C, { ...actionProps }, `extra_${groupKey}_${i_1}`))
15067
- ] }) }) }) }, groupKey);
15151
+ ] }) }) }) }, `group-${groupIndex}`);
15068
15152
  }) }, JSON.stringify(containers)),
15069
15153
  /* @__PURE__ */ jsx(NewGroupDropZone, { disabled: dndDisabled, setIsHovering: setIsHoveringNewGroupDropZone }),
15070
15154
  /* @__PURE__ */ jsx(DragOverlay, { adjustScale: false, dropAnimation, children: activeGroupData && draggingGroupId === activeGroupData.name ? /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-transparent", style: {
@@ -15085,7 +15169,7 @@ function DefaultHomePage({
15085
15169
  additionalPluginChildrenEnd,
15086
15170
  additionalChildrenEnd
15087
15171
  ] }),
15088
- dialogOpenForGroup && /* @__PURE__ */ jsx(RenameGroupDialog, { open: true, initialName: dialogOpenForGroup, existingGroupNames: items.map((g_9) => g_9.name).filter((n) => n !== dialogOpenForGroup), onClose: () => setDialogOpenForGroup(null), onRename: (newName) => {
15172
+ dialogOpenForGroup && /* @__PURE__ */ jsx(RenameGroupDialog, { open: true, initialName: dialogOpenForGroup, existingGroupNames: items.map((g_9) => g_9.name).filter((n) => n !== dialogOpenForGroup), onClose: handleDialogClose, onRename: (newName) => {
15089
15173
  handleRenameGroup(dialogOpenForGroup, newName);
15090
15174
  } })
15091
15175
  ] });
@@ -15779,14 +15863,17 @@ function LocalChangesMenu(t0) {
15779
15863
  t14 = $[25];
15780
15864
  }
15781
15865
  let t15;
15782
- let t16;
15783
15866
  if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
15784
- t15 = /* @__PURE__ */ jsx("h3", { className: "text-2xl mb-4", children: "Preview Local Changes" });
15785
- t16 = /* @__PURE__ */ jsx("p", { className: "mb-4", children: "These are the local changes that will be applied to the form." });
15867
+ t15 = /* @__PURE__ */ jsx(DialogTitle, { variant: "h6", children: "Preview Local Changes" });
15786
15868
  $[26] = t15;
15787
- $[27] = t16;
15788
15869
  } else {
15789
15870
  t15 = $[26];
15871
+ }
15872
+ let t16;
15873
+ if ($[27] === Symbol.for("react.memo_cache_sentinel")) {
15874
+ t16 = /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "mb-4", children: "These are the local changes that will be applied to the form." });
15875
+ $[27] = t16;
15876
+ } else {
15790
15877
  t16 = $[27];
15791
15878
  }
15792
15879
  let t17;
@@ -15802,8 +15889,7 @@ function LocalChangesMenu(t0) {
15802
15889
  const t18 = properties;
15803
15890
  let t19;
15804
15891
  if ($[29] !== localChangesData || $[30] !== t18) {
15805
- t19 = /* @__PURE__ */ jsxs(DialogContent, { children: [
15806
- t15,
15892
+ t19 = /* @__PURE__ */ jsxs(DialogContent, { className: "my-4", children: [
15807
15893
  t16,
15808
15894
  /* @__PURE__ */ jsx("div", { className: `border rounded-lg ${defaultBorderMixin}`, style: t17, children: /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsx(PropertyCollectionView, { data: localChangesData, properties: t18 }) }) })
15809
15895
  ] });
@@ -15837,6 +15923,7 @@ function LocalChangesMenu(t0) {
15837
15923
  let t22;
15838
15924
  if ($[35] !== previewDialogOpen || $[36] !== t19 || $[37] !== t21) {
15839
15925
  t22 = /* @__PURE__ */ jsxs(Dialog, { open: previewDialogOpen, onOpenChange: setPreviewDialogOpen, maxWidth: "4xl", children: [
15926
+ t15,
15840
15927
  t19,
15841
15928
  t21
15842
15929
  ] });
@@ -16384,7 +16471,7 @@ function EntityForm({
16384
16471
  /* @__PURE__ */ jsx("div", { id: `form_${path}`, className: 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__ */ jsxs("div", { className: cls("flex flex-col w-full pt-12 pb-16 px-4 sm:px-8 md:px-10"), children: [
16385
16472
  /* @__PURE__ */ jsxs("div", { className: "flex flex-row gap-4 self-end sticky top-4 z-10", children: [
16386
16473
  manualApplyLocalChanges && hasLocalChanges && /* @__PURE__ */ jsx(LocalChangesMenu, { cacheKey: status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId, properties: resolvedCollection.properties, localChangesData, formex, onClearLocalChanges: () => setLocalChangesCleared(true) }),
16387
- formex.dirty ? /* @__PURE__ */ jsx(Tooltip, { title: "There are local unsaved changes", children: /* @__PURE__ */ jsx(Chip, { size: "small", colorScheme: "orangeDarker", children: /* @__PURE__ */ jsx(EditIcon, { size: "smallest" }) }) }) : /* @__PURE__ */ jsx(Tooltip, { title: "The current form is in sync with the database", children: /* @__PURE__ */ jsx(Chip, { size: "small", children: /* @__PURE__ */ jsx(CheckIcon, { size: "smallest" }) }) })
16474
+ formex.dirty ? /* @__PURE__ */ jsx(Tooltip, { title: "This form has been modified", children: /* @__PURE__ */ jsx(Chip, { size: "small", className: "py-1", colorScheme: "orangeDarker", children: /* @__PURE__ */ jsx(EditIcon, { size: "smallest" }) }) }) : /* @__PURE__ */ jsx(Tooltip, { title: "The current form is in sync with the database", children: /* @__PURE__ */ jsx(Chip, { size: "small", className: "py-1", children: /* @__PURE__ */ jsx(CheckIcon, { size: "smallest" }) }) })
16388
16475
  ] }),
16389
16476
  formView
16390
16477
  ] }) }),
@@ -18549,7 +18636,7 @@ const PropertyFieldBinding = React__default.memo(PropertyFieldBindingInternal, (
18549
18636
  return false;
18550
18637
  });
18551
18638
  function PropertyFieldBindingInternal(t0) {
18552
- const $ = c(18);
18639
+ const $ = c(19);
18553
18640
  const {
18554
18641
  propertyKey,
18555
18642
  property,
@@ -18558,6 +18645,7 @@ function PropertyFieldBindingInternal(t0) {
18558
18645
  underlyingValueHasChanged,
18559
18646
  disabled: disabledProp,
18560
18647
  partOfArray,
18648
+ partOfBlock,
18561
18649
  minimalistView,
18562
18650
  autoFocus,
18563
18651
  index,
@@ -18566,15 +18654,8 @@ function PropertyFieldBindingInternal(t0) {
18566
18654
  } = t0;
18567
18655
  const authController = useAuthController();
18568
18656
  const customizationController = useCustomizationController();
18569
- if (propertyKey === "created_by") {
18570
- console.log("Rendering field for created_by", {
18571
- propertyKey,
18572
- property,
18573
- context
18574
- });
18575
- }
18576
18657
  let t1;
18577
- 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) {
18658
+ if ($[0] !== authController || $[1] !== autoFocus || $[2] !== context || $[3] !== customizationController.propertyConfigs || $[4] !== disabledProp || $[5] !== includeDescription || $[6] !== index || $[7] !== minimalistView || $[8] !== onPropertyChange || $[9] !== partOfArray || $[10] !== partOfBlock || $[11] !== property || $[12] !== propertyKey || $[13] !== size || $[14] !== underlyingValueHasChanged) {
18578
18659
  t1 = (fieldProps) => {
18579
18660
  let Component;
18580
18661
  const resolvedProperty = resolveProperty({
@@ -18637,6 +18718,7 @@ function PropertyFieldBindingInternal(t0) {
18637
18718
  context,
18638
18719
  disabled,
18639
18720
  partOfArray,
18721
+ partOfBlock,
18640
18722
  minimalistView,
18641
18723
  autoFocus,
18642
18724
  size,
@@ -18654,22 +18736,23 @@ function PropertyFieldBindingInternal(t0) {
18654
18736
  $[7] = minimalistView;
18655
18737
  $[8] = onPropertyChange;
18656
18738
  $[9] = partOfArray;
18657
- $[10] = property;
18658
- $[11] = propertyKey;
18659
- $[12] = size;
18660
- $[13] = underlyingValueHasChanged;
18661
- $[14] = t1;
18739
+ $[10] = partOfBlock;
18740
+ $[11] = property;
18741
+ $[12] = propertyKey;
18742
+ $[13] = size;
18743
+ $[14] = underlyingValueHasChanged;
18744
+ $[15] = t1;
18662
18745
  } else {
18663
- t1 = $[14];
18746
+ t1 = $[15];
18664
18747
  }
18665
18748
  let t2;
18666
- if ($[15] !== propertyKey || $[16] !== t1) {
18749
+ if ($[16] !== propertyKey || $[17] !== t1) {
18667
18750
  t2 = /* @__PURE__ */ jsx(Field, { name: propertyKey, children: t1 }, propertyKey);
18668
- $[15] = propertyKey;
18669
- $[16] = t1;
18670
- $[17] = t2;
18751
+ $[16] = propertyKey;
18752
+ $[17] = t1;
18753
+ $[18] = t2;
18671
18754
  } else {
18672
- t2 = $[17];
18755
+ t2 = $[18];
18673
18756
  }
18674
18757
  return t2;
18675
18758
  }
@@ -18681,6 +18764,7 @@ function FieldInternal({
18681
18764
  includeDescription,
18682
18765
  underlyingValueHasChanged,
18683
18766
  partOfArray,
18767
+ partOfBlock,
18684
18768
  minimalistView,
18685
18769
  autoFocus,
18686
18770
  context,
@@ -18730,6 +18814,7 @@ function FieldInternal({
18730
18814
  disabled: disabled ?? false,
18731
18815
  underlyingValueHasChanged: underlyingValueHasChanged ?? false,
18732
18816
  partOfArray: partOfArray ?? false,
18817
+ partOfBlock: partOfBlock ?? false,
18733
18818
  minimalistView: minimalistView ?? false,
18734
18819
  autoFocus: autoFocus ?? false,
18735
18820
  customProps: customFieldProps,
@@ -20041,6 +20126,7 @@ function BlockEntry(t0) {
20041
20126
  context,
20042
20127
  autoFocus,
20043
20128
  partOfArray: false,
20129
+ partOfBlock: true,
20044
20130
  minimalistView: true,
20045
20131
  onPropertyChange: storeProps
20046
20132
  } : void 0;
@@ -21052,6 +21138,11 @@ const EntityCollectionView = React__default.memo(function EntityCollectionView2(
21052
21138
  console.error("Save failure");
21053
21139
  console.error(e_0);
21054
21140
  setError(e_0);
21141
+ },
21142
+ onPreSaveHookError: (e_1) => {
21143
+ console.error("Pre-save hook error");
21144
+ console.error(e_1);
21145
+ setError(e_1);
21055
21146
  }
21056
21147
  });
21057
21148
  };
@@ -21149,7 +21240,7 @@ const EntityCollectionView = React__default.memo(function EntityCollectionView2(
21149
21240
  width: width_0,
21150
21241
  frozen
21151
21242
  }) => {
21152
- const isSelected = Boolean(usedSelectionController.selectedEntities.find((e_1) => e_1.id == entity_6.id && e_1.path == entity_6.path));
21243
+ const isSelected = Boolean(usedSelectionController.selectedEntities.find((e_2) => e_2.id == entity_6.id && e_2.path == entity_6.path));
21153
21244
  const customEntityActions_0 = (collection.entityActions ?? []).map((action) => resolveEntityAction(action, customizationController.entityActions)).filter(Boolean);
21154
21245
  const actions_0 = getActionsForEntity({
21155
21246
  entity: entity_6,
@@ -21158,9 +21249,9 @@ const EntityCollectionView = React__default.memo(function EntityCollectionView2(
21158
21249
  return /* @__PURE__ */ 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 });
21159
21250
  }, [updateLastDeleteTimestamp, usedSelectionController]);
21160
21251
  const title = /* @__PURE__ */ jsx(Popover, { open: popOverOpen, onOpenChange: setPopOverOpen, enabled: Boolean(collection.description), trigger: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start", children: [
21161
- /* @__PURE__ */ jsx(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) => {
21252
+ /* @__PURE__ */ jsx(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) => {
21162
21253
  setPopOverOpen(true);
21163
- e_2.stopPropagation();
21254
+ e_3.stopPropagation();
21164
21255
  } : void 0, children: `${collection.name}` }),
21165
21256
  /* @__PURE__ */ jsx(EntitiesCount, { fullPath, collection, filter: tableController.filterValues, sortBy: tableController.sortBy, onCountChange: setDocsCount })
21166
21257
  ] }), children: collection.description && /* @__PURE__ */ jsx("div", { className: "m-4 text-surface-900 dark:text-white", children: /* @__PURE__ */ jsx(Markdown, { source: collection.description }) }) });
@@ -22574,22 +22665,9 @@ function useBuildNavigationController(props) {
22574
22665
  const buildUrlCollectionPath = useCallback((path_0) => `${removeInitialAndTrailingSlashes(baseCollectionPath)}/${encodePath(path_0)}`, [baseCollectionPath]);
22575
22666
  const allPluginGroups = plugins?.flatMap((plugin) => plugin.homePage?.navigationEntries ? plugin.homePage.navigationEntries.map((e) => e.name) : []) ?? [];
22576
22667
  const pluginGroups = [...new Set(allPluginGroups)];
22577
- const onNavigationEntriesOrderUpdate = useCallback((entries) => {
22578
- if (!plugins) {
22579
- return;
22580
- }
22581
- const filteredEntries = entries.filter((entry) => entry.entries.length > 0);
22582
- if (plugins.some((plugin_1) => plugin_1.homePage?.onNavigationEntriesUpdate)) {
22583
- plugins.forEach((plugin_0) => {
22584
- if (plugin_0.homePage?.onNavigationEntriesUpdate) {
22585
- plugin_0.homePage.onNavigationEntriesUpdate(filteredEntries);
22586
- }
22587
- });
22588
- }
22589
- }, [plugins]);
22590
- const computeTopNavigation = useCallback((collections, views, adminViews, viewsOrder_0) => {
22668
+ const computeTopNavigation = useCallback((collections, views, adminViews, viewsOrder_0, navigationGroupMappingsOverride, onNavigationEntriesUpdateCallback) => {
22591
22669
  const finalNavigationGroupMappings = computeNavigationGroups({
22592
- navigationGroupMappings,
22670
+ navigationGroupMappings: navigationGroupMappingsOverride ?? navigationGroupMappings,
22593
22671
  collections,
22594
22672
  views,
22595
22673
  plugins
@@ -22621,7 +22699,7 @@ function useBuildNavigationController(props) {
22621
22699
  return acc;
22622
22700
  }, []), ...(views ?? []).reduce((acc_0, view) => {
22623
22701
  if (view.hideFromNavigation) return acc_0;
22624
- const pathKey_0 = Array.isArray(view.path) ? view.path[0] : view.path;
22702
+ const pathKey_0 = view.path;
22625
22703
  let groupName_0 = getGroup(view);
22626
22704
  if (finalNavigationGroupMappings) {
22627
22705
  for (const pluginGroupDef_0 of finalNavigationGroupMappings) {
@@ -22644,7 +22722,7 @@ function useBuildNavigationController(props) {
22644
22722
  return acc_0;
22645
22723
  }, []), ...(adminViews ?? []).reduce((acc_1, view_0) => {
22646
22724
  if (view_0.hideFromNavigation) return acc_1;
22647
- const pathKey_1 = Array.isArray(view_0.path) ? view_0.path[0] : view_0.path;
22725
+ const pathKey_1 = view_0.path;
22648
22726
  const groupName_1 = NAVIGATION_ADMIN_GROUP_NAME;
22649
22727
  acc_1.push({
22650
22728
  id: `admin:${pathKey_1}`,
@@ -22678,21 +22756,43 @@ function useBuildNavigationController(props) {
22678
22756
  });
22679
22757
  }
22680
22758
  const collectedGroupsFromEntries = navigationEntries.map((e_0) => e_0.group).filter(Boolean);
22681
- const allDefinedGroups = [...pluginGroups ?? [], ...collectedGroupsFromEntries];
22682
- const uniqueGroups = [...new Set(allDefinedGroups)].sort((a_1, b_1) => groupOrderValue(a_1) - groupOrderValue(b_1));
22759
+ const groupsFromMappings = finalNavigationGroupMappings.map((g_0) => g_0.name);
22760
+ const additionalGroups = collectedGroupsFromEntries.filter((g_1) => !groupsFromMappings.includes(g_1));
22761
+ const allDefinedGroups = [...pluginGroups ?? [], ...groupsFromMappings, ...additionalGroups];
22762
+ const uniqueGroupsArray = [...new Set(allDefinedGroups)];
22763
+ const adminGroups = uniqueGroupsArray.filter((g_2) => g_2 === NAVIGATION_ADMIN_GROUP_NAME);
22764
+ const nonAdminGroups = uniqueGroupsArray.filter((g_3) => g_3 !== NAVIGATION_ADMIN_GROUP_NAME);
22765
+ const uniqueGroups = [...nonAdminGroups, ...adminGroups];
22683
22766
  return {
22684
- allowDragAndDrop: plugins?.some((plugin_2) => plugin_2.homePage?.allowDragAndDrop) ?? false,
22767
+ allowDragAndDrop: plugins?.some((plugin_0) => plugin_0.homePage?.allowDragAndDrop) ?? false,
22685
22768
  navigationEntries,
22686
22769
  groups: uniqueGroups,
22687
- onNavigationEntriesUpdate: onNavigationEntriesOrderUpdate
22770
+ onNavigationEntriesUpdate: onNavigationEntriesUpdateCallback
22688
22771
  };
22689
- }, [navigationGroupMappings, buildCMSUrlPath, buildUrlCollectionPath, pluginGroups, onNavigationEntriesOrderUpdate]);
22772
+ }, [navigationGroupMappings, buildCMSUrlPath, buildUrlCollectionPath, pluginGroups]);
22773
+ const onNavigationEntriesOrderUpdate = useCallback((entries) => {
22774
+ if (!plugins) {
22775
+ return;
22776
+ }
22777
+ const filteredEntries = entries.filter((entry) => entry.entries.length > 0);
22778
+ if (collectionsRef.current && viewsRef.current) {
22779
+ const updatedNav = computeTopNavigation(collectionsRef.current, viewsRef.current, adminViewsRef.current ?? [], viewsOrder, filteredEntries, onNavigationEntriesOrderUpdate);
22780
+ setTopLevelNavigation(updatedNav);
22781
+ }
22782
+ if (plugins.some((plugin_2) => plugin_2.homePage?.onNavigationEntriesUpdate)) {
22783
+ plugins.forEach((plugin_1) => {
22784
+ if (plugin_1.homePage?.onNavigationEntriesUpdate) {
22785
+ plugin_1.homePage.onNavigationEntriesUpdate(filteredEntries);
22786
+ }
22787
+ });
22788
+ }
22789
+ }, [plugins, computeTopNavigation, viewsOrder]);
22690
22790
  const refreshNavigation = useCallback(async () => {
22691
22791
  if (disabled || authController.initialLoading) return;
22692
22792
  console.debug("Refreshing navigation");
22693
22793
  try {
22694
22794
  const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, plugins), resolveCMSViews(viewsProp, authController, dataSourceDelegate), resolveCMSViews(adminViewsProp, authController, dataSourceDelegate)]);
22695
- const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
22795
+ const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder, void 0, onNavigationEntriesOrderUpdate);
22696
22796
  let shouldUpdateTopLevelNav = false;
22697
22797
  if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
22698
22798
  collectionsRef.current = resolvedCollections;
@@ -22977,6 +23077,42 @@ function computeNavigationGroups({
22977
23077
  }
22978
23078
  return acc;
22979
23079
  }, [...result ?? []]) : result;
23080
+ const assignedEntries = /* @__PURE__ */ new Set();
23081
+ if (result) {
23082
+ result.forEach((group) => {
23083
+ group.entries.forEach((entry) => assignedEntries.add(entry));
23084
+ });
23085
+ }
23086
+ const unassignedGroupMap = {};
23087
+ (collections ?? []).forEach((collection) => {
23088
+ const entry = collection.id ?? collection.path;
23089
+ if (!assignedEntries.has(entry)) {
23090
+ const groupName = getGroup(collection);
23091
+ if (!unassignedGroupMap[groupName]) unassignedGroupMap[groupName] = [];
23092
+ unassignedGroupMap[groupName].push(entry);
23093
+ }
23094
+ });
23095
+ (views ?? []).forEach((view) => {
23096
+ const entry = view.path;
23097
+ if (!assignedEntries.has(entry)) {
23098
+ const groupName = getGroup(view);
23099
+ if (!unassignedGroupMap[groupName]) unassignedGroupMap[groupName] = [];
23100
+ unassignedGroupMap[groupName].push(entry);
23101
+ }
23102
+ });
23103
+ Object.entries(unassignedGroupMap).forEach(([groupName, entries]) => {
23104
+ if (result) {
23105
+ const existingGroup = result.find((g) => g.name === groupName);
23106
+ if (existingGroup) {
23107
+ existingGroup.entries.push(...entries);
23108
+ } else {
23109
+ result.push({
23110
+ name: groupName,
23111
+ entries
23112
+ });
23113
+ }
23114
+ }
23115
+ });
22980
23116
  if (!result) {
22981
23117
  result = [];
22982
23118
  const groupMap = {};
@@ -22988,7 +23124,7 @@ function computeNavigationGroups({
22988
23124
  });
22989
23125
  (views ?? []).forEach((view) => {
22990
23126
  const name = getGroup(view);
22991
- const entry = Array.isArray(view.path) ? view.path[0] : view.path;
23127
+ const entry = view.path;
22992
23128
  if (!groupMap[name]) groupMap[name] = [];
22993
23129
  groupMap[name].push(entry);
22994
23130
  });
@@ -27031,7 +27167,6 @@ export {
27031
27167
  isValidRegExp,
27032
27168
  joinCollectionLists,
27033
27169
  makePropertiesEditable,
27034
- makePropertiesNonEditable,
27035
27170
  mergeCallbacks,
27036
27171
  mergeCollection,
27037
27172
  mergeDeep,