@prose-reader/enhancer-annotations 1.222.0 → 1.223.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,25 @@
1
1
  import { DestroyableClass } from '@prose-reader/core';
2
- import { SerializableHighlight } from './types';
3
- type HighlightParams = {
4
- selection: Selection;
2
+ import { Annotation } from './types';
3
+ type AnnotationSharedParams = Omit<Annotation, "id" | "cfi"> & {
4
+ selection?: Selection;
5
+ };
6
+ type AnnotateParams = AnnotationSharedParams & {
5
7
  itemIndex: number;
6
- color?: string;
7
- contents?: string[];
8
+ };
9
+ type AnnotateAbsolutePageParams = AnnotationSharedParams & {
10
+ absolutePageIndex: number;
8
11
  };
9
12
  export declare class Commands extends DestroyableClass {
10
13
  private commandSubject;
11
- readonly highlight$: import('rxjs').Observable<{
12
- type: "highlight";
13
- data: HighlightParams;
14
+ readonly annotate$: import('rxjs').Observable<{
15
+ type: "annotate";
16
+ data: (AnnotateParams | AnnotateAbsolutePageParams) & {
17
+ absolutePageIndex?: number;
18
+ };
14
19
  }>;
15
20
  readonly add$: import('rxjs').Observable<{
16
21
  type: "add";
17
- data: SerializableHighlight | SerializableHighlight[];
22
+ data: Annotation | Annotation[];
18
23
  }>;
19
24
  readonly delete$: import('rxjs').Observable<{
20
25
  type: "delete";
@@ -23,7 +28,7 @@ export declare class Commands extends DestroyableClass {
23
28
  readonly update$: import('rxjs').Observable<{
24
29
  type: "update";
25
30
  id: string;
26
- data: Pick<HighlightParams, "color" | "contents">;
31
+ data: Pick<AnnotationSharedParams, "highlightColor" | "notes">;
27
32
  }>;
28
33
  readonly select$: import('rxjs').Observable<{
29
34
  type: "select";
@@ -32,10 +37,11 @@ export declare class Commands extends DestroyableClass {
32
37
  readonly reset$: import('rxjs').Observable<{
33
38
  type: "reset";
34
39
  }>;
35
- highlight: (params: HighlightParams) => void;
36
- add: (data: SerializableHighlight | SerializableHighlight[]) => void;
40
+ annotate: (params: AnnotateParams) => void;
41
+ annotateAbsolutePage: (params: AnnotateAbsolutePageParams) => void;
42
+ add: (data: Annotation | Annotation[]) => void;
37
43
  delete: (id: string) => void;
38
- update: (id: string, data: Pick<HighlightParams, "color" | "contents">) => void;
44
+ update: (id: string, data: Pick<AnnotationSharedParams, "highlightColor" | "notes">) => void;
39
45
  select: (id: string | undefined) => void;
40
46
  reset: () => void;
41
47
  destroy(): void;
@@ -1,15 +1,15 @@
1
1
  import { DestroyableClass, Reader } from '@prose-reader/core';
2
2
  import { BehaviorSubject } from 'rxjs';
3
- import { ProseHighlight } from './Highlight';
4
3
  import { SpineItemHighlights } from './SpineItemHighlights';
4
+ import { RuntimeAnnotation } from './types';
5
5
  export declare class ReaderHighlights extends DestroyableClass {
6
6
  private reader;
7
7
  private highlights;
8
8
  private selectedHighlight;
9
9
  private spineItemHighlights;
10
10
  tap$: SpineItemHighlights["tap$"];
11
- constructor(reader: Reader, highlights: BehaviorSubject<ProseHighlight[]>, selectedHighlight: BehaviorSubject<string | undefined>);
12
- getHighlightsForTarget: (target: EventTarget) => ProseHighlight[];
11
+ constructor(reader: Reader, highlights: BehaviorSubject<RuntimeAnnotation[]>, selectedHighlight: BehaviorSubject<string | undefined>);
12
+ getHighlightsForTarget: (target: EventTarget) => RuntimeAnnotation[];
13
13
  isTargetWithinHighlight: (target: EventTarget) => boolean;
14
- layout(): void;
14
+ layout(): import('rxjs').Observable<((null | undefined)[] | null)[] | null>;
15
15
  }
@@ -1,19 +1,20 @@
1
1
  import { DestroyableClass, Reader, SpineItem } from '@prose-reader/core';
2
2
  import { Observable } from 'rxjs';
3
- import { ProseHighlight } from './Highlight';
3
+ import { RuntimeAnnotation } from './types';
4
4
  export declare class SpineItemHighlight extends DestroyableClass {
5
5
  private spineItem;
6
6
  private containerElement;
7
7
  private reader;
8
- readonly highlight: ProseHighlight;
8
+ readonly highlight: RuntimeAnnotation;
9
9
  private isSelected;
10
10
  private container;
11
11
  readonly tap$: Observable<{
12
12
  event: Event;
13
- highlight: ProseHighlight;
13
+ highlight: RuntimeAnnotation;
14
14
  }>;
15
- constructor(spineItem: SpineItem, containerElement: HTMLElement, reader: Reader, highlight: ProseHighlight, isSelected: Observable<boolean>);
16
- render(): void;
15
+ private resolvedCfi$;
16
+ constructor(spineItem: SpineItem, containerElement: HTMLElement, reader: Reader, highlight: RuntimeAnnotation, isSelected: Observable<boolean>);
17
+ render(): Observable<null | undefined>;
17
18
  isWithinTarget(target: Node): boolean;
18
19
  destroy(): void;
19
20
  }
@@ -1,17 +1,17 @@
1
1
  import { DestroyableClass, Reader, SpineItem } from '@prose-reader/core';
2
2
  import { Observable } from 'rxjs';
3
- import { ProseHighlight } from './Highlight';
4
3
  import { SpineItemHighlight } from './SpineItemHighlight';
4
+ import { RuntimeAnnotation } from './types';
5
5
  export declare class SpineItemHighlights extends DestroyableClass {
6
- private highlights$;
6
+ private annotations$;
7
7
  private spineItem;
8
8
  private reader;
9
9
  private selectedHighlight;
10
10
  private layer;
11
11
  private highlights;
12
12
  readonly tap$: SpineItemHighlight["tap$"];
13
- constructor(highlights$: Observable<ProseHighlight[]>, spineItem: SpineItem, reader: Reader, selectedHighlight: Observable<string | undefined>);
14
- layout(): void;
13
+ constructor(annotations$: Observable<RuntimeAnnotation[]>, spineItem: SpineItem, reader: Reader, selectedHighlight: Observable<string | undefined>);
14
+ layout(): Observable<(null | undefined)[] | null>;
15
15
  getHighlightsForTarget(target: EventTarget): SpineItemHighlight[];
16
16
  destroy(): void;
17
17
  }
@@ -0,0 +1,4 @@
1
+ import { Annotation } from '../types';
2
+ export interface RuntimeAnnotation extends Annotation {
3
+ itemIndex: number;
4
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from './annotationsEnhancer';
2
2
  export * from './types';
3
- export * from './highlights/Highlight';
3
+ export * from './annotations/types';
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { isDefined } from 'reactjrx';
2
- import { Subject, filter, fromEvent, map, share, skip, tap, takeUntil, switchMap, distinctUntilChanged, of, shareReplay, merge, BehaviorSubject, withLatestFrom, debounceTime, mergeMap, forkJoin } from 'rxjs';
2
+ import { Subject, filter, fromEvent, map, share, shareReplay, skip, tap, takeUntil, merge, first, switchMap, distinctUntilChanged, of, forkJoin, defaultIfEmpty, BehaviorSubject, debounceTime, combineLatest } from 'rxjs';
3
3
  import { DestroyableClass } from '@prose-reader/core';
4
4
 
5
5
  class Commands extends DestroyableClass {
6
6
  commandSubject = new Subject();
7
- highlight$ = this.commandSubject.pipe(
8
- filter((command) => command.type === "highlight")
7
+ annotate$ = this.commandSubject.pipe(
8
+ filter((command) => command.type === "annotate")
9
9
  );
10
10
  add$ = this.commandSubject.pipe(
11
11
  filter((command) => command.type === "add")
@@ -22,8 +22,11 @@ class Commands extends DestroyableClass {
22
22
  reset$ = this.commandSubject.pipe(
23
23
  filter((command) => command.type === "reset")
24
24
  );
25
- highlight = (params) => {
26
- this.commandSubject.next({ type: "highlight", data: params });
25
+ annotate = (params) => {
26
+ this.commandSubject.next({ type: "annotate", data: params });
27
+ };
28
+ annotateAbsolutePage = (params) => {
29
+ this.commandSubject.next({ type: "annotate", data: params });
27
30
  };
28
31
  add = (data) => {
29
32
  this.commandSubject.next({ type: "add", data });
@@ -46,44 +49,6 @@ class Commands extends DestroyableClass {
46
49
  }
47
50
  }
48
51
 
49
- class ProseHighlight {
50
- cfi;
51
- endCfi;
52
- itemIndex;
53
- color;
54
- contents;
55
- range;
56
- selectionAsText;
57
- /**
58
- * Unique local ID. This is to ensure unicity
59
- * for duplicate selections
60
- */
61
- id;
62
- constructor(params) {
63
- this.cfi = params.cfi;
64
- this.endCfi = params.endCfi;
65
- this.itemIndex = params.itemIndex;
66
- this.color = params.color;
67
- this.contents = params.contents;
68
- this.id = params.id;
69
- this.selectionAsText = params.selectionAsText;
70
- }
71
- update(params) {
72
- Object.assign(this, params);
73
- return this;
74
- }
75
- toJSON() {
76
- return {
77
- cfi: this.cfi,
78
- endCfi: this.endCfi,
79
- color: this.color,
80
- contents: this.contents,
81
- id: this.id,
82
- selectionAsText: this.selectionAsText
83
- };
84
- }
85
- }
86
-
87
52
  const createElementForRange = (range, container, color) => {
88
53
  const rects = Array.from(range.getClientRects());
89
54
  const lineGroups = /* @__PURE__ */ new Map();
@@ -156,7 +121,10 @@ class SpineItemHighlight extends DestroyableClass {
156
121
  map((event) => ({ event, highlight: this.highlight })),
157
122
  share()
158
123
  );
159
- this.render();
124
+ this.resolvedCfi$ = this.spineItem.loaded$.pipe(
125
+ map(() => this.reader.cfi.resolveCfi({ cfi: this.highlight.cfi })),
126
+ shareReplay({ refCount: true, bufferSize: 1 })
127
+ );
160
128
  this.isSelected.pipe(
161
129
  skip(1),
162
130
  tap((isSelected2) => {
@@ -168,38 +136,47 @@ class SpineItemHighlight extends DestroyableClass {
168
136
  }),
169
137
  takeUntil(this.destroy$)
170
138
  ).subscribe();
139
+ merge(this.resolvedCfi$).pipe(takeUntil(this.destroy$)).subscribe();
171
140
  }
172
141
  container;
173
142
  tap$;
143
+ resolvedCfi$;
174
144
  render() {
175
- this.container.innerHTML = "";
176
- const range = this.highlight.range;
177
- if (!range) {
178
- return;
179
- }
180
- const rectElements = createElementForRange(
181
- range,
182
- this.container,
183
- this.highlight.color ?? "yellow"
145
+ return this.resolvedCfi$.pipe(
146
+ first(),
147
+ map((resolvedCfi) => {
148
+ if (!resolvedCfi || !resolvedCfi.isRange) return void 0;
149
+ const range = resolvedCfi.range;
150
+ this.container.innerHTML = "";
151
+ if (!range) {
152
+ return;
153
+ }
154
+ const rectElements = createElementForRange(
155
+ range,
156
+ this.container,
157
+ this.highlight.highlightColor ?? "yellow"
158
+ );
159
+ rectElements.forEach((elt) => {
160
+ elt.style.pointerEvents = "initial";
161
+ elt.style.cursor = "pointer";
162
+ elt.dataset.highlightRect = this.highlight.id;
163
+ this.container.appendChild(elt);
164
+ });
165
+ const firstElement = rectElements[0];
166
+ if (firstElement && this.highlight.notes) {
167
+ const noteIcon = document.createElement("span");
168
+ noteIcon.textContent = "📝";
169
+ noteIcon.style.position = "absolute";
170
+ noteIcon.style.top = "0";
171
+ noteIcon.style.left = "0";
172
+ noteIcon.style.transform = "translate(-0%, -80%)";
173
+ noteIcon.style.fontSize = "18px";
174
+ noteIcon.style.opacity = "50%";
175
+ firstElement.appendChild(noteIcon);
176
+ }
177
+ return null;
178
+ })
184
179
  );
185
- rectElements.forEach((elt) => {
186
- elt.style.pointerEvents = "initial";
187
- elt.style.cursor = "pointer";
188
- elt.dataset.highlightRect = this.highlight.id;
189
- this.container.appendChild(elt);
190
- });
191
- const firstElement = rectElements[0];
192
- if (firstElement && this.highlight.contents?.length) {
193
- const noteIcon = document.createElement("span");
194
- noteIcon.textContent = "📝";
195
- noteIcon.style.position = "absolute";
196
- noteIcon.style.top = "0";
197
- noteIcon.style.left = "0";
198
- noteIcon.style.transform = "translate(-0%, -80%)";
199
- noteIcon.style.fontSize = "18px";
200
- noteIcon.style.opacity = "50%";
201
- firstElement.appendChild(noteIcon);
202
- }
203
180
  }
204
181
  isWithinTarget(target) {
205
182
  return this.container.contains(target);
@@ -211,9 +188,9 @@ class SpineItemHighlight extends DestroyableClass {
211
188
  }
212
189
 
213
190
  class SpineItemHighlights extends DestroyableClass {
214
- constructor(highlights$, spineItem, reader, selectedHighlight) {
191
+ constructor(annotations$, spineItem, reader, selectedHighlight) {
215
192
  super();
216
- this.highlights$ = highlights$;
193
+ this.annotations$ = annotations$;
217
194
  this.spineItem = spineItem;
218
195
  this.reader = reader;
219
196
  this.selectedHighlight = selectedHighlight;
@@ -222,7 +199,7 @@ class SpineItemHighlights extends DestroyableClass {
222
199
  this.spineItem.containerElement,
223
200
  firstLayerElement
224
201
  );
225
- const itemHighlights$ = this.highlights$.pipe(
202
+ const itemHighlights$ = this.annotations$.pipe(
226
203
  switchMap((annotations) => {
227
204
  this.highlights.forEach((highlight) => highlight.destroy());
228
205
  this.highlights = [];
@@ -251,7 +228,7 @@ class SpineItemHighlights extends DestroyableClass {
251
228
  (highlights) => merge(...highlights.map((highlight) => highlight.tap$))
252
229
  )
253
230
  );
254
- highlights$.subscribe();
231
+ annotations$.subscribe();
255
232
  }
256
233
  layer;
257
234
  highlights = [];
@@ -259,7 +236,9 @@ class SpineItemHighlights extends DestroyableClass {
259
236
  layout() {
260
237
  const firstLayerElement = this.spineItem.renderer.documentContainer ?? document.createElement("div");
261
238
  layoutAnnotationLayer(firstLayerElement, this.layer);
262
- this.highlights.forEach((highlight) => highlight.render());
239
+ return forkJoin(
240
+ this.highlights.map((highlight) => highlight.render())
241
+ ).pipe(defaultIfEmpty(null));
263
242
  }
264
243
  getHighlightsForTarget(target) {
265
244
  return this.highlights.filter(
@@ -321,97 +300,97 @@ class ReaderHighlights extends DestroyableClass {
321
300
  return !!this.getHighlightsForTarget(target).length;
322
301
  };
323
302
  layout() {
324
- this.spineItemHighlights.value.forEach((item) => item.layout());
303
+ return forkJoin(
304
+ this.spineItemHighlights.value.map((item) => item.layout())
305
+ ).pipe(defaultIfEmpty(null));
325
306
  }
326
307
  }
327
308
 
328
- const consolidate = (highlight, reader) => {
329
- const { itemIndex } = reader.cfi.parseCfi(highlight.cfi ?? "");
330
- const spineItem = reader.spineItemsManager.get(itemIndex);
331
- if (!spineItem) return of(highlight);
332
- return of(highlight).pipe(
333
- withLatestFrom(spineItem.isReady$),
334
- tap(([, isItemReady]) => {
335
- const startCfi = reader.cfi.resolveCfi({ cfi: highlight.cfi ?? "" });
336
- const resolvedFocusCfi = reader.cfi.resolveCfi({
337
- cfi: highlight.endCfi ?? ""
338
- });
339
- if (startCfi?.node && resolvedFocusCfi?.node && isItemReady) {
340
- const range = startCfi?.node.ownerDocument?.createRange();
341
- range?.setStart(startCfi?.node, startCfi.offset ?? 0);
342
- range?.setEnd(resolvedFocusCfi?.node, resolvedFocusCfi.offset ?? 0);
343
- highlight.range = range;
344
- highlight.selectionAsText = range?.toString();
345
- } else {
346
- highlight.range = void 0;
347
- }
348
- }),
349
- map(() => highlight)
350
- );
351
- };
352
-
353
309
  const d = () => {
354
310
  if (!(typeof window > "u"))
355
311
  return window;
356
312
  };
357
- function E() {
313
+ function h() {
358
314
  var n;
359
315
  const e = (n = d()) == null ? void 0 : n.__PROSE_READER_DEBUG;
360
316
  return e === true || e === "true";
361
317
  }
362
- const i = (e) => `[${e}]`, s = (e, n = E()) => ({
363
- namespace: (t, o) => s(`${e} ${t}`, o),
364
- debug: n ? e ? Function.prototype.bind.call(console.debug, console, i(e)) : Function.prototype.bind.call(console.debug, console) : () => {
318
+ const u = (e, n = h(), t) => ({
319
+ namespace: (o, l) => u(`[${e}] [${o}]`, l, t),
320
+ debug: n ? e ? Function.prototype.bind.call(console.debug, console, e) : Function.prototype.bind.call(console.debug, console) : () => {
365
321
  },
366
- info: n ? e ? Function.prototype.bind.call(console.info, console, i(e)) : Function.prototype.bind.call(console.info, console) : () => {
322
+ info: n ? e ? Function.prototype.bind.call(
323
+ console.info,
324
+ console,
325
+ `%c${e}`,
326
+ t != null && t.color ? `color: ${t.color}` : void 0
327
+ ) : Function.prototype.bind.call(console.info, console) : () => {
367
328
  },
368
- log: n ? e ? Function.prototype.bind.call(console.log, console, i(e)) : Function.prototype.bind.call(console.log, console) : () => {
329
+ log: n ? e ? Function.prototype.bind.call(console.log, console, e) : Function.prototype.bind.call(console.log, console) : () => {
369
330
  },
370
- warn: n ? e ? Function.prototype.bind.call(console.warn, console, i(e)) : Function.prototype.bind.call(console.warn, console) : () => {
331
+ warn: n ? e ? Function.prototype.bind.call(console.warn, console, e) : Function.prototype.bind.call(console.warn, console) : () => {
371
332
  },
372
- error: n ? e ? Function.prototype.bind.call(console.error, console, i(e)) : Function.prototype.bind.call(console.error, console) : () => {
333
+ error: n ? e ? Function.prototype.bind.call(console.error, console, e) : Function.prototype.bind.call(console.error, console) : () => {
373
334
  }
374
- }), b = {
375
- ...s(),
376
- namespace: (e, n) => s(e, n)
335
+ }), F = {
336
+ ...u(),
337
+ namespace: (e, n, t) => u(e, n, t)
377
338
  };
378
339
 
379
340
  const name = "@prose-reader/enhancer-annotations";
380
341
 
381
342
  const IS_DEBUG_ENABLED = true;
382
- const report = b.namespace(name, IS_DEBUG_ENABLED);
343
+ const report = F.namespace(name, IS_DEBUG_ENABLED);
383
344
 
384
345
  const annotationsEnhancer = (next) => (options) => {
385
346
  const reader = next(options);
386
347
  const commands = new Commands();
387
- const highlightsSubject = new BehaviorSubject([]);
348
+ const annotationsSubject = new BehaviorSubject([]);
388
349
  const selectedHighlightSubject = new BehaviorSubject(
389
350
  void 0
390
351
  );
391
- const highlights$ = highlightsSubject.asObservable().pipe(distinctUntilChanged());
352
+ const annotations$ = annotationsSubject.asObservable().pipe(
353
+ distinctUntilChanged(),
354
+ tap((annotations) => {
355
+ report.debug("annotations", annotations);
356
+ }),
357
+ shareReplay({
358
+ refCount: true,
359
+ bufferSize: 1
360
+ })
361
+ );
392
362
  const readerHighlights = new ReaderHighlights(
393
363
  reader,
394
- highlightsSubject,
364
+ annotationsSubject,
395
365
  selectedHighlightSubject
396
366
  );
397
- const highlighted$ = commands.highlight$.pipe(
398
- map(({ data: { itemIndex, selection, ...rest } }) => {
367
+ const resolveItemInformation = (params) => {
368
+ if (params.itemIndex !== void 0)
369
+ return { itemIndex: params.itemIndex, pageIndex: void 0 };
370
+ if (params.absolutePageIndex !== void 0) {
371
+ return reader.spine.locator.getSpineInfoFromAbsolutePageIndex({
372
+ absolutePageIndex: params.absolutePageIndex
373
+ });
374
+ }
375
+ return void 0;
376
+ };
377
+ const annotated$ = commands.annotate$.pipe(
378
+ map(({ data: { selection, ...rest } }) => {
379
+ const { itemIndex, pageIndex = 0 } = resolveItemInformation(rest) ?? {};
399
380
  const spineItem = reader.spineItemsManager.get(itemIndex);
400
381
  if (!spineItem) return void 0;
401
- const range = reader.selection.createOrderedRangeFromSelection({
382
+ const range = selection ? reader.selection.createOrderedRangeFromSelection({
402
383
  selection,
403
384
  spineItem
404
- });
405
- if (!range) return void 0;
406
- const { start: startCfi, end: endCfi } = reader.cfi.generateCfiFromRange(range, spineItem.item);
407
- const highlight = new ProseHighlight({
408
- cfi: startCfi,
409
- endCfi,
410
- itemIndex,
385
+ }) : void 0;
386
+ const cfi = range ? reader.cfi.generateCfiFromRange(range, spineItem.item) : reader.cfi.generateCfiForSpineItemPage({ pageIndex, spineItem });
387
+ const highlight = {
388
+ cfi,
389
+ itemIndex: spineItem.index,
411
390
  id: window.crypto.randomUUID(),
412
391
  ...rest
413
- });
414
- highlightsSubject.next([...highlightsSubject.getValue(), highlight]);
392
+ };
393
+ annotationsSubject.next([...annotationsSubject.getValue(), highlight]);
415
394
  return [highlight.id];
416
395
  }),
417
396
  filter(isDefined),
@@ -421,28 +400,31 @@ const annotationsEnhancer = (next) => (options) => {
421
400
  map(({ data }) => {
422
401
  const annotations = Array.isArray(data) ? data : [data];
423
402
  const addedHighlights = annotations.map((annotation) => {
424
- const { itemIndex } = reader.cfi.parseCfi(annotation.cfi ?? "");
425
- const highlight = new ProseHighlight({ ...annotation, itemIndex });
403
+ const { itemIndex = 0 } = reader.cfi.parseCfi(annotation.cfi ?? "");
404
+ const highlight = {
405
+ ...annotation,
406
+ itemIndex
407
+ };
426
408
  return highlight;
427
409
  });
428
- highlightsSubject.next([
429
- ...highlightsSubject.getValue(),
410
+ annotationsSubject.next([
411
+ ...annotationsSubject.getValue(),
430
412
  ...addedHighlights
431
413
  ]);
432
414
  })
433
415
  );
434
416
  const delete$ = commands.delete$.pipe(
435
417
  tap(({ id }) => {
436
- highlightsSubject.next(
437
- highlightsSubject.getValue().filter((highlight) => highlight.id !== id)
418
+ annotationsSubject.next(
419
+ annotationsSubject.getValue().filter((highlight) => highlight.id !== id)
438
420
  );
439
421
  })
440
422
  );
441
423
  const update$ = commands.update$.pipe(
442
424
  tap(({ id, data }) => {
443
- highlightsSubject.next(
444
- highlightsSubject.getValue().map((highlight) => {
445
- return highlight.id === id ? highlight.update(data) : highlight;
425
+ annotationsSubject.next(
426
+ annotationsSubject.getValue().map((highlight) => {
427
+ return highlight.id === id ? { ...highlight, ...data } : highlight;
446
428
  })
447
429
  );
448
430
  })
@@ -454,55 +436,52 @@ const annotationsEnhancer = (next) => (options) => {
454
436
  );
455
437
  const reset$ = commands.reset$.pipe(
456
438
  tap(() => {
457
- highlightsSubject.next([]);
439
+ annotationsSubject.next([]);
458
440
  })
459
441
  );
460
- const highlightsConsolidation$ = merge(highlighted$, reader.layout$).pipe(
442
+ const renderAnnotations$ = merge(annotations$, reader.layout$).pipe(
461
443
  debounceTime(50),
462
- withLatestFrom(highlights$),
463
- mergeMap(
464
- () => forkJoin(
465
- highlightsSubject.value.map(
466
- (highlight) => consolidate(highlight, reader)
467
- )
444
+ switchMap(() => readerHighlights.layout())
445
+ );
446
+ const candidates$ = reader.layoutInfo$.pipe(
447
+ switchMap(
448
+ ({ pages }) => combineLatest(
449
+ pages.map((page) => {
450
+ const item = reader.spineItemsManager.get(page.itemIndex);
451
+ if (!item) return of(false);
452
+ if (item.renditionLayout === "pre-paginated") return of(true);
453
+ if (page.firstVisibleNode) return of(true);
454
+ return of(false);
455
+ })
468
456
  )
469
- ),
470
- tap((consolidatedHighlights) => {
471
- const consolidatedExistingHighlights = highlightsSubject.value.map(
472
- (highlight) => consolidatedHighlights.find((c) => c.id === highlight.id) ?? highlight
473
- );
474
- highlightsSubject.next(consolidatedExistingHighlights);
475
- readerHighlights.layout();
476
- })
457
+ )
477
458
  );
478
459
  merge(
479
- highlighted$,
460
+ annotated$,
480
461
  add$,
481
462
  delete$,
482
463
  update$,
483
464
  select$,
484
465
  reset$,
485
- highlightsConsolidation$,
486
- highlights$.pipe(
487
- tap((annotations) => {
488
- report.debug("highlights", annotations);
489
- })
490
- )
466
+ renderAnnotations$,
467
+ annotations$
491
468
  ).pipe(takeUntil(reader.$.destroy$)).subscribe();
492
469
  return {
493
470
  ...reader,
494
471
  __PROSE_READER_ENHANCER_ANNOTATIONS: true,
495
472
  destroy: () => {
496
- highlightsSubject.complete();
473
+ annotationsSubject.complete();
497
474
  commands.destroy();
498
475
  readerHighlights.destroy();
499
476
  reader.destroy();
500
477
  },
501
478
  annotations: {
502
- highlights$,
479
+ annotations$,
503
480
  highlightTap$: readerHighlights.tap$,
481
+ candidates$,
504
482
  isTargetWithinHighlight: readerHighlights.isTargetWithinHighlight,
505
- highlight: commands.highlight,
483
+ annotate: commands.annotate,
484
+ annotateAbsolutePage: commands.annotateAbsolutePage,
506
485
  add: commands.add,
507
486
  delete: commands.delete,
508
487
  update: commands.update,
@@ -512,5 +491,5 @@ const annotationsEnhancer = (next) => (options) => {
512
491
  };
513
492
  };
514
493
 
515
- export { ProseHighlight, annotationsEnhancer };
494
+ export { annotationsEnhancer };
516
495
  //# sourceMappingURL=index.js.map