Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | 4x 4x 300x 300x 300x 300x 210x 210x 300x 612x 612x 612x 18x 18x 612x 300x 3114x 3114x 3114x 3114x 2562x 2562x 30x 30x 30x 30x 30x 30x 2502x 1674x 1674x 1674x 828x 828x 828x 2562x 552x 552x 138x 138x 414x 402x 402x 24x 12x 402x 12x 12x 12x 300x 6x 6x 6x 6x 6x 6x 6x 300x | import {CursorAnchor} from '../../json-crdt-extensions/peritext/slice/constants'; import type {Peritext} from '../../json-crdt-extensions/peritext'; import type {EditorSlices} from '../../json-crdt-extensions/peritext/editor/EditorSlices'; import type {PeritextEventHandlerMap, PeritextEventTarget} from './PeritextEventTarget'; import type * as events from './types'; /** * Implementation of default handlers for Peritext events, such as "insert", * "delete", "cursor", etc. These implementations are used by the * {@link PeritextEventTarget} to provide default behavior for each event type. * If `event.preventDefault()` is called on a Peritext event, the default handler * will not be executed. */ export class PeritextEventDefaults implements PeritextEventHandlerMap { public constructor( protected readonly txt: Peritext, protected readonly et: PeritextEventTarget, ) {} public readonly change = (event: CustomEvent<events.ChangeDetail>) => {}; public readonly insert = (event: CustomEvent<events.InsertDetail>) => { const text = event.detail.text; this.txt.editor.insert(text); }; public readonly delete = (event: CustomEvent<events.DeleteDetail>) => { const {len = -1, unit = 'char', at} = event.detail; const editor = this.txt.editor; if (at !== undefined) { const point = editor.point(at); editor.cursor.set(point); } editor.delete(len, unit); }; public readonly cursor = (event: CustomEvent<events.CursorDetail>) => { const {at, edge, len, unit} = event.detail; const txt = this.txt; const editor = txt.editor; // If `at` is specified, it represents the absolute position. We move the // cursor to that position, and leave only one active cursor. All other // are automatically removed when `editor.cursor` getter is accessed. if ((typeof at === 'number' && at >= 0) || typeof at === 'object') { const point = editor.point(at); switch (edge) { case 'focus': case 'anchor': { const cursor = editor.cursor; cursor.setEndpoint(point, edge === 'focus' ? 0 : 1); Iif (cursor.isCollapsed()) { const start = cursor.start; start.refAfter(); cursor.set(start); } break; } case 'new': { editor.addCursor(txt.range(point)); break; } // both default: { // Select a range from the "at" position to the specified length. if (!!len && typeof len === 'number') { const point2 = editor.skip(point, len, unit ?? 'char'); const range = txt.rangeFromPoints(point, point2); // Sorted range. editor.cursor.set(range.start, range.end, len < 0 ? CursorAnchor.End : CursorAnchor.Start); } // Set caret (a collapsed cursor) at the specified position. else { point.refAfter(); editor.cursor.set(point); if (unit) editor.select(unit); } } } return; } // If `edge` is specified. const isSpecificEdgeSelected = edge === 'focus' || edge === 'anchor'; if (isSpecificEdgeSelected) { editor.move(len ?? 0, unit ?? 'char', edge === 'focus' ? 0 : 1, false); return; } // If `len` is specified. if (len) { const cursor = editor.cursor; if (cursor.isCollapsed()) editor.move(len, unit ?? 'char'); else { if (len > 0) cursor.collapseToEnd(); else cursor.collapseToStart(); } return; } // If `unit` is specified. if (unit) { editor.select(unit); return; } }; public readonly format = (event: CustomEvent<events.FormatDetail>) => { const {type, store = 'saved', behavior = 'one', data} = event.detail; const editor = this.txt.editor; const slices: EditorSlices = store === 'saved' ? editor.saved : store === 'extra' ? editor.extra : editor.local; switch (behavior) { case 'many': { Iif (type === undefined) throw new Error('TYPE_REQUIRED'); slices.insStack(type, data); break; } case 'one': { Iif (type === undefined) throw new Error('TYPE_REQUIRED'); editor.toggleExclFmt(type, data, slices); break; } case 'erase': { if (type === undefined) editor.eraseFormatting(slices); else slices.insErase(type, data); break; } case 'clear': { editor.clearFormatting(slices); break; } } }; public readonly marker = (event: CustomEvent<events.MarkerDetail>) => { const {action, type, data} = event.detail; switch (action) { case 'ins': { this.txt.editor.split(type, data); break; } case 'tog': { const marker = this.txt.overlay.getOrNextLowerMarker(this.txt.editor.cursor.start); Iif (marker) { marker.marker.update({type}); } console.log('togggling..', marker); break; } } }; } |