All files / json-crdt-peritext-ui/events PeritextEventTarget.ts

75% Statements 24/32
57.89% Branches 11/19
80% Functions 8/10
73.33% Lines 22/30

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 1125x                                     5x   5x 324x   324x           5082x 5082x 5082x 5082x       5082x 5082x 5082x       210x                       612x 582x 30x       30x         4152x                                                     6x 6x           102x 102x                    
import {SubscriptionEventTarget} from '../../util/events/TypedEventTarget';
import type {
  PeritextEventDetailMap,
  CursorDetail,
  FormatDetail,
  DeleteDetail,
  MarkerDetail,
  BufferDetail,
  SelectionMoveInstruction,
} from './types';
 
export type PeritextEventMap = {
  [K in keyof PeritextEventDetailMap]: CustomEvent<PeritextEventDetailMap[K]>;
};
 
export type PeritextEventHandlerMap = {
  [K in keyof PeritextEventDetailMap]: (event: CustomEvent<PeritextEventDetailMap[K]>) => void;
};
 
let __id = 0;
 
export class PeritextEventTarget extends SubscriptionEventTarget<PeritextEventMap> {
  public readonly id: number = __id++;
 
  public defaults: Partial<PeritextEventHandlerMap> = {};
 
  public dispatch<K extends keyof Omit<PeritextEventDetailMap, 'change'>>(
    type: K,
    detail: Omit<PeritextEventDetailMap, 'change'>[K],
  ): void {
    const event = new CustomEvent<PeritextEventDetailMap[K]>(type, {detail});
    this.dispatchEvent(event);
    if (!event.defaultPrevented) this.defaults[type]?.(event);
    this.change(event);
  }
 
  public change(ev?: CustomEvent<any>): void {
    const event = new CustomEvent<PeritextEventDetailMap['change']>('change', {detail: {ev}});
    this.dispatchEvent(event);
    if (!event.defaultPrevented) this.defaults.change?.(event);
  }
 
  public insert(text: string): void {
    this.dispatch('insert', {text});
  }
 
  public delete(len: number, unit?: SelectionMoveInstruction[1]): void;
  public delete(
    edge: SelectionMoveInstruction[0],
    unit: SelectionMoveInstruction[1],
    len?: SelectionMoveInstruction[2],
    collapse?: SelectionMoveInstruction[3],
  ): void;
  public delete(detail?: DeleteDetail): void;
  public delete(a: any = {}, b?: any, len?: any, collapse?: any): void {
    if (typeof a === 'number') {
      this.dispatch('delete', {move: [['focus', b ?? 'char', a]]});
    } else Iif (typeof a === 'string') {
      const move: SelectionMoveInstruction[] = [[a as SelectionMoveInstruction[0], b, len, collapse]];
      this.dispatch('delete', {move});
    } else {
      this.dispatch('delete', a);
    }
  }
 
  public cursor(detail: CursorDetail): void {
    this.dispatch('cursor', detail);
  }
 
  public move(
    edge: SelectionMoveInstruction[0],
    unit: SelectionMoveInstruction[1],
    len?: SelectionMoveInstruction[2],
    collapse?: SelectionMoveInstruction[3],
  ): void;
  public move(move?: CursorDetail['move'], at?: CursorDetail['at']): void;
  public move(a?: any, b?: any, len?: any, collapse?: any): void {
    if (typeof a === 'string') {
      const move: SelectionMoveInstruction[] = [[a as SelectionMoveInstruction[0], b, len, collapse]];
      this.cursor({move});
    } else {
      this.cursor({move: a, at: b});
    }
  }
 
  public format(type: FormatDetail['type'], behavior?: FormatDetail['behavior'], data?: FormatDetail['data']): void;
  public format(detail: FormatDetail): void;
  public format(
    a: FormatDetail | FormatDetail['type'],
    behavior?: FormatDetail['behavior'],
    data?: FormatDetail['data'],
  ): void {
    const detail: FormatDetail =
      typeof a === 'object' && !Array.isArray(a) ? (a as FormatDetail) : ({type: a, behavior, data} as FormatDetail);
    this.dispatch('format', detail);
  }
 
  public marker(action: MarkerDetail['action'], type: MarkerDetail['type'], data?: MarkerDetail['data']): void;
  public marker(detail: MarkerDetail): void;
  public marker(a: MarkerDetail | MarkerDetail['action'], b?: MarkerDetail['type'], c?: MarkerDetail['data']): void {
    const detail: MarkerDetail = typeof a === 'object' ? a : {action: a, type: b, data: c};
    this.dispatch('marker', detail);
  }
 
  public buffer(action: BufferDetail['action'], format?: BufferDetail['format']): void;
  public buffer(detail: BufferDetail): void;
  public buffer(a: BufferDetail | BufferDetail['action'], b?: BufferDetail['format']): void {
    const detail: BufferDetail = typeof a === 'object' ? a : {action: a, format: b};
    this.dispatch('buffer', detail);
  }
}