@firecms/core 3.0.0-canary.286 → 3.0.0-canary.288

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.umd.js CHANGED
@@ -253,6 +253,13 @@
253
253
  function isObject(item) {
254
254
  return item && typeof item === "object" && !Array.isArray(item);
255
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
+ }
256
263
  function mergeDeep(target, source, ignoreUndefined = false) {
257
264
  if (!isObject(target)) {
258
265
  return target;
@@ -273,7 +280,28 @@
273
280
  if (sourceValue instanceof Date) {
274
281
  output[key] = new Date(sourceValue.getTime());
275
282
  } else if (Array.isArray(sourceValue)) {
276
- 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
+ }
277
305
  } else if (isObject(sourceValue)) {
278
306
  if (isObject(outputValue)) {
279
307
  output[key] = mergeDeep(outputValue, sourceValue, ignoreUndefined);
@@ -1052,6 +1080,12 @@
1052
1080
  };
1053
1081
  });
1054
1082
  };
1083
+ function getLocalChangesBackup(collection) {
1084
+ if (!collection.localChangesBackup) {
1085
+ return "manual_apply";
1086
+ }
1087
+ return collection.localChangesBackup;
1088
+ }
1055
1089
  const kebabCaseRegex = /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g;
1056
1090
  const toKebabCase = (str) => {
1057
1091
  const regExpMatchArray = str.match(kebabCaseRegex);
@@ -6769,7 +6803,7 @@
6769
6803
  return t3;
6770
6804
  }
6771
6805
  function NumberPropertyPreview(t0) {
6772
- const $ = reactCompilerRuntime.c(10);
6806
+ const $ = reactCompilerRuntime.c(12);
6773
6807
  const {
6774
6808
  value,
6775
6809
  property,
@@ -6787,38 +6821,42 @@
6787
6821
  }
6788
6822
  const enumValues = t1;
6789
6823
  if (!enumValues) {
6790
- let t22;
6791
- if ($[2] !== value) {
6792
- t22 = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value });
6793
- $[2] = value;
6794
- $[3] = t22;
6824
+ const t22 = size === "small" ? "text-sm" : "";
6825
+ let t32;
6826
+ if ($[2] !== t22 || $[3] !== value) {
6827
+ t32 = /* @__PURE__ */ jsxRuntime.jsx("span", { className: t22, children: value });
6828
+ $[2] = t22;
6829
+ $[3] = value;
6830
+ $[4] = t32;
6795
6831
  } else {
6796
- t22 = $[3];
6832
+ t32 = $[4];
6797
6833
  }
6798
- return t22;
6834
+ return t32;
6799
6835
  }
6800
6836
  const t2 = size !== "medium" ? "small" : "medium";
6801
6837
  let t3;
6802
- if ($[4] !== enumKey || $[5] !== enumValues || $[6] !== t2) {
6838
+ if ($[5] !== enumKey || $[6] !== enumValues || $[7] !== t2) {
6803
6839
  t3 = /* @__PURE__ */ jsxRuntime.jsx(EnumValuesChip, { enumKey, enumValues, size: t2 });
6804
- $[4] = enumKey;
6805
- $[5] = enumValues;
6806
- $[6] = t2;
6807
- $[7] = t3;
6840
+ $[5] = enumKey;
6841
+ $[6] = enumValues;
6842
+ $[7] = t2;
6843
+ $[8] = t3;
6808
6844
  } else {
6809
- t3 = $[7];
6845
+ t3 = $[8];
6810
6846
  }
6811
6847
  return t3;
6812
6848
  } else {
6813
- let t1;
6814
- if ($[8] !== value) {
6815
- t1 = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value });
6816
- $[8] = value;
6849
+ const t1 = size === "small" ? "text-sm" : "";
6850
+ let t2;
6851
+ if ($[9] !== t1 || $[10] !== value) {
6852
+ t2 = /* @__PURE__ */ jsxRuntime.jsx("span", { className: t1, children: value });
6817
6853
  $[9] = t1;
6854
+ $[10] = value;
6855
+ $[11] = t2;
6818
6856
  } else {
6819
- t1 = $[9];
6857
+ t2 = $[11];
6820
6858
  }
6821
- return t1;
6859
+ return t2;
6822
6860
  }
6823
6861
  }
6824
6862
  function UserDisplay(t0) {
@@ -7367,6 +7405,389 @@
7367
7405
  }
7368
7406
  return t3;
7369
7407
  });
7408
+ function buildPropertyLabelAndGetProperty(properties, key) {
7409
+ if (!key) return {
7410
+ label: "",
7411
+ property: void 0
7412
+ };
7413
+ const segments = [];
7414
+ const re = /([^[.\]]+)|\[(\d+)\]/g;
7415
+ let m;
7416
+ while ((m = re.exec(key)) !== null) {
7417
+ if (m[1] !== void 0) segments.push(m[1]);
7418
+ else if (m[2] !== void 0) segments.push(Number(m[2]));
7419
+ }
7420
+ let currentProps = properties;
7421
+ let currentProp;
7422
+ let lastLabel = "";
7423
+ const getArrayOfProp = (p) => {
7424
+ if (!p || p.dataType !== "array") return void 0;
7425
+ return Array.isArray(p.of) ? p.of[0] : p.of;
7426
+ };
7427
+ for (const seg of segments) {
7428
+ if (typeof seg === "number") {
7429
+ lastLabel = `[${seg}]`;
7430
+ if (currentProp?.dataType === "array") {
7431
+ currentProp = getArrayOfProp(currentProp);
7432
+ if (currentProp?.dataType === "map" && currentProp.properties) {
7433
+ currentProps = currentProp.properties;
7434
+ } else {
7435
+ currentProps = void 0;
7436
+ }
7437
+ } else {
7438
+ currentProp = void 0;
7439
+ currentProps = void 0;
7440
+ }
7441
+ continue;
7442
+ }
7443
+ if (currentProps && currentProps[seg]) {
7444
+ const nextProp = currentProps[seg];
7445
+ currentProp = nextProp;
7446
+ lastLabel = nextProp.name || String(seg);
7447
+ if (nextProp.dataType === "map" && nextProp.properties) {
7448
+ currentProps = nextProp.properties;
7449
+ } else if (nextProp.dataType === "array") {
7450
+ currentProps = void 0;
7451
+ } else {
7452
+ currentProps = void 0;
7453
+ }
7454
+ } else {
7455
+ currentProp = void 0;
7456
+ currentProps = void 0;
7457
+ lastLabel = String(seg);
7458
+ }
7459
+ }
7460
+ return {
7461
+ label: lastLabel,
7462
+ property: currentProp
7463
+ };
7464
+ }
7465
+ const pathEndsWithIndex = (p) => /\[\d+\]$/.test(p);
7466
+ const PropertyCollectionView = (t0) => {
7467
+ const $ = reactCompilerRuntime.c(89);
7468
+ const {
7469
+ data,
7470
+ properties,
7471
+ baseKey: t1,
7472
+ suppressHeader: t2,
7473
+ size: t3
7474
+ } = t0;
7475
+ const baseKey = t1 === void 0 ? "" : t1;
7476
+ const suppressHeader = t2 === void 0 ? false : t2;
7477
+ const size = t3 === void 0 ? "small" : t3;
7478
+ const isTopLevel = !!baseKey && !baseKey.includes(".") && !baseKey.includes("[");
7479
+ if (Array.isArray(data)) {
7480
+ let t4;
7481
+ if ($[0] !== baseKey || $[1] !== properties) {
7482
+ t4 = baseKey ? buildPropertyLabelAndGetProperty(properties, baseKey) : {
7483
+ label: "",
7484
+ property: void 0
7485
+ };
7486
+ $[0] = baseKey;
7487
+ $[1] = properties;
7488
+ $[2] = t4;
7489
+ } else {
7490
+ t4 = $[2];
7491
+ }
7492
+ const {
7493
+ label: arrayLabel,
7494
+ property
7495
+ } = t4;
7496
+ const ofProp = property?.dataType === "array" ? Array.isArray(property.of) ? property.of[0] : property.of : void 0;
7497
+ const isArrayOfMaps = ofProp?.dataType === "map";
7498
+ const isArrayOfPrimitives = property?.dataType === "array" && ofProp && ofProp.dataType !== "map";
7499
+ if (baseKey && property && isArrayOfPrimitives) {
7500
+ const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${ui.defaultBorderMixin}` : ""}`;
7501
+ let t62;
7502
+ if ($[3] !== arrayLabel) {
7503
+ 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 }) });
7504
+ $[3] = arrayLabel;
7505
+ $[4] = t62;
7506
+ } else {
7507
+ t62 = $[4];
7508
+ }
7509
+ let t72;
7510
+ if ($[5] !== baseKey || $[6] !== data || $[7] !== property || $[8] !== size) {
7511
+ t72 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-8", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: baseKey, value: data, property, size }) });
7512
+ $[5] = baseKey;
7513
+ $[6] = data;
7514
+ $[7] = property;
7515
+ $[8] = size;
7516
+ $[9] = t72;
7517
+ } else {
7518
+ t72 = $[9];
7519
+ }
7520
+ let t82;
7521
+ if ($[10] !== t52 || $[11] !== t62 || $[12] !== t72) {
7522
+ t82 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t52, children: [
7523
+ t62,
7524
+ t72
7525
+ ] });
7526
+ $[10] = t52;
7527
+ $[11] = t62;
7528
+ $[12] = t72;
7529
+ $[13] = t82;
7530
+ } else {
7531
+ t82 = $[13];
7532
+ }
7533
+ return t82;
7534
+ }
7535
+ const t5 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${ui.defaultBorderMixin}` : ""}`;
7536
+ let t6;
7537
+ if ($[14] !== arrayLabel || $[15] !== baseKey || $[16] !== suppressHeader) {
7538
+ t6 = baseKey && arrayLabel && !suppressHeader && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", children: arrayLabel });
7539
+ $[14] = arrayLabel;
7540
+ $[15] = baseKey;
7541
+ $[16] = suppressHeader;
7542
+ $[17] = t6;
7543
+ } else {
7544
+ t6 = $[17];
7545
+ }
7546
+ const t7 = baseKey ? `pl-4 mt-1 border-l ${ui.defaultBorderMixin}` : "";
7547
+ let t8;
7548
+ if ($[18] !== baseKey || $[19] !== data || $[20] !== isArrayOfMaps || $[21] !== ofProp || $[22] !== properties || $[23] !== size) {
7549
+ let t92;
7550
+ if ($[25] !== baseKey || $[26] !== isArrayOfMaps || $[27] !== ofProp || $[28] !== properties || $[29] !== size) {
7551
+ t92 = (item, index) => {
7552
+ if (item === null || item === void 0) {
7553
+ return null;
7554
+ }
7555
+ const currentKey = baseKey ? `${baseKey}[${index}]` : `[${index}]`;
7556
+ const itemHeader = isArrayOfMaps && ofProp?.name ? `${ofProp.name} [${index}]` : `[${index}]`;
7557
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1", children: [
7558
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", children: itemHeader }),
7559
+ /* @__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 }) })
7560
+ ] }, currentKey);
7561
+ };
7562
+ $[25] = baseKey;
7563
+ $[26] = isArrayOfMaps;
7564
+ $[27] = ofProp;
7565
+ $[28] = properties;
7566
+ $[29] = size;
7567
+ $[30] = t92;
7568
+ } else {
7569
+ t92 = $[30];
7570
+ }
7571
+ t8 = data.map(t92);
7572
+ $[18] = baseKey;
7573
+ $[19] = data;
7574
+ $[20] = isArrayOfMaps;
7575
+ $[21] = ofProp;
7576
+ $[22] = properties;
7577
+ $[23] = size;
7578
+ $[24] = t8;
7579
+ } else {
7580
+ t8 = $[24];
7581
+ }
7582
+ let t9;
7583
+ if ($[31] !== t7 || $[32] !== t8) {
7584
+ t9 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: t7, children: t8 });
7585
+ $[31] = t7;
7586
+ $[32] = t8;
7587
+ $[33] = t9;
7588
+ } else {
7589
+ t9 = $[33];
7590
+ }
7591
+ let t10;
7592
+ if ($[34] !== t5 || $[35] !== t6 || $[36] !== t9) {
7593
+ t10 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t5, children: [
7594
+ t6,
7595
+ t9
7596
+ ] });
7597
+ $[34] = t5;
7598
+ $[35] = t6;
7599
+ $[36] = t9;
7600
+ $[37] = t10;
7601
+ } else {
7602
+ t10 = $[37];
7603
+ }
7604
+ return t10;
7605
+ }
7606
+ if (typeof data === "object" && data !== null) {
7607
+ let t4;
7608
+ if ($[38] !== baseKey || $[39] !== properties) {
7609
+ t4 = baseKey ? buildPropertyLabelAndGetProperty(properties, baseKey) : {
7610
+ label: "",
7611
+ property: void 0
7612
+ };
7613
+ $[38] = baseKey;
7614
+ $[39] = properties;
7615
+ $[40] = t4;
7616
+ } else {
7617
+ t4 = $[40];
7618
+ }
7619
+ const {
7620
+ label,
7621
+ property: property_0
7622
+ } = t4;
7623
+ if (baseKey && (!property_0 || property_0.dataType !== "map" || !property_0.properties)) {
7624
+ if (!property_0) {
7625
+ return null;
7626
+ }
7627
+ const t52 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${ui.defaultBorderMixin}` : ""}`;
7628
+ let t62;
7629
+ if ($[41] !== label) {
7630
+ 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 }) });
7631
+ $[41] = label;
7632
+ $[42] = t62;
7633
+ } else {
7634
+ t62 = $[42];
7635
+ }
7636
+ let t72;
7637
+ if ($[43] !== baseKey || $[44] !== data || $[45] !== property_0 || $[46] !== size) {
7638
+ t72 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-8", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: baseKey, value: data, property: property_0, size }) });
7639
+ $[43] = baseKey;
7640
+ $[44] = data;
7641
+ $[45] = property_0;
7642
+ $[46] = size;
7643
+ $[47] = t72;
7644
+ } else {
7645
+ t72 = $[47];
7646
+ }
7647
+ let t82;
7648
+ if ($[48] !== t52 || $[49] !== t62 || $[50] !== t72) {
7649
+ t82 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t52, children: [
7650
+ t62,
7651
+ t72
7652
+ ] });
7653
+ $[48] = t52;
7654
+ $[49] = t62;
7655
+ $[50] = t72;
7656
+ $[51] = t82;
7657
+ } else {
7658
+ t82 = $[51];
7659
+ }
7660
+ return t82;
7661
+ }
7662
+ let t5;
7663
+ if ($[52] !== baseKey || $[53] !== property_0 || $[54] !== suppressHeader) {
7664
+ t5 = baseKey && !suppressHeader && property_0?.dataType === "map" && (property_0.name || !pathEndsWithIndex(baseKey));
7665
+ $[52] = baseKey;
7666
+ $[53] = property_0;
7667
+ $[54] = suppressHeader;
7668
+ $[55] = t5;
7669
+ } else {
7670
+ t5 = $[55];
7671
+ }
7672
+ const showMapHeader = t5;
7673
+ const headerText = property_0?.name || label;
7674
+ const t6 = `${isTopLevel ? "py-4" : "py-1"} ${isTopLevel ? `border-b ${ui.defaultBorderMixin}` : ""}`;
7675
+ let t7;
7676
+ if ($[56] !== headerText || $[57] !== showMapHeader) {
7677
+ t7 = showMapHeader && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", component: "span", children: headerText });
7678
+ $[56] = headerText;
7679
+ $[57] = showMapHeader;
7680
+ $[58] = t7;
7681
+ } else {
7682
+ t7 = $[58];
7683
+ }
7684
+ const t8 = baseKey ? `pl-4 mt-1 border-l ${ui.defaultBorderMixin}` : "";
7685
+ let t9;
7686
+ if ($[59] !== baseKey || $[60] !== data || $[61] !== properties || $[62] !== size) {
7687
+ let t102;
7688
+ if ($[64] !== baseKey || $[65] !== properties || $[66] !== size) {
7689
+ t102 = (t112) => {
7690
+ const [key, value] = t112;
7691
+ if (value === null || value === void 0) {
7692
+ return null;
7693
+ }
7694
+ const currentKey_0 = baseKey ? `${baseKey}.${key}` : key;
7695
+ return /* @__PURE__ */ jsxRuntime.jsx(PropertyCollectionView, { data: value, properties, baseKey: currentKey_0, size }, currentKey_0);
7696
+ };
7697
+ $[64] = baseKey;
7698
+ $[65] = properties;
7699
+ $[66] = size;
7700
+ $[67] = t102;
7701
+ } else {
7702
+ t102 = $[67];
7703
+ }
7704
+ t9 = Object.entries(data).map(t102);
7705
+ $[59] = baseKey;
7706
+ $[60] = data;
7707
+ $[61] = properties;
7708
+ $[62] = size;
7709
+ $[63] = t9;
7710
+ } else {
7711
+ t9 = $[63];
7712
+ }
7713
+ let t10;
7714
+ if ($[68] !== t8 || $[69] !== t9) {
7715
+ t10 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: t8, children: t9 });
7716
+ $[68] = t8;
7717
+ $[69] = t9;
7718
+ $[70] = t10;
7719
+ } else {
7720
+ t10 = $[70];
7721
+ }
7722
+ let t11;
7723
+ if ($[71] !== t10 || $[72] !== t6 || $[73] !== t7) {
7724
+ t11 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t6, children: [
7725
+ t7,
7726
+ t10
7727
+ ] });
7728
+ $[71] = t10;
7729
+ $[72] = t6;
7730
+ $[73] = t7;
7731
+ $[74] = t11;
7732
+ } else {
7733
+ t11 = $[74];
7734
+ }
7735
+ return t11;
7736
+ }
7737
+ if (baseKey) {
7738
+ let t4;
7739
+ if ($[75] !== baseKey || $[76] !== properties) {
7740
+ t4 = buildPropertyLabelAndGetProperty(properties, baseKey);
7741
+ $[75] = baseKey;
7742
+ $[76] = properties;
7743
+ $[77] = t4;
7744
+ } else {
7745
+ t4 = $[77];
7746
+ }
7747
+ const {
7748
+ label: label_0,
7749
+ property: property_1
7750
+ } = t4;
7751
+ if (!property_1) {
7752
+ return null;
7753
+ }
7754
+ const t5 = `grid grid-cols-12 gap-x-4 ${isTopLevel ? "py-4" : "py-2"} items-start ${isTopLevel ? `border-b ${ui.defaultBorderMixin}` : ""}`;
7755
+ let t6;
7756
+ if ($[78] !== label_0) {
7757
+ 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 }) });
7758
+ $[78] = label_0;
7759
+ $[79] = t6;
7760
+ } else {
7761
+ t6 = $[79];
7762
+ }
7763
+ let t7;
7764
+ if ($[80] !== baseKey || $[81] !== data || $[82] !== property_1 || $[83] !== size) {
7765
+ t7 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-8", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: baseKey, value: data, property: property_1, size }) });
7766
+ $[80] = baseKey;
7767
+ $[81] = data;
7768
+ $[82] = property_1;
7769
+ $[83] = size;
7770
+ $[84] = t7;
7771
+ } else {
7772
+ t7 = $[84];
7773
+ }
7774
+ let t8;
7775
+ if ($[85] !== t5 || $[86] !== t6 || $[87] !== t7) {
7776
+ t8 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t5, children: [
7777
+ t6,
7778
+ t7
7779
+ ] });
7780
+ $[85] = t5;
7781
+ $[86] = t6;
7782
+ $[87] = t7;
7783
+ $[88] = t8;
7784
+ } else {
7785
+ t8 = $[88];
7786
+ }
7787
+ return t8;
7788
+ }
7789
+ return null;
7790
+ };
7370
7791
  function EntityView({
7371
7792
  entity,
7372
7793
  collection,
@@ -7384,31 +7805,17 @@
7384
7805
  authController
7385
7806
  }), [collection, path, entity, customizationController.propertyConfigs]);
7386
7807
  const properties = resolvedCollection.properties;
7387
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full " + className, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full mb-4", children: [
7388
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls(ui.defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0"), children: [
7389
- /* @__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" }) }),
7390
- /* @__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: [
7808
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full " + className, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full mb-4 p-4", children: [
7809
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `grid grid-cols-12 gap-x-4 py-4 items-start border-b ${ui.defaultBorderMixin}`, children: [
7810
+ /* @__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" }) }),
7811
+ /* @__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: [
7391
7812
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-grow mr-2", children: entity.id }),
7392
7813
  customizationController?.entityLinkBuilder && /* @__PURE__ */ jsxRuntime.jsx("a", { href: customizationController.entityLinkBuilder({
7393
7814
  entity
7394
7815
  }), rel: "noopener noreferrer", target: "_blank", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.OpenInNewIcon, { size: "small" }) }) })
7395
- ] })
7816
+ ] }) })
7396
7817
  ] }),
7397
- Object.entries(properties).map(([key, property]) => {
7398
- const value = entity.values?.[key];
7399
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls(ui.defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0"), children: [
7400
- /* @__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 }) }),
7401
- /* @__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(
7402
- PropertyPreview,
7403
- {
7404
- propertyKey: key,
7405
- value,
7406
- property,
7407
- size: "medium"
7408
- }
7409
- ) })
7410
- ] }, `reference_previews_${key}`);
7411
- })
7818
+ /* @__PURE__ */ jsxRuntime.jsx(PropertyCollectionView, { data: entity.values, properties, size: "medium" })
7412
7819
  ] }) });
7413
7820
  }
7414
7821
  function VirtualTableInput(props) {
@@ -9755,28 +10162,40 @@
9755
10162
  return value;
9756
10163
  }
9757
10164
  function saveEntityToCache(path, data) {
9758
- entityCache.set(path, data);
9759
10165
  if (isLocalStorageAvailable) {
9760
10166
  try {
9761
10167
  const key = LOCAL_STORAGE_PREFIX + path;
9762
10168
  const entityString = JSON.stringify(data, customReplacer);
10169
+ console.log("Saving entity to localStorage:", {
10170
+ key,
10171
+ entityString
10172
+ });
9763
10173
  localStorage.setItem(key, entityString);
9764
10174
  } catch (error) {
9765
10175
  console.error(`Failed to save entity for path "${path}" to localStorage:`, error);
9766
10176
  }
9767
10177
  }
9768
10178
  }
9769
- function getEntityFromCache(path, useLocalStorage = true) {
9770
- if (entityCache.has(path)) {
9771
- return entityCache.get(path);
9772
- }
9773
- if (isLocalStorageAvailable && useLocalStorage) {
10179
+ function removeEntityFromMemoryCache(path) {
10180
+ entityCache.delete(path);
10181
+ }
10182
+ function saveEntityToMemoryCache(path, data) {
10183
+ entityCache.set(path, data);
10184
+ }
10185
+ function getEntityFromMemoryCache(path) {
10186
+ return entityCache.get(path);
10187
+ }
10188
+ function getEntityFromCache(path) {
10189
+ if (isLocalStorageAvailable) {
9774
10190
  try {
9775
10191
  const key = LOCAL_STORAGE_PREFIX + path;
9776
10192
  const entityString = localStorage.getItem(key);
9777
10193
  if (entityString) {
9778
10194
  const entity = JSON.parse(entityString, customReviver);
9779
- entityCache.set(path, entity);
10195
+ console.log("Loaded entity from localStorage:", {
10196
+ key,
10197
+ entity
10198
+ });
9780
10199
  return entity;
9781
10200
  }
9782
10201
  } catch (error) {
@@ -9785,12 +10204,7 @@
9785
10204
  }
9786
10205
  return void 0;
9787
10206
  }
9788
- function hasEntityInCache(path) {
9789
- return entityCache.has(path);
9790
- }
9791
10207
  function removeEntityFromCache(path) {
9792
- console.debug("Removing entity from cache", path);
9793
- entityCache.delete(path);
9794
10208
  if (isLocalStorageAvailable) {
9795
10209
  try {
9796
10210
  const key = LOCAL_STORAGE_PREFIX + path;
@@ -9800,6 +10214,26 @@
9800
10214
  }
9801
10215
  }
9802
10216
  }
10217
+ function flattenKeys(obj, prefix = "", result = []) {
10218
+ if (isObject(obj) || Array.isArray(obj)) {
10219
+ const plainObject = isPlainObject(obj);
10220
+ if (!plainObject && prefix) {
10221
+ result.push(prefix);
10222
+ } else {
10223
+ for (const key in obj) {
10224
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
10225
+ const newKey = prefix ? Array.isArray(obj) ? `${prefix}[${key}]` : `${prefix}.${key}` : key;
10226
+ if (isObject(obj[key]) || Array.isArray(obj[key])) {
10227
+ flattenKeys(obj[key], newKey, result);
10228
+ } else {
10229
+ result.push(newKey);
10230
+ }
10231
+ }
10232
+ }
10233
+ }
10234
+ }
10235
+ return result;
10236
+ }
9803
10237
  const EntityCollectionRowActions = function EntityCollectionRowActions2({
9804
10238
  entity,
9805
10239
  collection,
@@ -9827,8 +10261,8 @@
9827
10261
  const hasCollapsedActions = actions.some((a) => a.collapsed || a.collapsed === void 0);
9828
10262
  const collapsedActions = actions.filter((a_0) => a_0.collapsed || a_0.collapsed === void 0);
9829
10263
  const uncollapsedActions = actions.filter((a_1) => a_1.collapsed === false);
9830
- const enableLocalChangesBackup = collection?.enableLocalChangesBackup !== void 0 ? collection?.enableLocalChangesBackup : true;
9831
- const hasDraft = enableLocalChangesBackup ? hasEntityInCache(fullPath + "/" + entity.id) : false;
10264
+ const enableLocalChangesBackup = collection ? getLocalChangesBackup(collection) : false;
10265
+ const hasDraft = enableLocalChangesBackup ? getEntityFromCache(fullPath + "/" + entity.id) : false;
9832
10266
  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) => {
9833
10267
  event.stopPropagation();
9834
10268
  }, []), style: {
@@ -15163,6 +15597,262 @@
15163
15597
  savingError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { color: "error", children: savingError.message }) })
15164
15598
  ] });
15165
15599
  }
15600
+ function LocalChangesMenu(t0) {
15601
+ const $ = reactCompilerRuntime.c(42);
15602
+ const {
15603
+ localChangesData,
15604
+ formex: formex2,
15605
+ onClearLocalChanges,
15606
+ cacheKey,
15607
+ properties
15608
+ } = t0;
15609
+ const snackbarController = useSnackbarController();
15610
+ const [previewDialogOpen, setPreviewDialogOpen] = React.useState(false);
15611
+ const [open, setOpen] = React.useState(false);
15612
+ let t1;
15613
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
15614
+ t1 = () => setOpen(true);
15615
+ $[0] = t1;
15616
+ } else {
15617
+ t1 = $[0];
15618
+ }
15619
+ const handleOpenMenu = t1;
15620
+ let t2;
15621
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
15622
+ t2 = () => setOpen(false);
15623
+ $[1] = t2;
15624
+ } else {
15625
+ t2 = $[1];
15626
+ }
15627
+ const handleCloseMenu = t2;
15628
+ let t3;
15629
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
15630
+ t3 = () => {
15631
+ setPreviewDialogOpen(true);
15632
+ handleCloseMenu();
15633
+ };
15634
+ $[2] = t3;
15635
+ } else {
15636
+ t3 = $[2];
15637
+ }
15638
+ const handlePreview = t3;
15639
+ let t4;
15640
+ if ($[3] !== formex2 || $[4] !== localChangesData || $[5] !== onClearLocalChanges || $[6] !== snackbarController) {
15641
+ t4 = () => {
15642
+ const mergedValues = mergeDeep(formex2.values, localChangesData);
15643
+ const touched = {
15644
+ ...formex2.touched
15645
+ };
15646
+ const previewKeys = flattenKeys(localChangesData);
15647
+ previewKeys.forEach((key) => {
15648
+ touched[key] = true;
15649
+ });
15650
+ formex2.setTouched(touched);
15651
+ formex2.setValues(mergedValues);
15652
+ snackbarController.open({
15653
+ type: "info",
15654
+ message: "Local changes applied to the form"
15655
+ });
15656
+ handleCloseMenu();
15657
+ onClearLocalChanges?.();
15658
+ };
15659
+ $[3] = formex2;
15660
+ $[4] = localChangesData;
15661
+ $[5] = onClearLocalChanges;
15662
+ $[6] = snackbarController;
15663
+ $[7] = t4;
15664
+ } else {
15665
+ t4 = $[7];
15666
+ }
15667
+ const handleApply = t4;
15668
+ let t5;
15669
+ if ($[8] !== cacheKey || $[9] !== onClearLocalChanges || $[10] !== snackbarController) {
15670
+ t5 = () => {
15671
+ removeEntityFromCache(cacheKey);
15672
+ snackbarController.open({
15673
+ type: "info",
15674
+ message: "Local changes discarded"
15675
+ });
15676
+ handleCloseMenu();
15677
+ onClearLocalChanges?.();
15678
+ };
15679
+ $[8] = cacheKey;
15680
+ $[9] = onClearLocalChanges;
15681
+ $[10] = snackbarController;
15682
+ $[11] = t5;
15683
+ } else {
15684
+ t5 = $[11];
15685
+ }
15686
+ const handleDiscard = t5;
15687
+ let t6;
15688
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
15689
+ t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.WarningIcon, { size: "smallest", className: "mr-1 text-yellow-600 dark:text-yellow-400" });
15690
+ $[12] = t6;
15691
+ } else {
15692
+ t6 = $[12];
15693
+ }
15694
+ let t7;
15695
+ if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
15696
+ 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: [
15697
+ t6,
15698
+ "Unsaved Local changes",
15699
+ /* @__PURE__ */ jsxRuntime.jsx(ui.KeyboardArrowDownIcon, { size: "smallest" })
15700
+ ] });
15701
+ $[13] = t7;
15702
+ } else {
15703
+ t7 = $[13];
15704
+ }
15705
+ let t8;
15706
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
15707
+ 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." });
15708
+ $[14] = t8;
15709
+ } else {
15710
+ t8 = $[14];
15711
+ }
15712
+ let t9;
15713
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
15714
+ t9 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handlePreview, children: [
15715
+ /* @__PURE__ */ jsxRuntime.jsx(ui.VisibilityIcon, { size: "small" }),
15716
+ "Preview Changes"
15717
+ ] });
15718
+ $[15] = t9;
15719
+ } else {
15720
+ t9 = $[15];
15721
+ }
15722
+ let t10;
15723
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
15724
+ t10 = /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "small" });
15725
+ $[16] = t10;
15726
+ } else {
15727
+ t10 = $[16];
15728
+ }
15729
+ let t11;
15730
+ if ($[17] !== handleApply) {
15731
+ t11 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handleApply, children: [
15732
+ t10,
15733
+ "Apply Changes"
15734
+ ] });
15735
+ $[17] = handleApply;
15736
+ $[18] = t11;
15737
+ } else {
15738
+ t11 = $[18];
15739
+ }
15740
+ let t12;
15741
+ if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
15742
+ t12 = /* @__PURE__ */ jsxRuntime.jsx(ui.CancelIcon, { size: "small" });
15743
+ $[19] = t12;
15744
+ } else {
15745
+ t12 = $[19];
15746
+ }
15747
+ let t13;
15748
+ if ($[20] !== handleDiscard) {
15749
+ t13 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handleDiscard, children: [
15750
+ t12,
15751
+ "Discard Local Changes"
15752
+ ] });
15753
+ $[20] = handleDiscard;
15754
+ $[21] = t13;
15755
+ } else {
15756
+ t13 = $[21];
15757
+ }
15758
+ let t14;
15759
+ if ($[22] !== open || $[23] !== t11 || $[24] !== t13) {
15760
+ t14 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Menu, { trigger: t7, open, onOpenChange: setOpen, children: [
15761
+ t8,
15762
+ t9,
15763
+ t11,
15764
+ t13
15765
+ ] });
15766
+ $[22] = open;
15767
+ $[23] = t11;
15768
+ $[24] = t13;
15769
+ $[25] = t14;
15770
+ } else {
15771
+ t14 = $[25];
15772
+ }
15773
+ let t15;
15774
+ let t16;
15775
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
15776
+ t15 = /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-2xl mb-4", children: "Preview Local Changes" });
15777
+ t16 = /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-4", children: "These are the local changes that will be applied to the form." });
15778
+ $[26] = t15;
15779
+ $[27] = t16;
15780
+ } else {
15781
+ t15 = $[26];
15782
+ t16 = $[27];
15783
+ }
15784
+ let t17;
15785
+ if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
15786
+ t17 = {
15787
+ maxHeight: 520,
15788
+ overflow: "auto"
15789
+ };
15790
+ $[28] = t17;
15791
+ } else {
15792
+ t17 = $[28];
15793
+ }
15794
+ const t18 = properties;
15795
+ let t19;
15796
+ if ($[29] !== localChangesData || $[30] !== t18) {
15797
+ t19 = /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { children: [
15798
+ t15,
15799
+ t16,
15800
+ /* @__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 }) }) })
15801
+ ] });
15802
+ $[29] = localChangesData;
15803
+ $[30] = t18;
15804
+ $[31] = t19;
15805
+ } else {
15806
+ t19 = $[31];
15807
+ }
15808
+ let t20;
15809
+ if ($[32] === Symbol.for("react.memo_cache_sentinel")) {
15810
+ t20 = /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { onClick: () => setPreviewDialogOpen(false), children: "Close" });
15811
+ $[32] = t20;
15812
+ } else {
15813
+ t20 = $[32];
15814
+ }
15815
+ let t21;
15816
+ if ($[33] !== handleApply) {
15817
+ t21 = /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { children: [
15818
+ t20,
15819
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "filled", onClick: () => {
15820
+ handleApply();
15821
+ setPreviewDialogOpen(false);
15822
+ }, children: "Apply changes" })
15823
+ ] });
15824
+ $[33] = handleApply;
15825
+ $[34] = t21;
15826
+ } else {
15827
+ t21 = $[34];
15828
+ }
15829
+ let t22;
15830
+ if ($[35] !== previewDialogOpen || $[36] !== t19 || $[37] !== t21) {
15831
+ t22 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Dialog, { open: previewDialogOpen, onOpenChange: setPreviewDialogOpen, maxWidth: "4xl", children: [
15832
+ t19,
15833
+ t21
15834
+ ] });
15835
+ $[35] = previewDialogOpen;
15836
+ $[36] = t19;
15837
+ $[37] = t21;
15838
+ $[38] = t22;
15839
+ } else {
15840
+ t22 = $[38];
15841
+ }
15842
+ let t23;
15843
+ if ($[39] !== t14 || $[40] !== t22) {
15844
+ t23 = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15845
+ t14,
15846
+ t22
15847
+ ] });
15848
+ $[39] = t14;
15849
+ $[40] = t22;
15850
+ $[41] = t23;
15851
+ } else {
15852
+ t23 = $[41];
15853
+ }
15854
+ return t23;
15855
+ }
15166
15856
  function extractTouchedValues(values, touched) {
15167
15857
  let acc = {};
15168
15858
  if (!touched || typeof touched !== "object") {
@@ -15175,6 +15865,56 @@
15175
15865
  });
15176
15866
  return acc;
15177
15867
  }
15868
+ function getChanges(source, comparison) {
15869
+ const changes = {};
15870
+ if (!source) {
15871
+ return {};
15872
+ }
15873
+ if (!comparison) {
15874
+ return source;
15875
+ }
15876
+ const allKeys = Array.from(/* @__PURE__ */ new Set([...Object.keys(source), ...Object.keys(comparison)]));
15877
+ for (const key of allKeys) {
15878
+ const sourceValue = source[key];
15879
+ const comparisonValue = comparison[key];
15880
+ if (equal(sourceValue, comparisonValue)) {
15881
+ continue;
15882
+ }
15883
+ const sourceHasKey = source && typeof source === "object" && Object.prototype.hasOwnProperty.call(source, key);
15884
+ const comparisonHasKey = comparison && typeof comparison === "object" && Object.prototype.hasOwnProperty.call(comparison, key);
15885
+ if (comparisonHasKey && !sourceHasKey) {
15886
+ changes[key] = void 0;
15887
+ } else if (Array.isArray(sourceValue)) {
15888
+ const comparisonArray = Array.isArray(comparisonValue) ? comparisonValue : [];
15889
+ if (sourceValue.length < comparisonArray.length) {
15890
+ changes[key] = sourceValue;
15891
+ continue;
15892
+ }
15893
+ const changedArray = sourceValue.map((item, index) => {
15894
+ const comparisonItem = comparisonArray[index];
15895
+ if (equal(item, comparisonItem)) {
15896
+ return null;
15897
+ }
15898
+ if (isObject(item) && item && isObject(comparisonItem) && comparisonItem) {
15899
+ const nestedChanges = getChanges(item, comparisonItem);
15900
+ return Object.keys(nestedChanges).length > 0 ? nestedChanges : item;
15901
+ }
15902
+ return item;
15903
+ });
15904
+ if (changedArray.some((item) => item !== null) || sourceValue.length > comparisonArray.length) {
15905
+ changes[key] = changedArray;
15906
+ }
15907
+ } else if (isObject(sourceValue) && sourceValue && isObject(comparisonValue) && comparisonValue) {
15908
+ const nestedChanges = getChanges(sourceValue, comparisonValue);
15909
+ if (Object.keys(nestedChanges).length > 0) {
15910
+ changes[key] = nestedChanges;
15911
+ }
15912
+ } else {
15913
+ changes[key] = sourceValue;
15914
+ }
15915
+ }
15916
+ return changes;
15917
+ }
15178
15918
  function EntityForm({
15179
15919
  path,
15180
15920
  fullIdPath,
@@ -15250,6 +15990,12 @@
15250
15990
  const [entityIdError, setEntityIdError] = React.useState(false);
15251
15991
  const [savingError, setSavingError] = React.useState();
15252
15992
  const autoSave = collection.formAutoSave && !collection.customId;
15993
+ const baseInitialValues = React.useMemo(() => getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs), [authController, collection, path, status, entity, customizationController.propertyConfigs]);
15994
+ const localChangesDataRaw = React.useMemo(() => entityId ? getEntityFromCache(path + "/" + entityId) : getEntityFromCache(path + "#new"), [entityId, path]);
15995
+ const [localChangesCleared, setLocalChangesCleared] = React.useState(false);
15996
+ const localChangesBackup = getLocalChangesBackup(collection);
15997
+ const autoApplyLocalChanges = localChangesBackup === "auto_apply";
15998
+ const manualApplyLocalChanges = localChangesBackup === "manual_apply";
15253
15999
  const onSubmit = (values, formexController) => {
15254
16000
  if (mustSetCustomId && !entityId) {
15255
16001
  console.error("Missing custom Id");
@@ -15280,20 +16026,30 @@
15280
16026
  formexController.setSubmitting(false);
15281
16027
  });
15282
16028
  };
15283
- const baseInitialValues = getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs);
15284
- const initialValues = initialDirtyValues ? mergeDeep(baseInitialValues, initialDirtyValues) : baseInitialValues;
15285
- const initialDirty = Boolean(initialDirtyValues) && initialDirtyValues && Object.keys(initialDirtyValues).length > 0;
16029
+ const [initialValues_0, initialDirty_0] = React.useMemo(() => {
16030
+ const initialValuesWithLocalChanges = autoApplyLocalChanges && localChangesDataRaw ? mergeDeep(baseInitialValues, localChangesDataRaw) : baseInitialValues;
16031
+ const initialValues = initialDirtyValues ? mergeDeep(initialValuesWithLocalChanges, initialDirtyValues) : initialValuesWithLocalChanges;
16032
+ const initialDirty = Boolean(initialDirtyValues) && initialDirtyValues && Object.keys(initialDirtyValues).length > 0;
16033
+ return [initialValues, initialDirty];
16034
+ }, [autoApplyLocalChanges, localChangesDataRaw, baseInitialValues, initialDirtyValues]);
16035
+ const localChangesData = React.useMemo(() => {
16036
+ if (!localChangesDataRaw) {
16037
+ return void 0;
16038
+ }
16039
+ return getChanges(localChangesDataRaw, initialValues_0);
16040
+ }, [localChangesDataRaw, initialValues_0]);
16041
+ const hasLocalChanges = !localChangesCleared && localChangesData && Object.keys(localChangesData).length > 0;
15286
16042
  const formex$1 = formexProp ?? formex.useCreateFormex({
15287
- initialValues,
15288
- initialDirty,
15289
- initialTouched: initialDirtyValues ? formex.flattenKeys(initialDirtyValues).reduce((previousValue, currentValue) => ({
16043
+ initialValues: initialValues_0,
16044
+ initialDirty: initialDirty_0,
16045
+ initialTouched: initialDirtyValues ? flattenKeys(initialDirtyValues).reduce((previousValue, currentValue) => ({
15290
16046
  ...previousValue,
15291
16047
  [currentValue]: true
15292
16048
  }), {}) : {},
15293
16049
  onSubmit,
15294
16050
  onReset: () => {
15295
16051
  clearDirtyCache();
15296
- onValuesModified?.(false);
16052
+ onValuesModified?.(false, initialValues_0);
15297
16053
  },
15298
16054
  onValuesChangeDeferred: (values_0, controller) => {
15299
16055
  const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
@@ -15352,14 +16108,16 @@
15352
16108
  }, [snackbarController]);
15353
16109
  function clearDirtyCache() {
15354
16110
  if (status === "new" || status === "copy") {
16111
+ removeEntityFromMemoryCache(path + "#new");
15355
16112
  removeEntityFromCache(path + "#new");
15356
16113
  } else {
16114
+ removeEntityFromMemoryCache(path + "/" + entityId);
15357
16115
  removeEntityFromCache(path + "/" + entityId);
15358
16116
  }
15359
16117
  }
15360
16118
  const onSaveSuccess = (updatedEntity) => {
15361
16119
  clearDirtyCache();
15362
- onValuesModified?.(false);
16120
+ onValuesModified?.(false, updatedEntity.values);
15363
16121
  if (!autoSave) snackbarController.open({
15364
16122
  type: "success",
15365
16123
  message: `${collection.singularName ?? collection.name}: Saved correctly`
@@ -15519,7 +16277,7 @@
15519
16277
  }, [doOnIdUpdate]);
15520
16278
  React.useEffect(() => {
15521
16279
  if (!autoSave) {
15522
- onValuesModified?.(modified);
16280
+ onValuesModified?.(modified, formex$1.values);
15523
16281
  }
15524
16282
  }, [formex$1.dirty]);
15525
16283
  const modified = formex$1.dirty;
@@ -15616,7 +16374,10 @@
15616
16374
  values: baseInitialValues
15617
16375
  }), noValidate: true, className: ui.cls("flex-1 flex flex-row w-full overflow-y-auto justify-center", className), children: [
15618
16376
  /* @__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: [
15619
- 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" }) }) }),
16377
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row gap-4 self-end sticky top-4 z-10", children: [
16378
+ 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) }),
16379
+ formex$1.dirty ? /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "There are local unsaved changes", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", 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", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest" }) }) })
16380
+ ] }),
15620
16381
  formView
15621
16382
  ] }) }),
15622
16383
  dialogActions
@@ -20426,7 +21187,7 @@
20426
21187
  /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", children: "So empty..." }),
20427
21188
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { color: "primary", variant: "outlined", onClick: onNewClick, className: "mt-4", children: [
20428
21189
  /* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, {}),
20429
- "Create your first entity"
21190
+ "Create your first entry"
20430
21191
  ] })
20431
21192
  ] }) : /* @__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}`),
20432
21193
  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}`),
@@ -23085,6 +23846,7 @@
23085
23846
  function createFormexStub(values) {
23086
23847
  const errorMessage = "You are in a read-only context. You cannot modify the formex controller.";
23087
23848
  return {
23849
+ debugId: "",
23088
23850
  values,
23089
23851
  initialValues: values,
23090
23852
  touched: {},
@@ -23099,6 +23861,9 @@
23099
23861
  setValues: () => {
23100
23862
  throw new Error(errorMessage);
23101
23863
  },
23864
+ setTouched(touched) {
23865
+ throw new Error(errorMessage);
23866
+ },
23102
23867
  setFieldValue: () => {
23103
23868
  throw new Error(errorMessage);
23104
23869
  },
@@ -23158,8 +23923,7 @@
23158
23923
  databaseId: props.databaseId,
23159
23924
  useCache: false
23160
23925
  });
23161
- const enableLocalChangesBackup = props.collection.enableLocalChangesBackup !== void 0 ? props.collection.enableLocalChangesBackup : true;
23162
- const initialDirtyValues = entityId ? getEntityFromCache(props.path + "/" + entityId, enableLocalChangesBackup) : getEntityFromCache(props.path + "#new", enableLocalChangesBackup);
23926
+ const initialDirtyValues = entityId ? getEntityFromMemoryCache(props.path + "/" + entityId) : getEntityFromMemoryCache(props.path + "#new");
23163
23927
  const authController = useAuthController();
23164
23928
  const initialStatus = props.copy ? "copy" : entityId ? "existing" : "new";
23165
23929
  const [status, setStatus] = React.useState(initialStatus);
@@ -23318,6 +24082,7 @@
23318
24082
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-16" })
23319
24083
  ] }) }) : null;
23320
24084
  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) => {
24085
+ console.log("333 EntityEditView onEntityChange:", entity_0);
23321
24086
  setUsedEntity(entity_0);
23322
24087
  formProps?.onEntityChange?.(entity_0);
23323
24088
  }, onStatusChange: (status_0) => {
@@ -23340,7 +24105,12 @@
23340
24105
  const shouldShowTopBar = Boolean(barActions) || hasAdditionalViews;
23341
24106
  let result = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col h-full w-full bg-white dark:bg-surface-900", children: [
23342
24107
  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: [
23343
- barActions,
24108
+ barActions?.({
24109
+ path: fullIdPath ?? path,
24110
+ entityId,
24111
+ values: formContext?.values ?? usedEntity?.values ?? {},
24112
+ status
24113
+ }),
23344
24114
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow" }),
23345
24115
  pluginActionsTop,
23346
24116
  globalLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "self-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CircularProgress, { size: "small" }) }),
@@ -23443,9 +24213,14 @@
23443
24213
  if (!props || !collection) {
23444
24214
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full" });
23445
24215
  }
23446
- 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: [
24216
+ 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: ({
24217
+ status,
24218
+ values
24219
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
23447
24220
  /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "self-center", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, { size: "small" }) }),
23448
24221
  allowFullScreen && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "self-center", onClick: () => {
24222
+ const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
24223
+ saveEntityToMemoryCache(key, values);
23449
24224
  if (entityId) navigate(location.pathname);
23450
24225
  else navigate(location.pathname + "#new");
23451
24226
  }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.OpenInFullIcon, { size: "small" }) })
@@ -26225,6 +27000,7 @@
26225
27000
  exports2.getIdIcon = getIdIcon;
26226
27001
  exports2.getLabelOrConfigFrom = getLabelOrConfigFrom;
26227
27002
  exports2.getLastSegment = getLastSegment;
27003
+ exports2.getLocalChangesBackup = getLocalChangesBackup;
26228
27004
  exports2.getPropertiesWithPropertiesOrder = getPropertiesWithPropertiesOrder;
26229
27005
  exports2.getPropertyInPath = getPropertyInPath;
26230
27006
  exports2.getRandomId = getRandomId;
@@ -26239,6 +27015,7 @@
26239
27015
  exports2.isEnumValueDisabled = isEnumValueDisabled;
26240
27016
  exports2.isHidden = isHidden;
26241
27017
  exports2.isObject = isObject;
27018
+ exports2.isPlainObject = isPlainObject;
26242
27019
  exports2.isPropertyBuilder = isPropertyBuilder;
26243
27020
  exports2.isReadOnly = isReadOnly;
26244
27021
  exports2.isReferenceProperty = isReferenceProperty;