@open-mercato/ui 0.6.5-develop.4703.1.59a086a9ee → 0.6.5-develop.4718.1.56d834bb34

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.
@@ -261,6 +261,9 @@ function normalizeDirtySnapshotValue(value) {
261
261
  function createDirtySnapshot(source) {
262
262
  return JSON.stringify(normalizeDirtySnapshotValue(source) ?? {});
263
263
  }
264
+ function createDirtyValueSnapshot(value) {
265
+ return JSON.stringify(normalizeDirtySnapshotValue(value) ?? null);
266
+ }
264
267
  const FIELDSET_ICON_COMPONENTS = {
265
268
  layers: Layers,
266
269
  tag: Tag,
@@ -555,6 +558,8 @@ function CrudForm({
555
558
  const clearDirtyState = React.useCallback((snapshotSource) => {
556
559
  const source = snapshotSource ?? valuesRef.current;
557
560
  dirtyBaselineSnapshotRef.current = createDirtySnapshot(source);
561
+ dirtyBaselineValuesRef.current = { ...source };
562
+ userEditedFieldIdsRef.current.clear();
558
563
  isDirtyRef.current = false;
559
564
  setHasUnsavedChanges(false);
560
565
  }, []);
@@ -1651,16 +1656,30 @@ function CrudForm({
1651
1656
  lastErrorFieldRef.current = fieldId;
1652
1657
  }
1653
1658
  }, [errors, formId]);
1659
+ const updateEditedFieldMarker = React.useCallback((id, nextValue, baselineSource = dirtyBaselineValuesRef.current) => {
1660
+ if (baselineSource && createDirtyValueSnapshot(baselineSource[id]) === createDirtyValueSnapshot(nextValue)) {
1661
+ userEditedFieldIdsRef.current.delete(id);
1662
+ return;
1663
+ }
1664
+ userEditedFieldIdsRef.current.add(id);
1665
+ }, []);
1654
1666
  const setValue = React.useCallback((id, nextValue) => {
1655
1667
  let nextData = null;
1656
1668
  let nextDirty = null;
1669
+ const currentValue = valuesRef.current[id];
1670
+ if (!Object.is(currentValue, nextValue)) {
1671
+ updateEditedFieldMarker(id, nextValue);
1672
+ }
1657
1673
  setValues((prev) => {
1658
1674
  if (Object.is(prev[id], nextValue)) return prev;
1675
+ const baselineSource = dirtyBaselineValuesRef.current ?? prev;
1676
+ updateEditedFieldMarker(id, nextValue, baselineSource);
1659
1677
  nextData = { ...prev, [id]: nextValue };
1660
1678
  valuesRef.current = nextData;
1661
1679
  if (!(embedded && !trackDirtyWhenEmbedded)) {
1662
1680
  const baseline = dirtyBaselineSnapshotRef.current ?? createDirtySnapshot(prev);
1663
1681
  dirtyBaselineSnapshotRef.current = baseline;
1682
+ dirtyBaselineValuesRef.current = baselineSource;
1664
1683
  nextDirty = createDirtySnapshot(nextData) !== baseline;
1665
1684
  }
1666
1685
  return nextData;
@@ -1728,7 +1747,7 @@ function CrudForm({
1728
1747
  }).catch((err) => {
1729
1748
  console.error("[CrudForm] Error in onFieldChange:", err);
1730
1749
  });
1731
- }, [embedded, extendedInjectionEventsEnabled, flash, t, trackDirtyWhenEmbedded, translateValidationMessage, triggerInjectionEvent]);
1750
+ }, [embedded, extendedInjectionEventsEnabled, flash, t, trackDirtyWhenEmbedded, translateValidationMessage, triggerInjectionEvent, updateEditedFieldMarker]);
1732
1751
  const onBlurRequest = React.useCallback((fieldId) => {
1733
1752
  void validateFieldOnBlur(fieldId);
1734
1753
  }, [validateFieldOnBlur]);
@@ -1752,6 +1771,8 @@ function CrudForm({
1752
1771
  );
1753
1772
  const appliedInitialValuesSnapshotRef = React.useRef(void 0);
1754
1773
  const dirtyBaselineSnapshotRef = React.useRef(void 0);
1774
+ const dirtyBaselineValuesRef = React.useRef(void 0);
1775
+ const userEditedFieldIdsRef = React.useRef(/* @__PURE__ */ new Set());
1755
1776
  React.useLayoutEffect(() => {
1756
1777
  if (!initialValues) return;
1757
1778
  const snapshot = JSON.stringify({
@@ -1767,8 +1788,14 @@ function CrudForm({
1767
1788
  let hadUnsavedEdits = false;
1768
1789
  setValues((prev) => {
1769
1790
  const priorBaseline = dirtyBaselineSnapshotRef.current;
1770
- hadUnsavedEdits = priorBaseline !== void 0 && createDirtySnapshot(prev) !== priorBaseline;
1771
- const merged = { ...prev, ...initialValues };
1791
+ const editedFieldIds = userEditedFieldIdsRef.current;
1792
+ hadUnsavedEdits = editedFieldIds.size > 0 || priorBaseline !== void 0 && createDirtySnapshot(prev) !== priorBaseline;
1793
+ const merged = { ...prev };
1794
+ const mergedRecord = merged;
1795
+ for (const [key, value] of Object.entries(initialValues)) {
1796
+ if (editedFieldIds.has(key)) continue;
1797
+ mergedRecord[key] = value;
1798
+ }
1772
1799
  for (const definition of injectedFieldDefinitions) {
1773
1800
  if (merged[definition.id] !== void 0) continue;
1774
1801
  const extracted = readByDotPath(initialRecord, definition.id);
@@ -1799,6 +1826,7 @@ function CrudForm({
1799
1826
  });
1800
1827
  if (mergedValues && !hadUnsavedEdits) {
1801
1828
  dirtyBaselineSnapshotRef.current = createDirtySnapshot(mergedValues);
1829
+ dirtyBaselineValuesRef.current = { ...mergedValues };
1802
1830
  }
1803
1831
  if (!extendedInjectionEventsEnabled || !mergedValues) return;
1804
1832
  let cancelled = false;
@@ -1813,6 +1841,7 @@ function CrudForm({
1813
1841
  if (cancelled || !transformed) return;
1814
1842
  if (isDirtyRef.current) return;
1815
1843
  dirtyBaselineSnapshotRef.current = createDirtySnapshot(transformed);
1844
+ dirtyBaselineValuesRef.current = { ...transformed };
1816
1845
  setValues(transformed);
1817
1846
  } catch (err) {
1818
1847
  console.error("[CrudForm] Error in transformDisplayData:", err);
@@ -1866,6 +1895,7 @@ function CrudForm({
1866
1895
  });
1867
1896
  if (mergedValues) {
1868
1897
  dirtyBaselineSnapshotRef.current = createDirtySnapshot(mergedValues);
1898
+ dirtyBaselineValuesRef.current = { ...mergedValues };
1869
1899
  }
1870
1900
  }, [isLoading, initialValuesHasId, cfDefinitions, customEntity]);
1871
1901
  const markFormAsClean = React.useCallback((snapshotSource) => {