fix(table): inline cell edits only save on real changes; no-op clicks can't truncate dates

makeEditable committed unconditionally on blur: clicking into a cell and
away again dirtied the file every time, and on date cells the write-back
was the 10-char truncated picker value — touching a date cell that carried
extra data silently clobbered it. Blur now compares against the value the
input was seeded with and skips the save on no-ops; Escape sets a cancelled
flag and blurs, so discard works even where element removal fires blur.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
SVM0N 2026-07-11 15:42:54 +00:00
parent a40891ac6c
commit 0dab369bfb
2 changed files with 23 additions and 7 deletions

File diff suppressed because one or more lines are too long

View file

@ -141,13 +141,29 @@ export function makeEditable(view: CardView, el: HTMLElement, row: CSVRow, h: st
type: isDate ? "date" : "text"
});
input.focus();
input.focus();
if (!isDate) input.select(); // selecting text is mostly useful for text inputs, dates have a native picker
// Prevent clicks on the input from bubbling up to row/document listeners
input.addEventListener("click", ev => ev.stopPropagation());
input.addEventListener("blur", () => { row[h] = input.value; view.scheduleSave(); el.empty(); el.setText(input.value || "—"); });
input.addEventListener("keydown", ev => { if (ev.key === "Enter") input.blur(); if (ev.key === "Escape") { el.empty(); el.setText(row[h] || "—"); } });
// Commit on blur — but only when the value actually changed from what we
// put into the input. Saving unconditionally meant every click-in/
// click-out dirtied the file (debounced vault write + sync churn), and
// for a date cell the write-back was the 10-char truncated pickerValue —
// silently clobbering any extra data just by touching the cell.
let cancelled = false;
input.addEventListener("blur", () => {
if (!cancelled && input.value !== pickerValue) {
row[h] = input.value;
view.scheduleSave();
}
el.empty();
el.setText((row[h] ?? "") || "—");
});
input.addEventListener("keydown", ev => {
if (ev.key === "Enter") input.blur();
if (ev.key === "Escape") { cancelled = true; input.blur(); }
});
});
}