@prose-reader/enhancer-annotations 1.301.0 → 1.304.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.
- package/dist/index.js +252 -539
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +9 -551
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +2 -2
package/dist/index.umd.cjs
CHANGED
|
@@ -1,557 +1,15 @@
|
|
|
1
|
-
(function (
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@prose-reader/core'), require('rxjs')) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', '@prose-reader/core', 'rxjs'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["prose-reader-enhancer-annotations"] = {}, global.core, global.rxjs));
|
|
5
|
-
})(this, (function (exports, core, rxjs) { 'use strict';
|
|
6
|
-
|
|
7
|
-
const createElementForRange = (range, container, color) => {
|
|
8
|
-
const rects = Array.from(range.getClientRects());
|
|
9
|
-
const lineGroups = /* @__PURE__ */ new Map();
|
|
10
|
-
rects.forEach((rect) => {
|
|
11
|
-
const lineY = Math.round(rect.top);
|
|
12
|
-
if (!lineGroups.has(lineY)) {
|
|
13
|
-
lineGroups.set(lineY, []);
|
|
14
|
-
}
|
|
15
|
-
lineGroups.get(lineY)?.push(rect);
|
|
16
|
-
});
|
|
17
|
-
return Array.from(lineGroups.values()).map((lineRects) => {
|
|
18
|
-
const left = Math.min(...lineRects.map((r) => r.left));
|
|
19
|
-
const right = Math.max(...lineRects.map((r) => r.right));
|
|
20
|
-
const top = lineRects[0]?.top;
|
|
21
|
-
const height = lineRects[0]?.height;
|
|
22
|
-
const rectEltContainer = container.ownerDocument.createElement("div");
|
|
23
|
-
const rectElt = container.ownerDocument.createElement("div");
|
|
24
|
-
rectEltContainer.style.cssText = `
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@prose-reader/core"),require("rxjs")):typeof define==`function`&&define.amd?define([`exports`,`@prose-reader/core`,`rxjs`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e[`prose-reader-enhancer-annotations`]={},e._prose_reader_core,e.rxjs))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=(e,t,n)=>{let r=Array.from(e.getClientRects()),i=new Map;return r.forEach(e=>{let t=Math.round(e.top);i.has(t)||i.set(t,[]),i.get(t)?.push(e)}),Array.from(i.values()).map(e=>{let r=Math.min(...e.map(e=>e.left)),i=Math.max(...e.map(e=>e.right)),a=e[0]?.top,o=e[0]?.height,s=t.ownerDocument.createElement(`div`),c=t.ownerDocument.createElement(`div`);return s.style.cssText=`
|
|
25
2
|
position: absolute;
|
|
26
|
-
width: ${
|
|
27
|
-
height: ${
|
|
28
|
-
top: ${
|
|
29
|
-
left: ${
|
|
3
|
+
width: ${i-r}px;
|
|
4
|
+
height: ${o}px;
|
|
5
|
+
top: ${a}px;
|
|
6
|
+
left: ${r}px;
|
|
30
7
|
box-sizing: border-box;
|
|
31
8
|
border: 3px dashed transparent;
|
|
32
|
-
|
|
33
|
-
rectElt.style.cssText = `
|
|
9
|
+
`,c.style.cssText=`
|
|
34
10
|
height: 100%;
|
|
35
11
|
width: 100%;
|
|
36
12
|
opacity: 40%;
|
|
37
|
-
background-color: ${
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return rectEltContainer;
|
|
41
|
-
});
|
|
42
|
-
};
|
|
43
|
-
const copyPositionStyle = (source, target) => {
|
|
44
|
-
core.setPropertyIfChanged(target.style, `cssText`, source.style.cssText);
|
|
45
|
-
};
|
|
46
|
-
const createAnnotationLayer = (container, layer) => {
|
|
47
|
-
const annotationLayer = container.ownerDocument.createElement("div");
|
|
48
|
-
layoutAnnotationLayer(layer, annotationLayer);
|
|
49
|
-
container.appendChild(annotationLayer);
|
|
50
|
-
return annotationLayer;
|
|
51
|
-
};
|
|
52
|
-
const layoutAnnotationLayer = (layer, annotationLayer) => {
|
|
53
|
-
copyPositionStyle(layer, annotationLayer);
|
|
54
|
-
if (layer.style.position === "") {
|
|
55
|
-
core.setStylePropertyIfChanged(annotationLayer.style, `position`, `absolute`);
|
|
56
|
-
core.setStylePropertyIfChanged(annotationLayer.style, `top`, `0`);
|
|
57
|
-
}
|
|
58
|
-
core.setStylePropertyIfChanged(annotationLayer.style, `opacity`, `1`);
|
|
59
|
-
core.setStylePropertyIfChanged(annotationLayer.style, `pointer-events`, `none`);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
class SpineItemHighlight extends core.DestroyableClass {
|
|
63
|
-
constructor(spineItem, containerElement, reader, highlight, isSelected) {
|
|
64
|
-
super();
|
|
65
|
-
this.spineItem = spineItem;
|
|
66
|
-
this.containerElement = containerElement;
|
|
67
|
-
this.reader = reader;
|
|
68
|
-
this.highlight = highlight;
|
|
69
|
-
this.isSelected = isSelected;
|
|
70
|
-
void this.spineItem;
|
|
71
|
-
void this.reader;
|
|
72
|
-
this.container = this.containerElement.ownerDocument.createElement("div");
|
|
73
|
-
this.container.dataset.highlightContainer = this.highlight.id;
|
|
74
|
-
this.containerElement.appendChild(this.container);
|
|
75
|
-
this.tap$ = rxjs.fromEvent(this.container, "click").pipe(
|
|
76
|
-
rxjs.map((event) => ({ event, highlight: this.highlight })),
|
|
77
|
-
rxjs.share()
|
|
78
|
-
);
|
|
79
|
-
this.resolvedCfi$ = this.spineItem.watch("isLoaded").pipe(
|
|
80
|
-
rxjs.map(() => this.reader.cfi.resolveCfi({ cfi: this.highlight.cfi })),
|
|
81
|
-
rxjs.shareReplay({ refCount: true, bufferSize: 1 })
|
|
82
|
-
);
|
|
83
|
-
const updateStateOnSelection$ = this.isSelected.pipe(
|
|
84
|
-
rxjs.tap((isSelected2) => {
|
|
85
|
-
this.updateStateOnSelection(isSelected2);
|
|
86
|
-
})
|
|
87
|
-
);
|
|
88
|
-
rxjs.merge(this.resolvedCfi$, updateStateOnSelection$).pipe(rxjs.takeUntil(this.destroy$)).subscribe();
|
|
89
|
-
}
|
|
90
|
-
spineItem;
|
|
91
|
-
containerElement;
|
|
92
|
-
reader;
|
|
93
|
-
highlight;
|
|
94
|
-
isSelected;
|
|
95
|
-
container;
|
|
96
|
-
tap$;
|
|
97
|
-
resolvedCfi$;
|
|
98
|
-
updateStateOnSelection(isSelected) {
|
|
99
|
-
Array.from(this.container.children).forEach((child) => {
|
|
100
|
-
if (child instanceof HTMLElement) {
|
|
101
|
-
core.setStylePropertyIfChanged(
|
|
102
|
-
child.style,
|
|
103
|
-
`border`,
|
|
104
|
-
isSelected ? "3px dashed red" : "3px dashed transparent"
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
render() {
|
|
110
|
-
return this.resolvedCfi$.pipe(
|
|
111
|
-
rxjs.first(),
|
|
112
|
-
rxjs.withLatestFrom(this.isSelected),
|
|
113
|
-
rxjs.map(([resolvedCfi, isSelected]) => {
|
|
114
|
-
if (!resolvedCfi?.isCfiRange) return void 0;
|
|
115
|
-
const range = resolvedCfi.range;
|
|
116
|
-
this.container.innerHTML = "";
|
|
117
|
-
if (!range) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const rectElements = createElementForRange(
|
|
121
|
-
range,
|
|
122
|
-
this.container,
|
|
123
|
-
this.highlight.highlightColor ?? "yellow"
|
|
124
|
-
);
|
|
125
|
-
rectElements.forEach((elt) => {
|
|
126
|
-
elt.style.pointerEvents = "initial";
|
|
127
|
-
elt.style.cursor = "pointer";
|
|
128
|
-
elt.dataset.highlightRect = this.highlight.id;
|
|
129
|
-
this.container.appendChild(elt);
|
|
130
|
-
});
|
|
131
|
-
const firstElement = rectElements[0];
|
|
132
|
-
if (firstElement && this.highlight.notes) {
|
|
133
|
-
const noteIcon = document.createElement("span");
|
|
134
|
-
noteIcon.textContent = "📝";
|
|
135
|
-
noteIcon.style.position = "absolute";
|
|
136
|
-
noteIcon.style.top = "0";
|
|
137
|
-
noteIcon.style.left = "0";
|
|
138
|
-
noteIcon.style.transform = "translate(-0%, -80%)";
|
|
139
|
-
noteIcon.style.fontSize = "18px";
|
|
140
|
-
noteIcon.style.opacity = "50%";
|
|
141
|
-
firstElement.appendChild(noteIcon);
|
|
142
|
-
}
|
|
143
|
-
this.updateStateOnSelection(isSelected);
|
|
144
|
-
return null;
|
|
145
|
-
})
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
isWithinTarget(target) {
|
|
149
|
-
return this.container.contains(target);
|
|
150
|
-
}
|
|
151
|
-
destroy() {
|
|
152
|
-
super.destroy();
|
|
153
|
-
this.container.remove();
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
class SpineItemHighlights extends core.DestroyableClass {
|
|
158
|
-
constructor(annotations$, spineItem, reader, selectedHighlight) {
|
|
159
|
-
super();
|
|
160
|
-
this.annotations$ = annotations$;
|
|
161
|
-
this.spineItem = spineItem;
|
|
162
|
-
this.reader = reader;
|
|
163
|
-
this.selectedHighlight = selectedHighlight;
|
|
164
|
-
const firstLayerElement = spineItem.renderer.documentContainer ?? document.createElement("div");
|
|
165
|
-
this.layer = createAnnotationLayer(
|
|
166
|
-
this.spineItem.containerElement,
|
|
167
|
-
firstLayerElement
|
|
168
|
-
);
|
|
169
|
-
const itemHighlights$ = this.annotations$.pipe(
|
|
170
|
-
rxjs.switchMap((annotations) => {
|
|
171
|
-
const newAnnotations = annotations.filter(
|
|
172
|
-
(annotation) => !this.highlights.some(
|
|
173
|
-
(highlight) => highlight.highlight.id === annotation.id
|
|
174
|
-
)
|
|
175
|
-
);
|
|
176
|
-
const oldAnnotations = this.highlights.filter(
|
|
177
|
-
(highlight) => highlight.highlight.itemIndex !== this.spineItem.item.index
|
|
178
|
-
);
|
|
179
|
-
this.highlights.forEach((highlight, index) => {
|
|
180
|
-
const existingAnnotation = annotations.find(
|
|
181
|
-
(annotation) => annotation.id === highlight.highlight.id
|
|
182
|
-
);
|
|
183
|
-
if (oldAnnotations.includes(highlight)) {
|
|
184
|
-
highlight.destroy();
|
|
185
|
-
this.highlights = this.highlights.splice(index, 1);
|
|
186
|
-
}
|
|
187
|
-
if (existingAnnotation) {
|
|
188
|
-
highlight.highlight = existingAnnotation;
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
newAnnotations.forEach((annotation) => {
|
|
192
|
-
if (annotation.itemIndex !== this.spineItem.item.index) return;
|
|
193
|
-
const isSelected$ = this.selectedHighlight.pipe(
|
|
194
|
-
rxjs.map((id) => id === annotation.id),
|
|
195
|
-
rxjs.distinctUntilChanged()
|
|
196
|
-
);
|
|
197
|
-
const spineItemHighlight = new SpineItemHighlight(
|
|
198
|
-
this.spineItem,
|
|
199
|
-
this.layer,
|
|
200
|
-
this.reader,
|
|
201
|
-
annotation,
|
|
202
|
-
isSelected$
|
|
203
|
-
);
|
|
204
|
-
this.highlights.push(spineItemHighlight);
|
|
205
|
-
});
|
|
206
|
-
return rxjs.of(this.highlights);
|
|
207
|
-
}),
|
|
208
|
-
rxjs.shareReplay(1),
|
|
209
|
-
rxjs.takeUntil(this.destroy$)
|
|
210
|
-
);
|
|
211
|
-
this.tap$ = itemHighlights$.pipe(
|
|
212
|
-
rxjs.switchMap(
|
|
213
|
-
(highlights) => rxjs.merge(...highlights.map((highlight) => highlight.tap$))
|
|
214
|
-
)
|
|
215
|
-
);
|
|
216
|
-
annotations$.subscribe();
|
|
217
|
-
}
|
|
218
|
-
annotations$;
|
|
219
|
-
spineItem;
|
|
220
|
-
reader;
|
|
221
|
-
selectedHighlight;
|
|
222
|
-
layer;
|
|
223
|
-
highlights = [];
|
|
224
|
-
tap$;
|
|
225
|
-
layout() {
|
|
226
|
-
const firstLayerElement = this.spineItem.renderer.documentContainer ?? document.createElement("div");
|
|
227
|
-
layoutAnnotationLayer(firstLayerElement, this.layer);
|
|
228
|
-
return rxjs.forkJoin(
|
|
229
|
-
this.highlights.map((highlight) => highlight.render())
|
|
230
|
-
).pipe(rxjs.defaultIfEmpty(null));
|
|
231
|
-
}
|
|
232
|
-
getHighlightsForTarget(target) {
|
|
233
|
-
return this.highlights.filter(
|
|
234
|
-
(highlight) => target instanceof Node && highlight.isWithinTarget(target)
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
destroy() {
|
|
238
|
-
super.destroy();
|
|
239
|
-
this.layer.remove();
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
class ReaderHighlights extends core.DestroyableClass {
|
|
244
|
-
constructor(reader, highlights, selectedHighlight) {
|
|
245
|
-
super();
|
|
246
|
-
this.reader = reader;
|
|
247
|
-
this.highlights = highlights;
|
|
248
|
-
this.selectedHighlight = selectedHighlight;
|
|
249
|
-
const cleanupByItemId = /* @__PURE__ */ new Map();
|
|
250
|
-
this.reader.hookManager.register(
|
|
251
|
-
"item.onDocumentLoad",
|
|
252
|
-
async ({ itemId }) => {
|
|
253
|
-
cleanupByItemId.get(itemId)?.();
|
|
254
|
-
cleanupByItemId.delete(itemId);
|
|
255
|
-
const spineItem = reader.spineItemsManager.get(itemId);
|
|
256
|
-
if (!spineItem) return;
|
|
257
|
-
const spineItemHighlights$ = this.highlights.pipe(
|
|
258
|
-
rxjs.map(
|
|
259
|
-
(highlights2) => highlights2.filter(
|
|
260
|
-
(highlight) => highlight.itemIndex === spineItem.item.index
|
|
261
|
-
)
|
|
262
|
-
)
|
|
263
|
-
);
|
|
264
|
-
const spineItemHighlights = new SpineItemHighlights(
|
|
265
|
-
spineItemHighlights$,
|
|
266
|
-
spineItem,
|
|
267
|
-
reader,
|
|
268
|
-
this.selectedHighlight
|
|
269
|
-
);
|
|
270
|
-
this.spineItemHighlights.next([
|
|
271
|
-
...this.spineItemHighlights.getValue(),
|
|
272
|
-
spineItemHighlights
|
|
273
|
-
]);
|
|
274
|
-
const cleanup = () => {
|
|
275
|
-
this.spineItemHighlights.next(
|
|
276
|
-
this.spineItemHighlights.getValue().filter((layer) => layer !== spineItemHighlights)
|
|
277
|
-
);
|
|
278
|
-
spineItemHighlights.destroy();
|
|
279
|
-
};
|
|
280
|
-
cleanupByItemId.set(itemId, cleanup);
|
|
281
|
-
}
|
|
282
|
-
);
|
|
283
|
-
this.reader.hookManager.register(
|
|
284
|
-
"item.onDocumentUnload",
|
|
285
|
-
async ({ itemId }) => {
|
|
286
|
-
cleanupByItemId.get(itemId)?.();
|
|
287
|
-
cleanupByItemId.delete(itemId);
|
|
288
|
-
}
|
|
289
|
-
);
|
|
290
|
-
this.tap$ = this.spineItemHighlights.pipe(
|
|
291
|
-
rxjs.switchMap((layers) => rxjs.merge(...layers.map((layer) => layer.tap$)))
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
reader;
|
|
295
|
-
highlights;
|
|
296
|
-
selectedHighlight;
|
|
297
|
-
spineItemHighlights = new rxjs.BehaviorSubject([]);
|
|
298
|
-
tap$;
|
|
299
|
-
getHighlightsForTarget = (target) => {
|
|
300
|
-
return this.spineItemHighlights.getValue().flatMap((layer) => layer.getHighlightsForTarget(target)).map((annotation) => annotation.highlight);
|
|
301
|
-
};
|
|
302
|
-
isTargetWithinHighlight = (target) => {
|
|
303
|
-
return !!this.getHighlightsForTarget(target).length;
|
|
304
|
-
};
|
|
305
|
-
layout() {
|
|
306
|
-
return rxjs.forkJoin(
|
|
307
|
-
this.spineItemHighlights.value.map((item) => item.layout())
|
|
308
|
-
).pipe(rxjs.defaultIfEmpty(null));
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const m = () => {
|
|
313
|
-
if (!(typeof window > "u"))
|
|
314
|
-
return window;
|
|
315
|
-
};
|
|
316
|
-
function b() {
|
|
317
|
-
const e = m()?.__PROSE_READER_DEBUG;
|
|
318
|
-
return e === true || e === "true";
|
|
319
|
-
}
|
|
320
|
-
const E = (e, n) => typeof e == "boolean" ? {
|
|
321
|
-
enabled: e,
|
|
322
|
-
options: n
|
|
323
|
-
} : {
|
|
324
|
-
enabled: e?.enabled,
|
|
325
|
-
options: e ?? n
|
|
326
|
-
}, w = (e) => e.at(-1)?.color, u = (e) => {
|
|
327
|
-
if (!e.length)
|
|
328
|
-
return;
|
|
329
|
-
if (!e.some((o) => o.color))
|
|
330
|
-
return [e.map((o) => o.label).join(" ")];
|
|
331
|
-
let n = "";
|
|
332
|
-
const t = [];
|
|
333
|
-
for (const o of e)
|
|
334
|
-
n += `%c${n ? ` ${o.label}` : o.label}`, t.push(
|
|
335
|
-
o.color ? `color: ${o.color}` : ""
|
|
336
|
-
);
|
|
337
|
-
return [n, ...t];
|
|
338
|
-
}, p = (e = [], n = b()) => {
|
|
339
|
-
let t = n;
|
|
340
|
-
const o = {
|
|
341
|
-
enable: (c) => {
|
|
342
|
-
l(c);
|
|
343
|
-
},
|
|
344
|
-
namespace: (c, s, i) => {
|
|
345
|
-
const a = E(
|
|
346
|
-
s,
|
|
347
|
-
i
|
|
348
|
-
), g = a.options?.color ?? w(e);
|
|
349
|
-
return p(
|
|
350
|
-
[
|
|
351
|
-
...e,
|
|
352
|
-
{
|
|
353
|
-
label: `[${c}]`,
|
|
354
|
-
color: g
|
|
355
|
-
}
|
|
356
|
-
],
|
|
357
|
-
a.enabled ?? t
|
|
358
|
-
);
|
|
359
|
-
},
|
|
360
|
-
isEnabled: () => t,
|
|
361
|
-
debug: () => {
|
|
362
|
-
},
|
|
363
|
-
info: () => {
|
|
364
|
-
},
|
|
365
|
-
log: () => {
|
|
366
|
-
},
|
|
367
|
-
groupCollapsed: () => {
|
|
368
|
-
},
|
|
369
|
-
groupEnd: () => {
|
|
370
|
-
},
|
|
371
|
-
getGroupArgs: (c) => {
|
|
372
|
-
const s = u(e);
|
|
373
|
-
if (!s)
|
|
374
|
-
return [c];
|
|
375
|
-
const [i, ...a] = s;
|
|
376
|
-
return [`${i} ${c}`, ...a];
|
|
377
|
-
},
|
|
378
|
-
warn: () => {
|
|
379
|
-
},
|
|
380
|
-
error: () => {
|
|
381
|
-
}
|
|
382
|
-
}, r = (c) => {
|
|
383
|
-
if (!c) {
|
|
384
|
-
o.debug = () => {
|
|
385
|
-
}, o.info = () => {
|
|
386
|
-
}, o.log = () => {
|
|
387
|
-
}, o.groupCollapsed = () => {
|
|
388
|
-
}, o.groupEnd = () => {
|
|
389
|
-
}, o.warn = () => {
|
|
390
|
-
}, o.error = () => {
|
|
391
|
-
};
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
const s = u(e) ?? [];
|
|
395
|
-
o.debug = Function.prototype.bind.call(
|
|
396
|
-
console.debug,
|
|
397
|
-
console,
|
|
398
|
-
...s
|
|
399
|
-
), o.info = Function.prototype.bind.call(
|
|
400
|
-
console.info,
|
|
401
|
-
console,
|
|
402
|
-
...s
|
|
403
|
-
), o.log = Function.prototype.bind.call(
|
|
404
|
-
console.log,
|
|
405
|
-
console,
|
|
406
|
-
...s
|
|
407
|
-
), o.groupCollapsed = Function.prototype.bind.call(
|
|
408
|
-
console.groupCollapsed,
|
|
409
|
-
console
|
|
410
|
-
), o.groupEnd = Function.prototype.bind.call(console.groupEnd, console), o.warn = Function.prototype.bind.call(
|
|
411
|
-
console.warn,
|
|
412
|
-
console,
|
|
413
|
-
...s
|
|
414
|
-
), o.error = Function.prototype.bind.call(
|
|
415
|
-
console.error,
|
|
416
|
-
console,
|
|
417
|
-
...s
|
|
418
|
-
);
|
|
419
|
-
}, l = (c) => {
|
|
420
|
-
t !== c && (t = c, r(t));
|
|
421
|
-
};
|
|
422
|
-
return r(t), o;
|
|
423
|
-
}, M = p();
|
|
424
|
-
|
|
425
|
-
const name = "@prose-reader/enhancer-annotations";
|
|
426
|
-
|
|
427
|
-
const IS_DEBUG_ENABLED = true;
|
|
428
|
-
const report = M.namespace(name, IS_DEBUG_ENABLED);
|
|
429
|
-
|
|
430
|
-
class Settings extends core.ReactiveEntity {
|
|
431
|
-
update(settings) {
|
|
432
|
-
super.mergeCompare(settings);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
const annotationsEnhancer = (next) => (options) => {
|
|
437
|
-
const { annotations: annotationsOptions, ...rest } = options;
|
|
438
|
-
const settings = new Settings({
|
|
439
|
-
annotations$: annotationsOptions?.annotations$
|
|
440
|
-
});
|
|
441
|
-
const reader = next(rest);
|
|
442
|
-
const annotations$ = settings.watch("annotations$").pipe(rxjs.switchMap((annotations) => annotations ?? rxjs.NEVER));
|
|
443
|
-
const runtimeAnnotations$ = annotations$.pipe(
|
|
444
|
-
rxjs.distinctUntilChanged(core.isShallowEqual),
|
|
445
|
-
rxjs.map((annotations) => {
|
|
446
|
-
const runtimeAnnotations = annotations.map(
|
|
447
|
-
(annotation) => {
|
|
448
|
-
const { itemIndex = 0 } = reader.cfi.parseCfi(annotation.cfi ?? "");
|
|
449
|
-
const highlight = {
|
|
450
|
-
...annotation,
|
|
451
|
-
itemIndex
|
|
452
|
-
};
|
|
453
|
-
return highlight;
|
|
454
|
-
}
|
|
455
|
-
);
|
|
456
|
-
return runtimeAnnotations;
|
|
457
|
-
}),
|
|
458
|
-
rxjs.tap((annotations) => {
|
|
459
|
-
report.debug("annotations", annotations);
|
|
460
|
-
}),
|
|
461
|
-
rxjs.shareReplay({
|
|
462
|
-
refCount: true,
|
|
463
|
-
bufferSize: 1
|
|
464
|
-
})
|
|
465
|
-
);
|
|
466
|
-
const selectedHighlight$ = runtimeAnnotations$.pipe(
|
|
467
|
-
rxjs.map(
|
|
468
|
-
(annotations) => annotations.find((annotation) => annotation.selected)?.id
|
|
469
|
-
),
|
|
470
|
-
rxjs.distinctUntilChanged(),
|
|
471
|
-
rxjs.shareReplay({ refCount: true, bufferSize: 1 })
|
|
472
|
-
);
|
|
473
|
-
const readerHighlights = new ReaderHighlights(
|
|
474
|
-
reader,
|
|
475
|
-
runtimeAnnotations$,
|
|
476
|
-
selectedHighlight$
|
|
477
|
-
);
|
|
478
|
-
const resolveItemInformation = (params) => {
|
|
479
|
-
if (params.itemIndex !== void 0)
|
|
480
|
-
return { itemIndex: params.itemIndex, pageIndex: void 0 };
|
|
481
|
-
if (params.absolutePageIndex !== void 0) {
|
|
482
|
-
return reader.spine.pages.fromAbsolutePageIndex(
|
|
483
|
-
params.absolutePageIndex
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
return void 0;
|
|
487
|
-
};
|
|
488
|
-
const createAnnotation = ({
|
|
489
|
-
selection,
|
|
490
|
-
...rest2
|
|
491
|
-
}) => {
|
|
492
|
-
const { itemIndex, pageIndex = 0 } = resolveItemInformation(rest2) ?? {};
|
|
493
|
-
const spineItem = reader.spineItemsManager.get(itemIndex);
|
|
494
|
-
const id = window.crypto.randomUUID();
|
|
495
|
-
if (!spineItem) return void 0;
|
|
496
|
-
const range = selection ? reader.selection.createOrderedRangeFromSelection({
|
|
497
|
-
selection,
|
|
498
|
-
spineItem
|
|
499
|
-
}) : void 0;
|
|
500
|
-
const pageEntry = reader.spine.pages.fromSpineItemPageIndex(
|
|
501
|
-
spineItem,
|
|
502
|
-
pageIndex
|
|
503
|
-
);
|
|
504
|
-
const cfiWithRangeOrFirstNodeOrRoot = range ? reader.cfi.generateCfiFromRange(range, spineItem.item) : pageEntry?.firstVisibleNode ? reader.cfi.generateCfiForSpineItemPage({
|
|
505
|
-
spineItem: spineItem.item,
|
|
506
|
-
pageNode: pageEntry.firstVisibleNode
|
|
507
|
-
}) : reader.cfi.generateRootCfi(spineItem.item);
|
|
508
|
-
const highlight = {
|
|
509
|
-
cfi: cfiWithRangeOrFirstNodeOrRoot,
|
|
510
|
-
itemIndex: spineItem.index,
|
|
511
|
-
id,
|
|
512
|
-
...rest2
|
|
513
|
-
};
|
|
514
|
-
return highlight;
|
|
515
|
-
};
|
|
516
|
-
const renderAnnotations$ = rxjs.merge(runtimeAnnotations$, reader.layout$).pipe(
|
|
517
|
-
rxjs.debounceTime(50),
|
|
518
|
-
rxjs.switchMap(() => readerHighlights.layout())
|
|
519
|
-
);
|
|
520
|
-
const candidates$ = reader.layoutInfo$.pipe(
|
|
521
|
-
rxjs.switchMap(
|
|
522
|
-
({ pages }) => rxjs.combineLatest(
|
|
523
|
-
pages.map((page) => {
|
|
524
|
-
const item = reader.spineItemsManager.get(page.itemIndex);
|
|
525
|
-
if (!item) return rxjs.of(false);
|
|
526
|
-
if (item.renditionLayout === "pre-paginated") return rxjs.of(true);
|
|
527
|
-
if (page.firstVisibleNode) return rxjs.of(true);
|
|
528
|
-
return rxjs.of(false);
|
|
529
|
-
})
|
|
530
|
-
)
|
|
531
|
-
)
|
|
532
|
-
);
|
|
533
|
-
rxjs.merge(renderAnnotations$, annotations$).pipe(rxjs.takeUntil(reader.$.destroy$)).subscribe();
|
|
534
|
-
return {
|
|
535
|
-
...reader,
|
|
536
|
-
__PROSE_READER_ENHANCER_ANNOTATIONS: true,
|
|
537
|
-
destroy: () => {
|
|
538
|
-
readerHighlights.destroy();
|
|
539
|
-
reader.destroy();
|
|
540
|
-
},
|
|
541
|
-
annotations: {
|
|
542
|
-
annotations$: runtimeAnnotations$,
|
|
543
|
-
highlightTap$: readerHighlights.tap$,
|
|
544
|
-
candidates$,
|
|
545
|
-
isTargetWithinHighlight: readerHighlights.isTargetWithinHighlight,
|
|
546
|
-
createAnnotation,
|
|
547
|
-
update: settings.update.bind(settings)
|
|
548
|
-
}
|
|
549
|
-
};
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
exports.annotationsEnhancer = annotationsEnhancer;
|
|
553
|
-
|
|
554
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
555
|
-
|
|
556
|
-
}));
|
|
557
|
-
//# sourceMappingURL=index.umd.cjs.map
|
|
13
|
+
background-color: ${n}
|
|
14
|
+
`,s.appendChild(c),s})},i=(e,n)=>{(0,t.setPropertyIfChanged)(n.style,`cssText`,e.style.cssText)},a=(e,t)=>{let n=e.ownerDocument.createElement(`div`);return o(t,n),e.appendChild(n),n},o=(e,n)=>{i(e,n),e.style.position===``&&((0,t.setStylePropertyIfChanged)(n.style,`position`,`absolute`),(0,t.setStylePropertyIfChanged)(n.style,`top`,`0`)),(0,t.setStylePropertyIfChanged)(n.style,`opacity`,`1`),(0,t.setStylePropertyIfChanged)(n.style,`pointer-events`,`none`)},s=class extends t.DestroyableClass{spineItem;containerElement;reader;highlight;isSelected;container;tap$;resolvedCfi$;constructor(e,t,r,i,a){super(),this.spineItem=e,this.containerElement=t,this.reader=r,this.highlight=i,this.isSelected=a,this.spineItem,this.reader,this.container=this.containerElement.ownerDocument.createElement(`div`),this.container.dataset.highlightContainer=this.highlight.id,this.containerElement.appendChild(this.container),this.tap$=(0,n.fromEvent)(this.container,`click`).pipe((0,n.map)(e=>({event:e,highlight:this.highlight})),(0,n.share)()),this.resolvedCfi$=this.spineItem.watch(`isLoaded`).pipe((0,n.map)(()=>this.reader.cfi.resolveCfi({cfi:this.highlight.cfi})),(0,n.shareReplay)({refCount:!0,bufferSize:1}));let o=this.isSelected.pipe((0,n.tap)(e=>{this.updateStateOnSelection(e)}));(0,n.merge)(this.resolvedCfi$,o).pipe((0,n.takeUntil)(this.destroy$)).subscribe()}updateStateOnSelection(e){Array.from(this.container.children).forEach(n=>{n instanceof HTMLElement&&(0,t.setStylePropertyIfChanged)(n.style,`border`,e?`3px dashed red`:`3px dashed transparent`)})}render(){return this.resolvedCfi$.pipe((0,n.first)(),(0,n.withLatestFrom)(this.isSelected),(0,n.map)(([e,t])=>{if(!e?.isCfiRange)return;let n=e.range;if(this.container.innerHTML=``,!n)return;let i=r(n,this.container,this.highlight.highlightColor??`yellow`);i.forEach(e=>{e.style.pointerEvents=`initial`,e.style.cursor=`pointer`,e.dataset.highlightRect=this.highlight.id,this.container.appendChild(e)});let a=i[0];if(a&&this.highlight.notes){let e=document.createElement(`span`);e.textContent=`📝`,e.style.position=`absolute`,e.style.top=`0`,e.style.left=`0`,e.style.transform=`translate(-0%, -80%)`,e.style.fontSize=`18px`,e.style.opacity=`50%`,a.appendChild(e)}return this.updateStateOnSelection(t),null}))}isWithinTarget(e){return this.container.contains(e)}destroy(){super.destroy(),this.container.remove()}},c=class extends t.DestroyableClass{annotations$;spineItem;reader;selectedHighlight;layer;highlights=[];tap$;constructor(e,t,r,i){super(),this.annotations$=e,this.spineItem=t,this.reader=r,this.selectedHighlight=i;let o=t.renderer.documentContainer??document.createElement(`div`);this.layer=a(this.spineItem.containerElement,o);let c=this.annotations$.pipe((0,n.switchMap)(e=>{let t=e.filter(e=>!this.highlights.some(t=>t.highlight.id===e.id)),r=this.highlights.filter(e=>e.highlight.itemIndex!==this.spineItem.item.index);return this.highlights.forEach((t,n)=>{let i=e.find(e=>e.id===t.highlight.id);r.includes(t)&&(t.destroy(),this.highlights=this.highlights.splice(n,1)),i&&(t.highlight=i)}),t.forEach(e=>{if(e.itemIndex!==this.spineItem.item.index)return;let t=this.selectedHighlight.pipe((0,n.map)(t=>t===e.id),(0,n.distinctUntilChanged)()),r=new s(this.spineItem,this.layer,this.reader,e,t);this.highlights.push(r)}),(0,n.of)(this.highlights)}),(0,n.shareReplay)(1),(0,n.takeUntil)(this.destroy$));this.tap$=c.pipe((0,n.switchMap)(e=>(0,n.merge)(...e.map(e=>e.tap$)))),e.subscribe()}layout(){return o(this.spineItem.renderer.documentContainer??document.createElement(`div`),this.layer),(0,n.forkJoin)(this.highlights.map(e=>e.render())).pipe((0,n.defaultIfEmpty)(null))}getHighlightsForTarget(e){return this.highlights.filter(t=>e instanceof Node&&t.isWithinTarget(e))}destroy(){super.destroy(),this.layer.remove()}},l=class extends t.DestroyableClass{reader;highlights;selectedHighlight;spineItemHighlights=new n.BehaviorSubject([]);tap$;constructor(e,t,r){super(),this.reader=e,this.highlights=t,this.selectedHighlight=r;let i=new Map;this.reader.hookManager.register(`item.onDocumentLoad`,async({itemId:t})=>{i.get(t)?.(),i.delete(t);let r=e.spineItemsManager.get(t);if(!r)return;let a=new c(this.highlights.pipe((0,n.map)(e=>e.filter(e=>e.itemIndex===r.item.index))),r,e,this.selectedHighlight);this.spineItemHighlights.next([...this.spineItemHighlights.getValue(),a]),i.set(t,()=>{this.spineItemHighlights.next(this.spineItemHighlights.getValue().filter(e=>e!==a)),a.destroy()})}),this.reader.hookManager.register(`item.onDocumentUnload`,async({itemId:e})=>{i.get(e)?.(),i.delete(e)}),this.tap$=this.spineItemHighlights.pipe((0,n.switchMap)(e=>(0,n.merge)(...e.map(e=>e.tap$))))}getHighlightsForTarget=e=>this.spineItemHighlights.getValue().flatMap(t=>t.getHighlightsForTarget(e)).map(e=>e.highlight);isTargetWithinHighlight=e=>!!this.getHighlightsForTarget(e).length;layout(){return(0,n.forkJoin)(this.spineItemHighlights.value.map(e=>e.layout())).pipe((0,n.defaultIfEmpty)(null))}},u=()=>{if(!(typeof window>`u`))return window};function d(){let e=u()?.__PROSE_READER_DEBUG;return e===!0||e===`true`}var f=(e,t)=>typeof e==`boolean`?{enabled:e,options:t}:{enabled:e?.enabled,options:e??t},p=e=>e.at(-1)?.color,m=e=>{if(!e.length)return;if(!e.some(e=>e.color))return[e.map(e=>e.label).join(` `)];let t=``,n=[];for(let r of e)t+=`%c${t?` ${r.label}`:r.label}`,n.push(r.color?`color: ${r.color}`:``);return[t,...n]},h=(e=[],t=d())=>{let n=t,r={enable:e=>{a(e)},namespace:(t,r,i)=>{let a=f(r,i),o=a.options?.color??p(e);return h([...e,{label:`[${t}]`,color:o}],a.enabled??n)},isEnabled:()=>n,debug:()=>{},info:()=>{},log:()=>{},groupCollapsed:()=>{},groupEnd:()=>{},getGroupArgs:t=>{let n=m(e);if(!n)return[t];let[r,...i]=n;return[`${r} ${t}`,...i]},warn:()=>{},error:()=>{}},i=t=>{if(!t){r.debug=()=>{},r.info=()=>{},r.log=()=>{},r.groupCollapsed=()=>{},r.groupEnd=()=>{},r.warn=()=>{},r.error=()=>{};return}let n=m(e)??[];r.debug=Function.prototype.bind.call(console.debug,console,...n),r.info=Function.prototype.bind.call(console.info,console,...n),r.log=Function.prototype.bind.call(console.log,console,...n),r.groupCollapsed=Function.prototype.bind.call(console.groupCollapsed,console),r.groupEnd=Function.prototype.bind.call(console.groupEnd,console),r.warn=Function.prototype.bind.call(console.warn,console,...n),r.error=Function.prototype.bind.call(console.error,console,...n)},a=e=>{n!==e&&(n=e,i(n))};return i(n),r},g=h().namespace(`@prose-reader/enhancer-annotations`,!0),_=class extends t.ReactiveEntity{update(e){super.mergeCompare(e)}};e.annotationsEnhancer=e=>r=>{let{annotations:i,...a}=r,o=new _({annotations$:i?.annotations$}),s=e(a),c=o.watch(`annotations$`).pipe((0,n.switchMap)(e=>e??n.NEVER)),u=c.pipe((0,n.distinctUntilChanged)(t.isShallowEqual),(0,n.map)(e=>e.map(e=>{let{itemIndex:t=0}=s.cfi.parseCfi(e.cfi??``);return{...e,itemIndex:t}})),(0,n.tap)(e=>{g.debug(`annotations`,e)}),(0,n.shareReplay)({refCount:!0,bufferSize:1})),d=new l(s,u,u.pipe((0,n.map)(e=>e.find(e=>e.selected)?.id),(0,n.distinctUntilChanged)(),(0,n.shareReplay)({refCount:!0,bufferSize:1}))),f=e=>{if(e.itemIndex!==void 0)return{itemIndex:e.itemIndex,pageIndex:void 0};if(e.absolutePageIndex!==void 0)return s.spine.pages.fromAbsolutePageIndex(e.absolutePageIndex)},p=({selection:e,...t})=>{let{itemIndex:n,pageIndex:r=0}=f(t)??{},i=s.spineItemsManager.get(n),a=window.crypto.randomUUID();if(!i)return;let o=e?s.selection.createOrderedRangeFromSelection({selection:e,spineItem:i}):void 0,c=s.spine.pages.fromSpineItemPageIndex(i,r);return{cfi:o?s.cfi.generateCfiFromRange(o,i.item):c?.firstVisibleNode?s.cfi.generateCfiForSpineItemPage({spineItem:i.item,pageNode:c.firstVisibleNode}):s.cfi.generateRootCfi(i.item),itemIndex:i.index,id:a,...t}},m=(0,n.merge)(u,s.layout$).pipe((0,n.debounceTime)(50),(0,n.switchMap)(()=>d.layout())),h=s.layoutInfo$.pipe((0,n.switchMap)(({pages:e})=>(0,n.combineLatest)(e.map(e=>{let t=s.spineItemsManager.get(e.itemIndex);return t&&(t.renditionLayout===`pre-paginated`||e.firstVisibleNode)?(0,n.of)(!0):(0,n.of)(!1)}))));return(0,n.merge)(m,c).pipe((0,n.takeUntil)(s.$.destroy$)).subscribe(),{...s,__PROSE_READER_ENHANCER_ANNOTATIONS:!0,destroy:()=>{d.destroy(),s.destroy()},annotations:{annotations$:u,highlightTap$:d.tap$,candidates$:h,isTargetWithinHighlight:d.isTargetWithinHighlight,createAnnotation:p,update:o.update.bind(o)}}}});
|
|
15
|
+
//# sourceMappingURL=index.umd.cjs.map
|