allozaur/feat/chat form contenteditable (#26717)
* feat: Add contenteditable tokenizer for badge/code-chip chat input * feat: Add source-space undo/redo history for the rich input * feat: Split text glued to a closing code fence onto its own line * feat: Add ChatFormContenteditable rich input renderer * feat : wire the contenteditable into ChatForm with auto-switch gating
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Source-space undo/redo history for the chat-form contenteditable, whose
|
||||
* imperative DOM rebuilds destroy the browser's native undo stack.
|
||||
* Entries record the state BEFORE an edit; edits within `groupWindowMs`
|
||||
* extend the open group so a typing burst undoes as a unit, while
|
||||
* structural edits (paste, mention insert, clear) pass `newGroup`.
|
||||
*/
|
||||
|
||||
export interface SourceHistoryEntry {
|
||||
value: string;
|
||||
caret: number;
|
||||
}
|
||||
|
||||
export class SourceHistory {
|
||||
private undoStack: SourceHistoryEntry[] = [];
|
||||
private redoStack: SourceHistoryEntry[] = [];
|
||||
private lastPush = 0;
|
||||
|
||||
constructor(
|
||||
private limit = 100,
|
||||
private groupWindowMs = 800
|
||||
) {}
|
||||
|
||||
push(entry: SourceHistoryEntry, now: number, newGroup = false): void {
|
||||
if (newGroup || now - this.lastPush >= this.groupWindowMs || this.undoStack.length === 0) {
|
||||
this.undoStack.push(entry);
|
||||
if (this.undoStack.length > this.limit) this.undoStack.shift();
|
||||
}
|
||||
this.lastPush = now;
|
||||
this.redoStack = [];
|
||||
}
|
||||
|
||||
undo(current: SourceHistoryEntry): SourceHistoryEntry | null {
|
||||
const entry = this.undoStack.pop();
|
||||
if (!entry) return null;
|
||||
this.redoStack.push(current);
|
||||
this.lastPush = 0; // the next edit after an undo starts a new group
|
||||
return entry;
|
||||
}
|
||||
|
||||
redo(current: SourceHistoryEntry): SourceHistoryEntry | null {
|
||||
const entry = this.redoStack.pop();
|
||||
if (!entry) return null;
|
||||
this.undoStack.push(current);
|
||||
this.lastPush = 0;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user