Skip to content

Commit 6d003de

Browse files
committed
fix(json-crdt-peritext-ui): 🐛 make multi-cursor work again
1 parent 4c92831 commit 6d003de

File tree

6 files changed

+29
-13
lines changed

6 files changed

+29
-13
lines changed

src/json-crdt-extensions/peritext/editor/Editor.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ export class Editor<T = string> implements Printable {
115115
};
116116
}
117117

118+
public mainCursor(): Cursor<T> | undefined {
119+
return this.cursors0()();
120+
}
121+
118122
public cursors() {
119123
return new UndefEndIter(this.cursors0());
120124
}

src/json-crdt-peritext-ui/events/defaults/PeritextEventDefaults.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,11 @@ export class PeritextEventDefaults implements PeritextEventHandlerMap {
111111

112112
public readonly change = (event: CustomEvent<events.ChangeDetail>) => {};
113113

114-
public readonly insert = (event: CustomEvent<events.InsertDetail>) => {
115-
const text = event.detail.text;
116-
const editor = this.txt.editor;
117-
editor.insert(text);
114+
public readonly insert = ({detail}: CustomEvent<events.InsertDetail>) => {
115+
const {move, text} = detail;
116+
const set = [...this.getSelSet(detail)];
117+
if (move) this.moveSelSet(set, detail);
118+
this.txt.editor.insert(text, set);
118119
this.undo?.capture();
119120
};
120121

@@ -132,7 +133,10 @@ export class PeritextEventDefaults implements PeritextEventHandlerMap {
132133
range.set(start);
133134
}
134135
}
135-
if (deleted) return;
136+
if (deleted) {
137+
this.undo?.capture();
138+
return;
139+
}
136140
if (move) this.moveSelSet(set, detail);
137141
for (const range of set) {
138142
editor.delRange(range);
@@ -141,6 +145,7 @@ export class PeritextEventDefaults implements PeritextEventHandlerMap {
141145
start.refAfter();
142146
range.set(start);
143147
}
148+
this.undo?.capture();
144149
};
145150

146151
public readonly cursor = ({detail}: CustomEvent<events.CursorDetail>) => {
@@ -155,7 +160,6 @@ export class PeritextEventDefaults implements PeritextEventHandlerMap {
155160
break;
156161
}
157162
} else {
158-
editor.delCursors();
159163
for (const range of set) {
160164
editor.cursor.setRange(range);
161165
break;

src/json-crdt-peritext-ui/events/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,17 @@ export type SelectionMoveInstruction = [
120120
/**
121121
* Event dispatched to insert text into the document.
122122
*/
123-
export interface InsertDetail {
123+
export interface InsertDetail extends SelectionDetailPart, SelectionMoveDetailPart {
124124
text: string;
125125
}
126126

127127
/**
128-
* Event dispatched to delete text from the document.
128+
* Event dispatched to delete text from the document. The deletion happens by
129+
* collapsing all selections to a single point and deleting the text and any
130+
* annotations contained in the selections. If all selections are already
131+
* collapsed, the moves specified in `move` are performed and all selections
132+
* are collapsed to a single point, while deleting all text and any annotations
133+
* contained in the selections.
129134
*/
130135
export interface DeleteDetail extends SelectionDetailPart, SelectionMoveDetailPart {}
131136

src/json-crdt-peritext-ui/plugins/minimal/TopToolbar/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export const TopToolbar: React.FC<TopToolbarProps> = ({ctx}) => {
1818

1919
if (!ctx.dom) return null;
2020

21-
const [complete] = editor.hasCursor() ? peritext.overlay.stat(editor.cursor) : [new Set()];
21+
const cursor = editor.mainCursor();
22+
const [complete] = cursor ? peritext.overlay.stat(cursor) : [new Set()];
2223

2324
const inlineGroupButton = (type: string | number, name: React.ReactNode) => (
2425
<Button

src/json-crdt-peritext-ui/plugins/toolbar/TopToolbar/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ export const TopToolbar: React.FC<TopToolbarProps> = ({ctx}) => {
2121

2222
if (!ctx.dom) return null;
2323

24-
const [complete] = editor.hasCursor() ? peritext.overlay.stat(editor.cursor) : [new Set()];
24+
const cursor = editor.mainCursor();
25+
const [complete] = cursor ? peritext.overlay.stat(cursor) : [new Set()];
2526

2627
const inlineGroupButton = (type: string | number, name: React.ReactNode) => (
2728
<Button

src/json-crdt-peritext-ui/plugins/toolbar/state/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,13 @@ export class ToolbarState implements UiLifeCycles {
7575
const {activeLeafBlockId$, txt} = this;
7676
const {overlay, editor} = txt;
7777
const value = activeLeafBlockId$.getValue();
78-
if (editor.cursorCard() !== 1 || !editor.cursor.isCollapsed()) {
78+
const cardinality = editor.cursorCard();
79+
if (cardinality !== 1 || (cardinality === 1 && !editor.mainCursor()?.isCollapsed())) {
7980
if (value) activeLeafBlockId$.next(null);
8081
return;
8182
}
82-
const focus = editor.cursor.focus();
83-
const marker = overlay.getOrNextLowerMarker(focus);
83+
const focus = editor.mainCursor()?.focus();
84+
const marker = focus ? overlay.getOrNextLowerMarker(focus) : void 0;
8485
const markerId = marker?.marker.start.id ?? txt.str.id;
8586
const doSet = !value || compare(value, markerId) !== 0;
8687
if (doSet) activeLeafBlockId$.next(markerId);

0 commit comments

Comments
 (0)