Skip to content

Commit d2ad754

Browse files
committed
feat(json-crdt-peritext-ui): 🎸 implement multi-cursor block-merge
1 parent d88ad48 commit d2ad754

File tree

5 files changed

+36
-1
lines changed

5 files changed

+36
-1
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,18 @@ export class Editor<T = string> implements Printable {
912912
this.updMarkerAt(cursor.start, type, data, slices);
913913
}
914914

915+
public delMarker(): void {
916+
const markerPoints = new Set<MarkerOverlayPoint<T>>();
917+
for (let i = this.cursors0(), cursor = i(); cursor; cursor = i()) {
918+
const markerPoint = this.txt.overlay.getOrNextLowerMarker(cursor.start);
919+
if (markerPoint) markerPoints.add(markerPoint);
920+
}
921+
for (const markerPoint of markerPoints) {
922+
const boundary = markerPoint.marker.boundary();
923+
this.delRange(boundary);
924+
}
925+
}
926+
915927
// ---------------------------------------------------------- export / import
916928

917929
public export(range: Range<T>): ViewRange {
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1+
import {Anchor} from '../rga/constants';
12
import {PersistedSlice} from './PersistedSlice';
3+
import type {Range} from '../rga/Range';
24

35
/**
46
* Represents a block split in the text, i.e. it is a *marker* that shows
57
* where a block was split. Markers also insert one "\n" new line character.
68
* Both marker ends are attached to the "before" anchor fo the "\n" new line
79
* character, i.e. it is *collapsed* to the "before" anchor.
810
*/
9-
export class MarkerSlice<T = string> extends PersistedSlice<T> {}
11+
export class MarkerSlice<T = string> extends PersistedSlice<T> {
12+
/**
13+
* Returns the {@link Range} which exactly contains the block boundary of this
14+
* marker.
15+
*/
16+
public boundary(): Range<T> {
17+
const start = this.start;
18+
const end = start.clone();
19+
end.anchor = Anchor.After;
20+
return this.txt.range(start, end);
21+
}
22+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ export class PeritextEventDefaults implements PeritextEventHandlerMap {
200200
if (type !== void 0) editor.updMarker(type, data);
201201
break;
202202
}
203+
case 'del': {
204+
editor.delMarker();
205+
break;
206+
}
203207
}
204208
this.undo?.capture();
205209
};

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ export const TopToolbar: React.FC<TopToolbarProps> = ({ctx}) => {
7474
{button('Clear', () => {
7575
ctx.dom?.et.format({behavior: 'clear'});
7676
})}
77+
{button('Delete block split', () => {
78+
ctx.dom?.et.marker({action: 'del'});
79+
})}
7780
<ButtonSeparator />
7881
{blockGroupButtom(CommonSliceType.p, 'Paragraph')}
7982
{blockGroupButtom(CommonSliceType.blockquote, 'Blockquote')}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ export const TopToolbar: React.FC<TopToolbarProps> = ({ctx}) => {
7777
{button('Clear', () => {
7878
ctx.dom?.et.format({behavior: 'clear'});
7979
})}
80+
{button('Delete block split', () => {
81+
ctx.dom?.et.marker({action: 'del'});
82+
})}
8083
<ButtonSeparator />
8184
{blockGroupButton(CommonSliceType.p, 'Paragraph')}
8285
{blockGroupButton(CommonSliceType.blockquote, 'Blockquote')}

0 commit comments

Comments
 (0)