@prose-reader/enhancer-annotations 1.124.0 → 1.126.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,9 +1,7 @@
1
- import { DestroyableClass } from '@prose-reader/core';
2
- import { Highlight } from './types';
3
- type HighlightParams = {
4
- document: Document;
5
- selection: Selection;
6
- itemId: string;
1
+ import { DestroyableClass, Reader } from '@prose-reader/core';
2
+ import { ObservedValueOf } from 'rxjs';
3
+ import { SerializableHighlight } from './types';
4
+ type HighlightParams = ObservedValueOf<Reader["selection"]["selection$"]> & {
7
5
  color?: string;
8
6
  contents?: string[];
9
7
  };
@@ -15,7 +13,7 @@ export declare class Commands extends DestroyableClass {
15
13
  }>;
16
14
  readonly add$: import('rxjs').Observable<{
17
15
  type: "add";
18
- data: Highlight | Highlight[];
16
+ data: SerializableHighlight | SerializableHighlight[];
19
17
  }>;
20
18
  readonly delete$: import('rxjs').Observable<{
21
19
  type: "delete";
@@ -31,7 +29,7 @@ export declare class Commands extends DestroyableClass {
31
29
  id: string | undefined;
32
30
  }>;
33
31
  highlight: (params: HighlightParams) => void;
34
- add: (data: Highlight | Highlight[]) => void;
32
+ add: (data: SerializableHighlight | SerializableHighlight[]) => void;
35
33
  delete: (id: string) => void;
36
34
  update: (id: string, data: Pick<HighlightParams, "color" | "contents">) => void;
37
35
  select: (id: string | undefined) => void;
@@ -1,11 +1,11 @@
1
1
  import { Reader } from '@prose-reader/core';
2
2
  import { Observable } from 'rxjs';
3
- import { RuntimeHighlight } from './types';
4
3
  import { ReaderHighlights } from './highlights/ReaderHighlights';
5
4
  import { Commands } from './Commands';
5
+ import { Highlight } from './highlights/Highlight';
6
6
  export declare const annotationsEnhancer: <InheritOptions, InheritOutput extends Reader>(next: (options: InheritOptions) => InheritOutput) => (options: InheritOptions) => InheritOutput & {
7
7
  annotations: {
8
- annotations$: Observable<RuntimeHighlight[]>;
8
+ highlights$: Observable<Highlight[]>;
9
9
  highlightTap$: ReaderHighlights["tap$"];
10
10
  highlight: Commands["highlight"];
11
11
  add: Commands["add"];
@@ -0,0 +1,21 @@
1
+ import { SerializableHighlight } from '../types';
2
+ export declare class Highlight {
3
+ anchorCfi: string | undefined;
4
+ focusCfi: string | undefined;
5
+ itemIndex?: number;
6
+ color?: string;
7
+ contents?: string[];
8
+ spineItemPageIndex?: number;
9
+ absolutePageIndex?: number;
10
+ range?: Range;
11
+ lastSelectionText?: string;
12
+ /**
13
+ * Unique local ID. This is to ensure unicity
14
+ * for duplicate selections
15
+ */
16
+ id: string;
17
+ constructor(params: SerializableHighlight & {
18
+ itemIndex?: number;
19
+ });
20
+ toJSON(): SerializableHighlight;
21
+ }
@@ -1,7 +1,7 @@
1
1
  import { DestroyableClass, Reader } from '@prose-reader/core';
2
2
  import { BehaviorSubject } from 'rxjs';
3
- import { Highlight } from '../types';
4
3
  import { SpineItemHighlights } from './SpineItemHighlights';
4
+ import { Highlight } from './Highlight';
5
5
  export declare class ReaderHighlights extends DestroyableClass {
6
6
  private reader;
7
7
  private highlights;
@@ -9,6 +9,7 @@ export declare class ReaderHighlights extends DestroyableClass {
9
9
  private spineItemHighlights;
10
10
  tap$: SpineItemHighlights["tap$"];
11
11
  constructor(reader: Reader, highlights: BehaviorSubject<Highlight[]>, selectedHighlight: BehaviorSubject<string | undefined>);
12
- getHighlightsForTarget: (target: EventTarget) => import('../types').RuntimeHighlight[];
12
+ getHighlightsForTarget: (target: EventTarget) => Highlight[];
13
13
  isTargetWithinHighlight: (target: EventTarget) => boolean;
14
+ layout(): void;
14
15
  }
@@ -1,18 +1,18 @@
1
1
  import { DestroyableClass, Reader, SpineItem } from '@prose-reader/core';
2
- import { RuntimeHighlight } from '../types';
3
2
  import { Observable } from 'rxjs';
3
+ import { Highlight } from './Highlight';
4
4
  export declare class SpineItemHighlight extends DestroyableClass {
5
5
  private spineItem;
6
6
  private containerElement;
7
7
  private reader;
8
- readonly highlight: RuntimeHighlight;
8
+ readonly highlight: Highlight;
9
9
  private isSelected;
10
10
  private container;
11
11
  readonly tap$: Observable<{
12
12
  event: Event;
13
- highlight: RuntimeHighlight;
13
+ highlight: Highlight;
14
14
  }>;
15
- constructor(spineItem: SpineItem, containerElement: HTMLElement, reader: Reader, highlight: RuntimeHighlight, isSelected: Observable<boolean>);
15
+ constructor(spineItem: SpineItem, containerElement: HTMLElement, reader: Reader, highlight: Highlight, isSelected: Observable<boolean>);
16
16
  render(): void;
17
17
  isWithinTarget(target: Node): boolean;
18
18
  destroy(): void;
@@ -1,16 +1,16 @@
1
1
  import { Observable } from 'rxjs';
2
- import { RuntimeHighlight } from '../types';
3
2
  import { DestroyableClass, Reader, SpineItem } from '@prose-reader/core';
4
3
  import { SpineItemHighlight } from './SpineItemHighlight';
4
+ import { Highlight } from './Highlight';
5
5
  export declare class SpineItemHighlights extends DestroyableClass {
6
- private annotations$;
6
+ private highlights$;
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(annotations$: Observable<RuntimeHighlight[]>, spineItem: SpineItem, reader: Reader, selectedHighlight: Observable<string | undefined>);
13
+ constructor(highlights$: Observable<Highlight[]>, spineItem: SpineItem, reader: Reader, selectedHighlight: Observable<string | undefined>);
14
14
  layout(): void;
15
15
  getHighlightsForTarget(target: EventTarget): SpineItemHighlight[];
16
16
  destroy(): void;
@@ -0,0 +1,3 @@
1
+ import { Reader } from '@prose-reader/core';
2
+ import { Highlight } from './Highlight';
3
+ export declare const consolidate: (highlight: Highlight, reader: Reader) => void;
@@ -1,11 +1,4 @@
1
- export declare const getElementsForRange: (range: Range, container: HTMLElement) => HTMLDivElement[];
2
- export declare const getRangeFromSelection: (overlayElement: HTMLElement, anchor: {
3
- node: Node;
4
- offset?: number;
5
- }, focus: {
6
- node: Node;
7
- offset?: number;
8
- }) => Range;
1
+ export declare const createElementForRange: (range: Range, container: HTMLElement, color: string) => HTMLDivElement[];
9
2
  export declare const copyPositionStyle: (source: HTMLElement, target: HTMLElement) => void;
10
3
  export declare const createAnnotationLayer: (container: HTMLElement, layer: HTMLElement) => HTMLDivElement;
11
4
  export declare const layoutAnnotationLayer: (layer: HTMLElement, annotationLayer: HTMLElement) => void;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './annotationsEnhancer';
2
2
  export * from './types';
3
+ export * from './highlights/Highlight';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { fromEvent, map, share, skip, tap, takeUntil, switchMap, distinctUntilChanged, of, shareReplay, merge, BehaviorSubject, Subject, filter } from 'rxjs';
2
- import { DestroyableClass } from '@prose-reader/core';
1
+ import { DestroyableClass, waitForSwitch } from '@prose-reader/core';
2
+ import { fromEvent, map, share, skip, tap, takeUntil, switchMap, distinctUntilChanged, of, shareReplay, merge, BehaviorSubject, Subject, filter, debounceTime, withLatestFrom } from 'rxjs';
3
3
 
4
4
  const c = "@prose-reader", i = (e) => `[${e}]`, p = (e, n) => ({
5
5
  debug: !n || (window == null ? void 0 : window.__PROSE_READER_DEBUG) !== !0 ? () => {
@@ -16,7 +16,7 @@ const c = "@prose-reader", i = (e) => `[${e}]`, p = (e, n) => ({
16
16
  const IS_DEBUG_ENABLED = true;
17
17
  const report = $.namespace(`enhancer-annotations`, IS_DEBUG_ENABLED);
18
18
 
19
- const getElementsForRange = (range, container) => {
19
+ const createElementForRange = (range, container, color) => {
20
20
  const rects = Array.from(range.getClientRects());
21
21
  const lineGroups = /* @__PURE__ */ new Map();
22
22
  rects.forEach((rect) => {
@@ -31,39 +31,27 @@ const getElementsForRange = (range, container) => {
31
31
  const right = Math.max(...lineRects.map((r) => r.right));
32
32
  const top = lineRects[0]?.top;
33
33
  const height = lineRects[0]?.height;
34
+ const rectEltContainer = container.ownerDocument.createElement("div");
34
35
  const rectElt = container.ownerDocument.createElement("div");
35
- rectElt.style.cssText = `
36
+ rectEltContainer.style.cssText = `
36
37
  position: absolute;
37
38
  width: ${right - left}px;
38
39
  height: ${height}px;
39
40
  top: ${top}px;
40
41
  left: ${left}px;
41
- opacity: 50%;
42
+ box-sizing: border-box;
43
+ border: 3px dashed transparent;
44
+ `;
45
+ rectElt.style.cssText = `
46
+ height: 100%;
47
+ width: 100%;
48
+ opacity: 25%;
49
+ background-color: ${color}
42
50
  `;
43
- return rectElt;
51
+ rectEltContainer.appendChild(rectElt);
52
+ return rectEltContainer;
44
53
  });
45
54
  };
46
- const getRangeFromSelection = (overlayElement, anchor, focus) => {
47
- const range = overlayElement.ownerDocument.createRange();
48
- const comparison = anchor.node.compareDocumentPosition(focus.node);
49
- try {
50
- if (comparison & Node.DOCUMENT_POSITION_PRECEDING) {
51
- range.setStart(focus.node, focus.offset || 0);
52
- range.setEnd(anchor.node, anchor.offset || 0);
53
- } else if (comparison & Node.DOCUMENT_POSITION_FOLLOWING) {
54
- range.setStart(anchor.node, anchor.offset || 0);
55
- range.setEnd(focus.node, focus.offset || 0);
56
- } else {
57
- const startOffset = Math.min(anchor.offset || 0, focus.offset || 0);
58
- const endOffset = Math.max(anchor.offset || 0, focus.offset || 0);
59
- range.setStart(anchor.node, startOffset);
60
- range.setEnd(anchor.node, endOffset);
61
- }
62
- } catch (e) {
63
- report.error(e);
64
- }
65
- return range;
66
- };
67
55
  const copyPositionStyle = (source, target) => {
68
56
  target.style.cssText = source.style.cssText;
69
57
  };
@@ -92,6 +80,7 @@ class SpineItemHighlight extends DestroyableClass {
92
80
  this.highlight = highlight;
93
81
  this.isSelected = isSelected;
94
82
  void this.spineItem;
83
+ void this.reader;
95
84
  this.container = this.containerElement.ownerDocument.createElement("div");
96
85
  this.container.dataset["highlightContainer"] = this.highlight.id;
97
86
  this.containerElement.appendChild(this.container);
@@ -105,7 +94,7 @@ class SpineItemHighlight extends DestroyableClass {
105
94
  tap((isSelected2) => {
106
95
  Array.from(this.container.children).forEach((child) => {
107
96
  if (child instanceof HTMLElement) {
108
- child.style.border = isSelected2 ? "3px dashed red" : "none";
97
+ child.style.border = isSelected2 ? "3px dashed red" : "3px dashed transparent";
109
98
  }
110
99
  });
111
100
  }),
@@ -116,25 +105,29 @@ class SpineItemHighlight extends DestroyableClass {
116
105
  tap$;
117
106
  render() {
118
107
  this.container.innerHTML = "";
119
- const { node: anchorNode, offset: anchorOffset } = this.reader.cfi.resolveCfi({ cfi: this.highlight.anchorCfi ?? `` }) ?? {};
120
- const { node: focusNode, offset: focusOffset } = this.reader.cfi.resolveCfi({ cfi: this.highlight.focusCfi ?? `` }) ?? {};
121
- if (!anchorNode || !focusNode) {
122
- report.error(`Unable to resolve anchor cfi: ${this.highlight.anchorCfi}`);
108
+ const range = this.highlight.range;
109
+ if (!range) {
123
110
  return;
124
111
  }
125
- const range = getRangeFromSelection(
126
- this.containerElement,
127
- { node: anchorNode, offset: anchorOffset },
128
- { node: focusNode, offset: focusOffset }
129
- );
130
- const rectElements = getElementsForRange(range, this.container);
112
+ const rectElements = createElementForRange(range, this.container, this.highlight.color ?? "yellow");
131
113
  rectElements.forEach((elt) => {
132
114
  elt.style.pointerEvents = "initial";
133
115
  elt.style.cursor = "pointer";
134
- elt.style.backgroundColor = this.highlight.color ?? "yellow";
135
116
  elt.dataset["highlightRect"] = this.highlight.id;
136
117
  this.container.appendChild(elt);
137
118
  });
119
+ const firstElement = rectElements[0];
120
+ if (firstElement && this.highlight.contents?.length) {
121
+ const noteIcon = document.createElement("span");
122
+ noteIcon.textContent = "📝";
123
+ noteIcon.style.position = "absolute";
124
+ noteIcon.style.top = "0";
125
+ noteIcon.style.left = "0";
126
+ noteIcon.style.transform = "translate(-0%, -80%)";
127
+ noteIcon.style.fontSize = "18px";
128
+ noteIcon.style.opacity = "50%";
129
+ firstElement.appendChild(noteIcon);
130
+ }
138
131
  }
139
132
  isWithinTarget(target) {
140
133
  return this.container.contains(target);
@@ -146,20 +139,20 @@ class SpineItemHighlight extends DestroyableClass {
146
139
  }
147
140
 
148
141
  class SpineItemHighlights extends DestroyableClass {
149
- constructor(annotations$, spineItem, reader, selectedHighlight) {
142
+ constructor(highlights$, spineItem, reader, selectedHighlight) {
150
143
  super();
151
- this.annotations$ = annotations$;
144
+ this.highlights$ = highlights$;
152
145
  this.spineItem = spineItem;
153
146
  this.reader = reader;
154
147
  this.selectedHighlight = selectedHighlight;
155
148
  const firstLayerElement = spineItem.renderer.layers[0]?.element ?? document.createElement("div");
156
149
  this.layer = createAnnotationLayer(this.spineItem.containerElement, firstLayerElement);
157
- const highlights$ = this.annotations$.pipe(
150
+ const itemHighlights$ = this.highlights$.pipe(
158
151
  switchMap((annotations) => {
159
152
  this.highlights.forEach((highlight) => highlight.destroy());
160
153
  this.highlights = [];
161
154
  annotations.forEach((annotation) => {
162
- if (annotation.itemId !== this.spineItem.item.id) return;
155
+ if (annotation.itemIndex !== this.spineItem.item.index) return;
163
156
  const isSelected$ = this.selectedHighlight.pipe(
164
157
  map((id) => id === annotation.id),
165
158
  distinctUntilChanged()
@@ -172,7 +165,7 @@ class SpineItemHighlights extends DestroyableClass {
172
165
  shareReplay(1),
173
166
  takeUntil(this.destroy$)
174
167
  );
175
- this.tap$ = highlights$.pipe(switchMap((highlights) => merge(...highlights.map((highlight) => highlight.tap$))));
168
+ this.tap$ = itemHighlights$.pipe(switchMap((highlights) => merge(...highlights.map((highlight) => highlight.tap$))));
176
169
  highlights$.subscribe();
177
170
  }
178
171
  layer;
@@ -202,18 +195,13 @@ class ReaderHighlights extends DestroyableClass {
202
195
  const spineItem = reader.spineItemsManager.get(itemId);
203
196
  if (!spineItem) return;
204
197
  const spineItemHighlights$ = this.highlights.pipe(
205
- map((highlights2) => highlights2.filter((highlight) => highlight.itemId === itemId))
198
+ map((highlights2) => highlights2.filter((highlight) => highlight.itemIndex === spineItem.item.index))
206
199
  );
207
200
  const spineItemHighlights = new SpineItemHighlights(spineItemHighlights$, spineItem, reader, this.selectedHighlight);
208
201
  this.spineItemHighlights.next([...this.spineItemHighlights.getValue(), spineItemHighlights]);
209
- const deregister = reader.hookManager.register("item.onAfterLayout", ({ item }) => {
210
- if (item.id !== itemId) return;
211
- spineItemHighlights.layout();
212
- });
213
202
  destroy(() => {
214
203
  this.spineItemHighlights.next(this.spineItemHighlights.getValue().filter((layer) => layer !== spineItemHighlights));
215
204
  spineItemHighlights.destroy();
216
- deregister();
217
205
  });
218
206
  });
219
207
  this.tap$ = this.spineItemHighlights.pipe(switchMap((layers) => merge(...layers.map((layer) => layer.tap$))));
@@ -226,6 +214,9 @@ class ReaderHighlights extends DestroyableClass {
226
214
  isTargetWithinHighlight = (target) => {
227
215
  return !!this.getHighlightsForTarget(target).length;
228
216
  };
217
+ layout() {
218
+ this.spineItemHighlights.getValue().forEach((item) => item.layout());
219
+ }
229
220
  }
230
221
 
231
222
  class Commands extends DestroyableClass {
@@ -256,6 +247,82 @@ class Commands extends DestroyableClass {
256
247
  }
257
248
  }
258
249
 
250
+ class Highlight {
251
+ anchorCfi;
252
+ focusCfi;
253
+ itemIndex;
254
+ color;
255
+ contents;
256
+ spineItemPageIndex;
257
+ absolutePageIndex;
258
+ range;
259
+ lastSelectionText;
260
+ /**
261
+ * Unique local ID. This is to ensure unicity
262
+ * for duplicate selections
263
+ */
264
+ id;
265
+ constructor(params) {
266
+ this.anchorCfi = params.anchorCfi;
267
+ this.focusCfi = params.focusCfi;
268
+ this.itemIndex = params.itemIndex;
269
+ this.color = params.color;
270
+ this.contents = params.contents;
271
+ this.id = params.id;
272
+ this.lastSelectionText = params.lastSelectionText;
273
+ }
274
+ toJSON() {
275
+ return {
276
+ anchorCfi: this.anchorCfi,
277
+ focusCfi: this.focusCfi,
278
+ color: this.color,
279
+ contents: this.contents,
280
+ id: this.id,
281
+ lastSelectionText: this.lastSelectionText
282
+ };
283
+ }
284
+ }
285
+
286
+ const consolidate = (highlight, reader) => {
287
+ const { itemIndex } = reader.cfi.parseCfi(highlight.anchorCfi ?? "");
288
+ const spineItem = reader.spineItemsManager.get(itemIndex);
289
+ const resolvedAnchorCfi = reader.cfi.resolveCfi({ cfi: highlight.anchorCfi ?? "" });
290
+ const resolvedFocusCfi = reader.cfi.resolveCfi({ cfi: highlight.focusCfi ?? "" });
291
+ if (!spineItem) return;
292
+ if (spineItem.item.renditionLayout === `pre-paginated`) {
293
+ highlight.spineItemPageIndex = 0;
294
+ } else {
295
+ if (resolvedAnchorCfi?.node) {
296
+ highlight.spineItemPageIndex = reader.spine.locator.spineItemLocator.getSpineItemPageIndexFromNode(
297
+ resolvedAnchorCfi.node,
298
+ resolvedAnchorCfi.offset ?? 0,
299
+ spineItem
300
+ );
301
+ }
302
+ }
303
+ if (resolvedAnchorCfi?.node && resolvedFocusCfi?.node && spineItem.isReady) {
304
+ const range = reader.selection.createRangeFromSelection({
305
+ selection: {
306
+ anchorNode: resolvedAnchorCfi.node,
307
+ anchorOffset: resolvedAnchorCfi.offset ?? 0,
308
+ focusNode: resolvedFocusCfi.node,
309
+ focusOffset: resolvedFocusCfi.offset ?? 0
310
+ },
311
+ spineItem
312
+ });
313
+ highlight.range = range;
314
+ highlight.lastSelectionText = range?.toString();
315
+ } else {
316
+ highlight.range = void 0;
317
+ }
318
+ if (highlight.spineItemPageIndex !== void 0) {
319
+ highlight.absolutePageIndex = reader.spine.locator.getAbsolutePageIndexFromPageIndex({
320
+ pageIndex: highlight.spineItemPageIndex,
321
+ spineItemOrId: spineItem
322
+ });
323
+ }
324
+ };
325
+
259
326
  const annotationsEnhancer = (next) => (options) => {
260
327
  const reader = next(options);
261
328
  const commands = new Commands();
@@ -263,16 +330,27 @@ const annotationsEnhancer = (next) => (options) => {
263
330
  const selectedHighlightSubject = new BehaviorSubject(void 0);
264
331
  const readerHighlights = new ReaderHighlights(reader, highlightsSubject, selectedHighlightSubject);
265
332
  const highlight$ = commands.highlight$.pipe(
266
- tap(({ data: { itemId, selection, ...rest } }) => {
267
- const { anchorCfi, focusCfi } = reader.selection.generateCfis({ itemId, selection });
268
- const annotation = { anchorCfi, focusCfi, itemId, id: window.crypto.randomUUID(), ...rest };
269
- highlightsSubject.next([...highlightsSubject.getValue(), annotation]);
333
+ tap(({ data: { itemIndex, selection, ...rest } }) => {
334
+ const item = reader.spineItemsManager.get(itemIndex)?.item;
335
+ if (!item) return;
336
+ const { anchorCfi, focusCfi } = reader.cfi.generateCfiFromSelection({ item, selection });
337
+ const highlight = new Highlight({ anchorCfi, focusCfi, itemIndex, id: window.crypto.randomUUID(), ...rest });
338
+ consolidate(highlight, reader);
339
+ highlightsSubject.next([...highlightsSubject.getValue(), highlight]);
270
340
  })
271
341
  );
272
342
  const add$ = commands.add$.pipe(
273
343
  tap(({ data }) => {
274
344
  const annotations = Array.isArray(data) ? data : [data];
275
- highlightsSubject.next([...highlightsSubject.getValue(), ...annotations]);
345
+ highlightsSubject.next([
346
+ ...highlightsSubject.getValue(),
347
+ ...annotations.map((annotation) => {
348
+ const { itemIndex } = reader.cfi.parseCfi(annotation.anchorCfi ?? "");
349
+ const highlight = new Highlight({ ...annotation, itemIndex });
350
+ consolidate(highlight, reader);
351
+ return highlight;
352
+ })
353
+ ]);
276
354
  })
277
355
  );
278
356
  const delete$ = commands.delete$.pipe(
@@ -283,7 +361,7 @@ const annotationsEnhancer = (next) => (options) => {
283
361
  const update$ = commands.update$.pipe(
284
362
  tap(({ id, data }) => {
285
363
  highlightsSubject.next(
286
- highlightsSubject.getValue().map((highlight) => highlight.id === id ? { ...highlight, ...data } : highlight)
364
+ highlightsSubject.getValue().map((highlight) => highlight.id === id ? new Highlight({ ...highlight, ...data }) : highlight)
287
365
  );
288
366
  })
289
367
  );
@@ -292,16 +370,27 @@ const annotationsEnhancer = (next) => (options) => {
292
370
  selectedHighlightSubject.next(id);
293
371
  })
294
372
  );
295
- const annotations$ = highlightsSubject.asObservable();
373
+ const highlights$ = highlightsSubject.asObservable();
374
+ const highlightsConsolidation$ = reader.layout$.pipe(
375
+ debounceTime(50),
376
+ waitForSwitch(reader.viewportFree$),
377
+ withLatestFrom(highlights$),
378
+ tap(([, highlights]) => {
379
+ highlights.forEach((highlight) => consolidate(highlight, reader));
380
+ highlightsSubject.next(highlights);
381
+ readerHighlights.layout();
382
+ })
383
+ );
296
384
  merge(
297
385
  highlight$,
298
386
  add$,
299
387
  delete$,
300
388
  update$,
301
389
  select$,
302
- annotations$.pipe(
390
+ highlightsConsolidation$,
391
+ highlights$.pipe(
303
392
  tap((annotations) => {
304
- report.debug("annotations", annotations);
393
+ report.debug("highlights", annotations);
305
394
  })
306
395
  )
307
396
  ).pipe(takeUntil(reader.$.destroy$)).subscribe();
@@ -314,7 +403,7 @@ const annotationsEnhancer = (next) => (options) => {
314
403
  reader.destroy();
315
404
  },
316
405
  annotations: {
317
- annotations$,
406
+ highlights$,
318
407
  highlightTap$: readerHighlights.tap$,
319
408
  isTargetWithinHighlight: readerHighlights.isTargetWithinHighlight,
320
409
  highlight: commands.highlight,
@@ -326,5 +415,5 @@ const annotationsEnhancer = (next) => (options) => {
326
415
  };
327
416
  };
328
417
 
329
- export { annotationsEnhancer };
418
+ export { Highlight, annotationsEnhancer };
330
419
  //# sourceMappingURL=index.js.map