@laminapdf/viewer 0.2.0-alpha.4 → 0.2.0-alpha.6
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/README.md +79 -10
- package/dist/client.d.ts +60 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +241 -22
- package/dist/client.js.map +1 -1
- package/dist/edit/session.d.ts +91 -0
- package/dist/edit/session.d.ts.map +1 -0
- package/dist/edit/session.js +179 -0
- package/dist/edit/session.js.map +1 -0
- package/dist/edit-log.d.ts +32 -0
- package/dist/edit-log.d.ts.map +1 -0
- package/dist/edit-log.js +74 -0
- package/dist/edit-log.js.map +1 -0
- package/dist/find/controller.d.ts +6 -0
- package/dist/find/controller.d.ts.map +1 -1
- package/dist/find/controller.js +69 -2
- package/dist/find/controller.js.map +1 -1
- package/dist/first-draw.d.ts +10 -0
- package/dist/first-draw.d.ts.map +1 -0
- package/dist/first-draw.js +33 -0
- package/dist/first-draw.js.map +1 -0
- package/dist/history/history.d.ts +74 -0
- package/dist/history/history.d.ts.map +1 -0
- package/dist/history/history.js +135 -0
- package/dist/history/history.js.map +1 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/layers/copy.d.ts +26 -0
- package/dist/layers/copy.d.ts.map +1 -0
- package/dist/layers/copy.js +150 -0
- package/dist/layers/copy.js.map +1 -0
- package/dist/layers/link-layer.d.ts +101 -0
- package/dist/layers/link-layer.d.ts.map +1 -0
- package/dist/layers/link-layer.js +527 -0
- package/dist/layers/link-layer.js.map +1 -0
- package/dist/layers/link-preview.d.ts +77 -0
- package/dist/layers/link-preview.d.ts.map +1 -0
- package/dist/layers/link-preview.js +202 -0
- package/dist/layers/link-preview.js.map +1 -0
- package/dist/layers/link-url.d.ts +19 -0
- package/dist/layers/link-url.d.ts.map +1 -0
- package/dist/layers/link-url.js +47 -0
- package/dist/layers/link-url.js.map +1 -0
- package/dist/layers/spans.d.ts +0 -6
- package/dist/layers/spans.d.ts.map +1 -1
- package/dist/layers/spans.js +2 -20
- package/dist/layers/spans.js.map +1 -1
- package/dist/layers/structure-layer.d.ts.map +1 -1
- package/dist/layers/structure-layer.js +3 -0
- package/dist/layers/structure-layer.js.map +1 -1
- package/dist/layers/text-layer.d.ts +27 -6
- package/dist/layers/text-layer.d.ts.map +1 -1
- package/dist/layers/text-layer.js +310 -28
- package/dist/layers/text-layer.js.map +1 -1
- package/dist/layout/page-layout.d.ts +7 -0
- package/dist/layout/page-layout.d.ts.map +1 -1
- package/dist/layout/page-layout.js +15 -0
- package/dist/layout/page-layout.js.map +1 -1
- package/dist/protocol.d.ts +197 -5
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +33 -6
- package/dist/protocol.js.map +1 -1
- package/dist/source/opfs.d.ts +35 -0
- package/dist/source/opfs.d.ts.map +1 -0
- package/dist/source/opfs.js +178 -0
- package/dist/source/opfs.js.map +1 -0
- package/dist/thumbnails/strip.d.ts +1 -1
- package/dist/thumbnails/strip.d.ts.map +1 -1
- package/dist/thumbnails/strip.js +48 -4
- package/dist/thumbnails/strip.js.map +1 -1
- package/dist/view/previews.d.ts +47 -0
- package/dist/view/previews.d.ts.map +1 -0
- package/dist/view/previews.js +97 -0
- package/dist/view/previews.js.map +1 -0
- package/dist/view/user-select.d.ts +3 -0
- package/dist/view/user-select.d.ts.map +1 -0
- package/dist/view/user-select.js +10 -0
- package/dist/view/user-select.js.map +1 -0
- package/dist/view/viewer.d.ts +143 -5
- package/dist/view/viewer.d.ts.map +1 -1
- package/dist/view/viewer.js +590 -50
- package/dist/view/viewer.js.map +1 -1
- package/dist/worker/document.d.ts +66 -6
- package/dist/worker/document.d.ts.map +1 -1
- package/dist/worker/document.js +139 -23
- package/dist/worker/document.js.map +1 -1
- package/dist/worker/edit.d.ts +35 -0
- package/dist/worker/edit.d.ts.map +1 -0
- package/dist/worker/edit.js +305 -0
- package/dist/worker/edit.js.map +1 -0
- package/dist/worker/find.d.ts +2 -2
- package/dist/worker/find.d.ts.map +1 -1
- package/dist/worker/find.js +8 -21
- package/dist/worker/find.js.map +1 -1
- package/dist/worker/fingerprint.d.ts +10 -0
- package/dist/worker/fingerprint.d.ts.map +1 -0
- package/dist/worker/fingerprint.js +42 -0
- package/dist/worker/fingerprint.js.map +1 -0
- package/dist/worker/methods.d.ts.map +1 -1
- package/dist/worker/methods.js +42 -4
- package/dist/worker/methods.js.map +1 -1
- package/dist/worker/navigation.d.ts +5 -1
- package/dist/worker/navigation.d.ts.map +1 -1
- package/dist/worker/navigation.js +22 -4
- package/dist/worker/navigation.js.map +1 -1
- package/dist/worker/print.d.ts +14 -0
- package/dist/worker/print.d.ts.map +1 -0
- package/dist/worker/print.js +49 -0
- package/dist/worker/print.js.map +1 -0
- package/dist/worker/recent-pages.d.ts +16 -0
- package/dist/worker/recent-pages.d.ts.map +1 -0
- package/dist/worker/recent-pages.js +68 -0
- package/dist/worker/recent-pages.js.map +1 -0
- package/dist/worker/render.d.ts.map +1 -1
- package/dist/worker/render.js +5 -2
- package/dist/worker/render.js.map +1 -1
- package/dist/worker/session.d.ts +59 -0
- package/dist/worker/session.d.ts.map +1 -0
- package/dist/worker/session.js +152 -0
- package/dist/worker/session.js.map +1 -0
- package/dist/worker/text.d.ts +11 -3
- package/dist/worker/text.d.ts.map +1 -1
- package/dist/worker/text.js +33 -25
- package/dist/worker/text.js.map +1 -1
- package/package.json +9 -8
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
// The link layer (web-app §6 C6, R07): on every mounted page, an anchor over each of Lamina PDF's
|
|
2
|
+
// links, in the page's `lamina-layer-annot` slot, above the text and below the find highlights.
|
|
3
|
+
// Like the other layers, the anchors sit in page points inside one box that a CSS transform scales
|
|
4
|
+
// and turns to the page. Only the anchors take pointer events, so text around a link still selects.
|
|
5
|
+
// Anchors follow page order, so Tab moves through a page's links in order, then the next page's.
|
|
6
|
+
// While a drag that started outside every link is under way, no anchor takes pointer events, so a
|
|
7
|
+
// selection begun in the text runs on over the text under a link.
|
|
8
|
+
//
|
|
9
|
+
// What a link does is decided here, never by the browser: a primary click or Enter is always
|
|
10
|
+
// handled (`preventDefault`). A link inside the document goes there through the viewer (a history
|
|
11
|
+
// jump); its `href` is the app's address for that page, so a middle click or "Open in new tab"
|
|
12
|
+
// opens the same document there. A web or email link asks the app to confirm first, on a click,
|
|
13
|
+
// a middle click or Enter. It has no `href`, so no browser menu ("Open in new tab") can open it
|
|
14
|
+
// without asking; its title shows the address. Anything else (another file, an action a reader
|
|
15
|
+
// never runs, a refused scheme, a broken destination) has no `href` either, does nothing, and
|
|
16
|
+
// says why on hover.
|
|
17
|
+
//
|
|
18
|
+
// Previews (R07): a link inside the document, a standard page action or a link to another
|
|
19
|
+
// file asks its viewer to preview it. With a mouse or pen, 300 ms after the pointer comes onto it,
|
|
20
|
+
// and the preview ends 300 ms after the pointer leaves both the link and the preview (which holds it
|
|
21
|
+
// while hovered, WCAG 1.4.13). With the keyboard, 300 ms after it takes visible focus, ending on blur.
|
|
22
|
+
// With touch, on a long-press of 500 ms that moves less than 10 CSS px: the click that would follow
|
|
23
|
+
// is cancelled, the press selects no text, and the OS's link menu stays shut. Web links never preview:
|
|
24
|
+
// they ask before opening, and their page is never fetched (ADR 0011).
|
|
25
|
+
import { placeBox } from "./box.js";
|
|
26
|
+
import { externalLink } from "./link-url.js";
|
|
27
|
+
/** English, for a viewer whose app gives none. */
|
|
28
|
+
const ENGLISH = {
|
|
29
|
+
page: (page) => `Link to page ${page + 1}`,
|
|
30
|
+
nextPage: "Goes to the next page",
|
|
31
|
+
previousPage: "Goes to the previous page",
|
|
32
|
+
firstPage: "Goes to the first page",
|
|
33
|
+
lastPage: "Goes to the last page",
|
|
34
|
+
otherFile: (file) => file === undefined
|
|
35
|
+
? "Links to another file, which can't be opened from here"
|
|
36
|
+
: `Links to another file, ${file}, which can't be opened from here`,
|
|
37
|
+
refused: (uri) => `This link's address can't be opened: ${uri}`,
|
|
38
|
+
unsupported: "This link asks to run an action. The reader never runs these.",
|
|
39
|
+
broken: "This link's destination isn't in the document",
|
|
40
|
+
};
|
|
41
|
+
/** How long a link is hovered or focused before its preview shows, and after it is left before it goes (ms). */
|
|
42
|
+
const PREVIEW_DWELL_MS = 300;
|
|
43
|
+
/** How long a finger rests on a link before its preview opens (ms). */
|
|
44
|
+
const PREVIEW_LONG_PRESS_MS = 500;
|
|
45
|
+
/** How far a finger may move (CSS px) and still long-press. */
|
|
46
|
+
const PREVIEW_SLOP = 10;
|
|
47
|
+
/** The page a standard named action goes to from page `page` of `count`, and its words. */
|
|
48
|
+
function namedAction(name, page, count, words) {
|
|
49
|
+
switch (name) {
|
|
50
|
+
case "NextPage":
|
|
51
|
+
return { page: Math.min(count - 1, page + 1), label: words.nextPage };
|
|
52
|
+
case "PrevPage":
|
|
53
|
+
return { page: Math.max(0, page - 1), label: words.previousPage };
|
|
54
|
+
case "FirstPage":
|
|
55
|
+
return { page: 0, label: words.firstPage };
|
|
56
|
+
case "LastPage":
|
|
57
|
+
return { page: count - 1, label: words.lastPage };
|
|
58
|
+
default:
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** The selector every link anchor matches. */
|
|
63
|
+
const ANCHOR = "a.lamina-link";
|
|
64
|
+
/** The link anchor `target` is in, if any. */
|
|
65
|
+
function anchorOf(target) {
|
|
66
|
+
const anchor = target instanceof Element ? target.closest(ANCHOR) : null;
|
|
67
|
+
return anchor instanceof HTMLElement ? anchor : undefined;
|
|
68
|
+
}
|
|
69
|
+
/** What a link that does nothing means: named and noted by `note`. */
|
|
70
|
+
function inert(link, note) {
|
|
71
|
+
return { follow: { kind: "none", link, note }, label: note, note };
|
|
72
|
+
}
|
|
73
|
+
/** The box around eight-number quads (or the rectangle, without any), in page points. */
|
|
74
|
+
function areas(link) {
|
|
75
|
+
const out = [];
|
|
76
|
+
const q = link.quads ?? [];
|
|
77
|
+
for (let at = 0; at + 8 <= q.length; at += 8) {
|
|
78
|
+
const xs = [q[at], q[at + 2], q[at + 4], q[at + 6]].map((v) => v ?? 0);
|
|
79
|
+
const ys = [q[at + 1], q[at + 3], q[at + 5], q[at + 7]].map((v) => v ?? 0);
|
|
80
|
+
const x = Math.min(...xs);
|
|
81
|
+
const y = Math.min(...ys);
|
|
82
|
+
out.push({ x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y });
|
|
83
|
+
}
|
|
84
|
+
if (out.length > 0)
|
|
85
|
+
return out;
|
|
86
|
+
const [x0, y0, x1, y1] = link.rect;
|
|
87
|
+
return [{ x: Math.min(x0, x1), y: Math.min(y0, y1), width: Math.abs(x1 - x0), height: Math.abs(y1 - y0) }];
|
|
88
|
+
}
|
|
89
|
+
/** The link layer of one viewer. */
|
|
90
|
+
export class LinkLayer {
|
|
91
|
+
name = "annot";
|
|
92
|
+
#host;
|
|
93
|
+
#options;
|
|
94
|
+
#words;
|
|
95
|
+
#pages = new Map();
|
|
96
|
+
#follows = new WeakMap();
|
|
97
|
+
#links = new WeakMap();
|
|
98
|
+
#listening = new AbortController();
|
|
99
|
+
/** The dwell, grace or long-press timer. */
|
|
100
|
+
#timer;
|
|
101
|
+
/** The anchor whose preview shows, and how it was asked for. */
|
|
102
|
+
#shown;
|
|
103
|
+
/** The anchor the dwell or long-press timer is for. */
|
|
104
|
+
#pending;
|
|
105
|
+
/** The pointer is over the preview: it stays. */
|
|
106
|
+
#held = false;
|
|
107
|
+
/** The anchor under a fine pointer, if any. */
|
|
108
|
+
#hovered;
|
|
109
|
+
/** An anchor whose preview Escape closed: it shows again only after the pointer or focus leaves it. */
|
|
110
|
+
#dismissed;
|
|
111
|
+
/** A touch on an anchor: where it started. */
|
|
112
|
+
#press;
|
|
113
|
+
/** A long-press opened a preview: the click its lift sends is cancelled. */
|
|
114
|
+
#swallowClick = false;
|
|
115
|
+
/** The last pointer that went down was a finger (for `contextmenu`, which says nothing of it). */
|
|
116
|
+
#touching = false;
|
|
117
|
+
constructor(host, options = {}) {
|
|
118
|
+
this.#host = host;
|
|
119
|
+
this.#options = options;
|
|
120
|
+
this.#words = options.words ?? ENGLISH;
|
|
121
|
+
const { signal } = this.#listening;
|
|
122
|
+
host.root.addEventListener("pointerdown", (e) => {
|
|
123
|
+
if (e.button === 0 && !this.#followOf(e))
|
|
124
|
+
this.#passThrough(true);
|
|
125
|
+
}, { signal });
|
|
126
|
+
for (const end of ["pointerup", "pointercancel"]) {
|
|
127
|
+
document.addEventListener(end, () => this.#passThrough(false), { signal });
|
|
128
|
+
}
|
|
129
|
+
// A button released outside the window may send no pointerup: leaving the window ends the drag too.
|
|
130
|
+
window.addEventListener("blur", () => this.#passThrough(false), { signal });
|
|
131
|
+
}
|
|
132
|
+
/** Stops listening: the viewer is going. */
|
|
133
|
+
destroy() {
|
|
134
|
+
clearTimeout(this.#timer);
|
|
135
|
+
this.#listening.abort();
|
|
136
|
+
}
|
|
137
|
+
/** The pointer is over the preview (`true`) or has left it (`false`): a hovered preview stays. */
|
|
138
|
+
hold(held) {
|
|
139
|
+
this.#held = held;
|
|
140
|
+
if (held) {
|
|
141
|
+
if (this.#shown !== undefined)
|
|
142
|
+
clearTimeout(this.#timer);
|
|
143
|
+
}
|
|
144
|
+
else if (this.#shown?.pointer === "fine" && this.#hovered !== this.#shown.anchor) {
|
|
145
|
+
this.#later(PREVIEW_DWELL_MS, () => this.#end());
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** Escape or Close: hides the preview, which stays hidden until its link is left. */
|
|
149
|
+
dismiss() {
|
|
150
|
+
this.#dismissed = this.#shown?.anchor ?? this.#pending;
|
|
151
|
+
this.#cancel();
|
|
152
|
+
this.#end();
|
|
153
|
+
}
|
|
154
|
+
/** The previewed link, else the focused one: what `follow` would follow. */
|
|
155
|
+
#followable() {
|
|
156
|
+
const anchor = this.#shown?.anchor ?? anchorOf(document.activeElement);
|
|
157
|
+
return anchor?.isConnected === true ? anchor : undefined;
|
|
158
|
+
}
|
|
159
|
+
/** Whether a link is previewed or focused, so `follow` has one to follow. */
|
|
160
|
+
canFollow() {
|
|
161
|
+
return this.#followable() !== undefined;
|
|
162
|
+
}
|
|
163
|
+
/** Follows the previewed link, else the focused one (`nav.follow-link`); `false` when there is neither. */
|
|
164
|
+
follow() {
|
|
165
|
+
const anchor = this.#followable();
|
|
166
|
+
if (anchor === undefined)
|
|
167
|
+
return false;
|
|
168
|
+
this.#cancel();
|
|
169
|
+
this.#end();
|
|
170
|
+
// A long-press's lift may have sent no click: this one is not that click.
|
|
171
|
+
this.#swallowClick = false;
|
|
172
|
+
anchor.click();
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
#later(ms, run) {
|
|
176
|
+
clearTimeout(this.#timer);
|
|
177
|
+
this.#timer = setTimeout(run, ms);
|
|
178
|
+
}
|
|
179
|
+
#cancel() {
|
|
180
|
+
clearTimeout(this.#timer);
|
|
181
|
+
this.#timer = undefined;
|
|
182
|
+
this.#pending = undefined;
|
|
183
|
+
}
|
|
184
|
+
/** Asks for `anchor`'s preview, if its link has one. */
|
|
185
|
+
#show(anchor, pointer) {
|
|
186
|
+
this.#pending = undefined;
|
|
187
|
+
const link = this.#links.get(anchor);
|
|
188
|
+
const follow = this.#follows.get(anchor);
|
|
189
|
+
if (!anchor.isConnected || link === undefined || follow === undefined)
|
|
190
|
+
return;
|
|
191
|
+
const shows = this.#shows(link, follow);
|
|
192
|
+
if (shows === undefined)
|
|
193
|
+
return;
|
|
194
|
+
if (this.#shown !== undefined && this.#shown.anchor !== anchor)
|
|
195
|
+
this.#end();
|
|
196
|
+
this.#shown = { anchor, pointer };
|
|
197
|
+
this.#host.preview?.({ link, shows, anchor, pointer });
|
|
198
|
+
}
|
|
199
|
+
/** Hides the preview. */
|
|
200
|
+
#end() {
|
|
201
|
+
const shown = this.#shown;
|
|
202
|
+
if (shown === undefined)
|
|
203
|
+
return;
|
|
204
|
+
this.#shown = undefined;
|
|
205
|
+
this.#held = false;
|
|
206
|
+
this.#host.previewEnd?.(shown.anchor);
|
|
207
|
+
}
|
|
208
|
+
/** What a preview of `link` shows; `undefined` for a link that has none (web links, inert ones). */
|
|
209
|
+
#shows(link, follow) {
|
|
210
|
+
switch (follow.kind) {
|
|
211
|
+
case "target":
|
|
212
|
+
return { kind: "target", target: follow.target };
|
|
213
|
+
case "page":
|
|
214
|
+
return { kind: "page", page: follow.page, note: follow.label };
|
|
215
|
+
case "none":
|
|
216
|
+
return link.kind === "remote" ? { kind: "note", note: follow.note } : undefined;
|
|
217
|
+
default:
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/** Listens on one page's links for what asks for a preview: the mouse, focus and touch. */
|
|
222
|
+
#listenForPreviews(box) {
|
|
223
|
+
this.#listenForHover(box);
|
|
224
|
+
this.#listenForFocus(box);
|
|
225
|
+
this.#listenForTouch(box);
|
|
226
|
+
}
|
|
227
|
+
/** A mouse or pen: 300 ms on a link shows its preview, 300 ms off both ends it. */
|
|
228
|
+
#listenForHover(box) {
|
|
229
|
+
box.addEventListener("pointerover", (e) => {
|
|
230
|
+
if (e.pointerType === "touch")
|
|
231
|
+
return;
|
|
232
|
+
const anchor = anchorOf(e.target);
|
|
233
|
+
if (anchor === undefined || anchor === this.#hovered)
|
|
234
|
+
return;
|
|
235
|
+
this.#hovered = anchor;
|
|
236
|
+
if (anchor === this.#dismissed)
|
|
237
|
+
return;
|
|
238
|
+
if (this.#shown?.anchor === anchor) {
|
|
239
|
+
clearTimeout(this.#timer);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
this.#pending = anchor;
|
|
243
|
+
this.#later(PREVIEW_DWELL_MS, () => this.#show(anchor, "fine"));
|
|
244
|
+
});
|
|
245
|
+
box.addEventListener("pointerout", (e) => {
|
|
246
|
+
if (e.pointerType === "touch")
|
|
247
|
+
return;
|
|
248
|
+
const anchor = anchorOf(e.target);
|
|
249
|
+
if (anchor === undefined || (e.relatedTarget instanceof Node && anchor.contains(e.relatedTarget)))
|
|
250
|
+
return;
|
|
251
|
+
this.#hovered = undefined;
|
|
252
|
+
if (this.#dismissed === anchor)
|
|
253
|
+
this.#dismissed = undefined;
|
|
254
|
+
if (this.#pending === anchor)
|
|
255
|
+
this.#cancel();
|
|
256
|
+
if (this.#shown?.anchor === anchor && this.#shown.pointer === "fine" && !this.#held) {
|
|
257
|
+
this.#later(PREVIEW_DWELL_MS, () => this.#end());
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/** The keyboard: 300 ms of visible focus shows the preview; leaving the link ends it. */
|
|
262
|
+
#listenForFocus(box) {
|
|
263
|
+
box.addEventListener("focusin", (e) => {
|
|
264
|
+
const anchor = anchorOf(e.target);
|
|
265
|
+
if (anchor === undefined || anchor === this.#dismissed || !anchor.matches(":focus-visible"))
|
|
266
|
+
return;
|
|
267
|
+
this.#pending = anchor;
|
|
268
|
+
this.#later(PREVIEW_DWELL_MS, () => this.#show(anchor, "keyboard"));
|
|
269
|
+
});
|
|
270
|
+
box.addEventListener("focusout", (e) => {
|
|
271
|
+
const anchor = anchorOf(e.target);
|
|
272
|
+
if (anchor === undefined)
|
|
273
|
+
return;
|
|
274
|
+
if (this.#dismissed === anchor)
|
|
275
|
+
this.#dismissed = undefined;
|
|
276
|
+
if (this.#pending === anchor)
|
|
277
|
+
this.#cancel();
|
|
278
|
+
if (this.#shown?.anchor === anchor && this.#shown.pointer === "keyboard")
|
|
279
|
+
this.#end();
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/** A finger: a still long-press opens the preview, and the click its lift sends is cancelled. */
|
|
283
|
+
#listenForTouch(box) {
|
|
284
|
+
box.addEventListener("pointerdown", (e) => {
|
|
285
|
+
// A new press: a long-press before it that sent no click leaves nothing to cancel.
|
|
286
|
+
this.#swallowClick = false;
|
|
287
|
+
this.#touching = e.pointerType === "touch";
|
|
288
|
+
const anchor = this.#touching ? anchorOf(e.target) : undefined;
|
|
289
|
+
if (anchor === undefined)
|
|
290
|
+
return;
|
|
291
|
+
this.#press = { x: e.clientX, y: e.clientY, id: e.pointerId };
|
|
292
|
+
this.#pending = anchor;
|
|
293
|
+
this.#later(PREVIEW_LONG_PRESS_MS, () => {
|
|
294
|
+
this.#press = undefined;
|
|
295
|
+
this.#swallowClick = true;
|
|
296
|
+
// The press selects no text, whatever the browser began.
|
|
297
|
+
document.getSelection()?.removeAllRanges();
|
|
298
|
+
this.#show(anchor, "touch");
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
box.addEventListener("pointermove", (e) => {
|
|
302
|
+
const press = this.#press;
|
|
303
|
+
if (press === undefined || e.pointerId !== press.id)
|
|
304
|
+
return;
|
|
305
|
+
if (Math.hypot(e.clientX - press.x, e.clientY - press.y) > PREVIEW_SLOP) {
|
|
306
|
+
this.#press = undefined;
|
|
307
|
+
this.#cancel();
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
for (const end of ["pointerup", "pointercancel"]) {
|
|
311
|
+
box.addEventListener(end, (e) => {
|
|
312
|
+
if (this.#press?.id !== e.pointerId)
|
|
313
|
+
return;
|
|
314
|
+
this.#press = undefined;
|
|
315
|
+
this.#cancel();
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
// Before the click that follows: a long-press's lift follows nothing.
|
|
319
|
+
box.addEventListener("click", (e) => {
|
|
320
|
+
if (!this.#swallowClick)
|
|
321
|
+
return;
|
|
322
|
+
this.#swallowClick = false;
|
|
323
|
+
e.preventDefault();
|
|
324
|
+
e.stopImmediatePropagation();
|
|
325
|
+
}, { capture: true });
|
|
326
|
+
box.addEventListener("contextmenu", (e) => {
|
|
327
|
+
if (this.#touching && anchorOf(e.target) !== undefined)
|
|
328
|
+
e.preventDefault();
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/** Lets the pointer through every anchor (a selection drag is under way), or stops letting it. */
|
|
332
|
+
#passThrough(through) {
|
|
333
|
+
for (const { box } of this.#pages.values()) {
|
|
334
|
+
for (const a of box.children)
|
|
335
|
+
a.style.pointerEvents = through ? "none" : "auto";
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
onMount(page, slot) {
|
|
339
|
+
const box = document.createElement("div");
|
|
340
|
+
box.className = "lamina-link-layer";
|
|
341
|
+
Object.assign(box.style, {
|
|
342
|
+
position: "absolute",
|
|
343
|
+
left: "0",
|
|
344
|
+
top: "0",
|
|
345
|
+
transformOrigin: "0 0",
|
|
346
|
+
pointerEvents: "none",
|
|
347
|
+
});
|
|
348
|
+
slot.append(box);
|
|
349
|
+
const view = { box, abort: new AbortController(), size: undefined };
|
|
350
|
+
this.#pages.set(page, view);
|
|
351
|
+
this.#listenForPreviews(box);
|
|
352
|
+
box.addEventListener("click", (e) => this.#click(e));
|
|
353
|
+
// A link without an `href` (a web link) gets no click from Enter: it follows it here.
|
|
354
|
+
box.addEventListener("keydown", (e) => {
|
|
355
|
+
const anchor = e.target instanceof HTMLElement ? e.target : undefined;
|
|
356
|
+
// One follow per press, as a native link's click: a held key's repeats ask nothing more.
|
|
357
|
+
if (e.key === "Enter" && !e.repeat && anchor !== undefined && !anchor.hasAttribute("href"))
|
|
358
|
+
this.#click(e);
|
|
359
|
+
});
|
|
360
|
+
// A middle click on a web link would open it without asking: it asks too.
|
|
361
|
+
box.addEventListener("auxclick", (e) => {
|
|
362
|
+
if (e.button === 1 && this.#followOf(e)?.kind === "external")
|
|
363
|
+
this.#click(e);
|
|
364
|
+
});
|
|
365
|
+
this.#host.client
|
|
366
|
+
.pageLinks(page, { signal: view.abort.signal })
|
|
367
|
+
.then((links) => {
|
|
368
|
+
if (this.#pages.get(page) === view)
|
|
369
|
+
this.#draw(page, view, links);
|
|
370
|
+
})
|
|
371
|
+
.catch(() => {
|
|
372
|
+
// Aborted (the page left), or links that can't be read: the page stays without them.
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
onUnmount(page) {
|
|
376
|
+
const view = this.#pages.get(page);
|
|
377
|
+
if (view !== undefined && this.#shown !== undefined && view.box.contains(this.#shown.anchor))
|
|
378
|
+
this.#end();
|
|
379
|
+
if (view !== undefined && this.#pending !== undefined && view.box.contains(this.#pending))
|
|
380
|
+
this.#cancel();
|
|
381
|
+
view?.abort.abort();
|
|
382
|
+
view?.box.remove();
|
|
383
|
+
this.#pages.delete(page);
|
|
384
|
+
}
|
|
385
|
+
onZoom(page, _slot, size) {
|
|
386
|
+
const view = this.#pages.get(page);
|
|
387
|
+
if (view === undefined)
|
|
388
|
+
return;
|
|
389
|
+
view.size = size;
|
|
390
|
+
this.#place(page, view);
|
|
391
|
+
}
|
|
392
|
+
/** Places every page again: the view turned. */
|
|
393
|
+
refresh() {
|
|
394
|
+
for (const [page, view] of this.#pages)
|
|
395
|
+
this.#place(page, view);
|
|
396
|
+
}
|
|
397
|
+
#place(page, view) {
|
|
398
|
+
const points = this.#host.points(page);
|
|
399
|
+
if (points !== undefined && view.size !== undefined)
|
|
400
|
+
placeBox(view.box, points, view.size, this.#host.rotation());
|
|
401
|
+
}
|
|
402
|
+
#draw(page, view, links) {
|
|
403
|
+
view.box.replaceChildren(...links.map((link) => this.#anchor(page, link)));
|
|
404
|
+
}
|
|
405
|
+
/** The anchor for `link` on page `page`: placed, named, and with what following it does. */
|
|
406
|
+
#anchor(page, link) {
|
|
407
|
+
const { follow, label, note } = this.#meaning(page, link);
|
|
408
|
+
const a = document.createElement("a");
|
|
409
|
+
a.className = "lamina-link";
|
|
410
|
+
a.draggable = false;
|
|
411
|
+
const href = this.#internalHref(follow);
|
|
412
|
+
if (href === undefined) {
|
|
413
|
+
// No address for the browser to follow: still a link in the tab order, and named.
|
|
414
|
+
a.setAttribute("role", "link");
|
|
415
|
+
a.tabIndex = 0;
|
|
416
|
+
if (follow.kind === "none")
|
|
417
|
+
a.setAttribute("aria-disabled", "true");
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
a.href = href;
|
|
421
|
+
a.referrerPolicy = "no-referrer";
|
|
422
|
+
}
|
|
423
|
+
a.setAttribute("aria-label", link.contents ?? label);
|
|
424
|
+
if (note !== undefined)
|
|
425
|
+
a.title = note;
|
|
426
|
+
const [first, ...rest] = areas(link);
|
|
427
|
+
const bounds = first ?? { x: 0, y: 0, width: 0, height: 0 };
|
|
428
|
+
Object.assign(a.style, {
|
|
429
|
+
position: "absolute",
|
|
430
|
+
left: `${bounds.x}px`,
|
|
431
|
+
top: `${bounds.y}px`,
|
|
432
|
+
width: `${bounds.width}px`,
|
|
433
|
+
height: `${bounds.height}px`,
|
|
434
|
+
pointerEvents: "auto",
|
|
435
|
+
cursor: follow.kind === "none" ? "default" : "pointer",
|
|
436
|
+
// A long-press opens the preview: no OS link menu, no selection of the link.
|
|
437
|
+
webkitTouchCallout: "none",
|
|
438
|
+
webkitUserSelect: "none",
|
|
439
|
+
userSelect: "none",
|
|
440
|
+
});
|
|
441
|
+
// A link over several areas (its quads): the first is the anchor, the others its children,
|
|
442
|
+
// placed from it, so only the areas follow the link and the focus ring is on the first.
|
|
443
|
+
for (const area of rest) {
|
|
444
|
+
const part = document.createElement("span");
|
|
445
|
+
Object.assign(part.style, {
|
|
446
|
+
position: "absolute",
|
|
447
|
+
left: `${area.x - bounds.x}px`,
|
|
448
|
+
top: `${area.y - bounds.y}px`,
|
|
449
|
+
width: `${area.width}px`,
|
|
450
|
+
height: `${area.height}px`,
|
|
451
|
+
});
|
|
452
|
+
a.append(part);
|
|
453
|
+
}
|
|
454
|
+
this.#follows.set(a, follow);
|
|
455
|
+
this.#links.set(a, link);
|
|
456
|
+
return a;
|
|
457
|
+
}
|
|
458
|
+
/** What `link` on page `page` does, its name, and the note it shows on hover. */
|
|
459
|
+
#meaning(page, link) {
|
|
460
|
+
const words = this.#words;
|
|
461
|
+
switch (link.kind) {
|
|
462
|
+
case "dest":
|
|
463
|
+
case "named":
|
|
464
|
+
return link.target === undefined
|
|
465
|
+
? inert(link, words.broken)
|
|
466
|
+
: { follow: { kind: "target", target: link.target }, label: words.page(link.target.page) };
|
|
467
|
+
case "uri": {
|
|
468
|
+
const external = externalLink(link.uri);
|
|
469
|
+
return external.kind === "open"
|
|
470
|
+
? { follow: { kind: "external", link: external }, label: external.href, note: external.href }
|
|
471
|
+
: inert(link, words.refused(link.uri));
|
|
472
|
+
}
|
|
473
|
+
case "remote": {
|
|
474
|
+
return inert(link, words.otherFile(link.file));
|
|
475
|
+
}
|
|
476
|
+
case "named-action": {
|
|
477
|
+
const to = namedAction(link.name, page, this.#host.pageCount(), words);
|
|
478
|
+
return to === undefined
|
|
479
|
+
? inert(link, words.unsupported)
|
|
480
|
+
: { follow: { kind: "page", page: to.page, label: to.label }, label: to.label, note: to.label };
|
|
481
|
+
}
|
|
482
|
+
default:
|
|
483
|
+
return inert(link, words.unsupported);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
#internalHref(follow) {
|
|
487
|
+
if (follow.kind === "target")
|
|
488
|
+
return this.#options.href?.(follow.target.page);
|
|
489
|
+
if (follow.kind === "page")
|
|
490
|
+
return this.#options.href?.(follow.page);
|
|
491
|
+
return undefined;
|
|
492
|
+
}
|
|
493
|
+
/** What following the anchor `e` happened on does. */
|
|
494
|
+
#followOf(e) {
|
|
495
|
+
const anchor = anchorOf(e.target);
|
|
496
|
+
return anchor === undefined ? undefined : this.#follows.get(anchor);
|
|
497
|
+
}
|
|
498
|
+
#click(e) {
|
|
499
|
+
const follow = this.#followOf(e);
|
|
500
|
+
if (follow === undefined)
|
|
501
|
+
return;
|
|
502
|
+
// Following a link ends its preview.
|
|
503
|
+
this.#cancel();
|
|
504
|
+
this.#end();
|
|
505
|
+
const external = follow.kind === "external";
|
|
506
|
+
// A modified click on a link inside the document opens its `href` where the browser puts it.
|
|
507
|
+
const modified = e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || (e instanceof MouseEvent && e.button !== 0);
|
|
508
|
+
if (!external && modified)
|
|
509
|
+
return;
|
|
510
|
+
e.preventDefault();
|
|
511
|
+
switch (follow.kind) {
|
|
512
|
+
case "target":
|
|
513
|
+
this.#host.goTo(follow.target);
|
|
514
|
+
return;
|
|
515
|
+
case "page":
|
|
516
|
+
this.#host.goToPage(follow.page);
|
|
517
|
+
return;
|
|
518
|
+
case "external":
|
|
519
|
+
this.#options.onExternal?.(follow.link);
|
|
520
|
+
return;
|
|
521
|
+
case "none":
|
|
522
|
+
this.#options.onInert?.(follow.link, follow.note);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
//# sourceMappingURL=link-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-layer.js","sourceRoot":"","sources":["../../src/layers/link-layer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Target } from "@laminapdf/sdk";
|
|
2
|
+
import type { PageSize } from "../layout/page-layout.js";
|
|
3
|
+
import type { TextRunData } from "../protocol.js";
|
|
4
|
+
/** How far above and left of the destination point the crop starts, in points. */
|
|
5
|
+
export declare const PREVIEW_PAD = 8;
|
|
6
|
+
/** The crop's width without text lines to measure (an image-only page, no text module), in points. */
|
|
7
|
+
export declare const PREVIEW_NO_TEXT_WIDTH = 360;
|
|
8
|
+
/** The largest crop a region preview draws, in CSS px. */
|
|
9
|
+
export declare const PREVIEW_MAX: {
|
|
10
|
+
readonly width: 480;
|
|
11
|
+
readonly height: 180;
|
|
12
|
+
};
|
|
13
|
+
/** R07's page preview: a crop this wide and this high (CSS px) of the page's top. */
|
|
14
|
+
export declare const PAGE_PREVIEW: {
|
|
15
|
+
readonly width: 224;
|
|
16
|
+
readonly height: 92;
|
|
17
|
+
};
|
|
18
|
+
/** A rectangle in page space, in points. */
|
|
19
|
+
export interface PageRect {
|
|
20
|
+
readonly x: number;
|
|
21
|
+
readonly y: number;
|
|
22
|
+
readonly width: number;
|
|
23
|
+
readonly height: number;
|
|
24
|
+
}
|
|
25
|
+
/** One line of a page's text, in page space: its box and its text. */
|
|
26
|
+
export interface PreviewLine {
|
|
27
|
+
readonly left: number;
|
|
28
|
+
readonly top: number;
|
|
29
|
+
readonly right: number;
|
|
30
|
+
readonly bottom: number;
|
|
31
|
+
readonly text: string;
|
|
32
|
+
}
|
|
33
|
+
/** What a preview shows: `clip` of page `page`, drawn at `scale` CSS px per point. */
|
|
34
|
+
export interface PreviewRegion {
|
|
35
|
+
/** `region`: around the destination point; `page`: the page's top (R07). */
|
|
36
|
+
readonly kind: "region" | "page";
|
|
37
|
+
readonly page: number;
|
|
38
|
+
readonly clip: PageRect;
|
|
39
|
+
readonly scale: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A page's text lines, from its runs and glyph quads (`pageText`). Runs come in reading order:
|
|
43
|
+
* a run joins the line before it when it sits on the same band and starts no further right than
|
|
44
|
+
* twice its font size past the line's end, so the two columns of a page stay two lines. Vertical
|
|
45
|
+
* and empty runs are left out.
|
|
46
|
+
*/
|
|
47
|
+
export declare function previewLines(runs: readonly TextRunData[], quads: Float32Array): PreviewLine[];
|
|
48
|
+
/**
|
|
49
|
+
* What a preview of `target` shows. `size` is the destination page's displayed size, `lines` its
|
|
50
|
+
* text lines (`undefined` without text), `percent` the reader's zoom. Bad values (a top above the
|
|
51
|
+
* page, a rectangle outside it, NaN) are clamped onto the page and never throw.
|
|
52
|
+
*/
|
|
53
|
+
export declare function previewRegion(target: Target, size: PageSize, lines: readonly PreviewLine[] | undefined, percent: number): PreviewRegion;
|
|
54
|
+
/** The text of the lines inside `clip`, in reading order, joined and cut at `max` characters. */
|
|
55
|
+
export declare function previewText(lines: readonly PreviewLine[], clip: PageRect, max?: number): string;
|
|
56
|
+
/** What to ask the renderer for: the page at `scale` (device px per point), cut to `clip`. */
|
|
57
|
+
export interface PreviewRender {
|
|
58
|
+
readonly scale: number;
|
|
59
|
+
readonly clip: {
|
|
60
|
+
readonly x: number;
|
|
61
|
+
readonly y: number;
|
|
62
|
+
readonly width: number;
|
|
63
|
+
readonly height: number;
|
|
64
|
+
};
|
|
65
|
+
/** The crop's size on screen, in CSS px (turned with the view). */
|
|
66
|
+
readonly css: {
|
|
67
|
+
readonly width: number;
|
|
68
|
+
readonly height: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The render request for `region` of a page of `size`, turned `rotation` degrees clockwise as the
|
|
73
|
+
* view is, at `dpr` device pixels per CSS px. The clip is in the rotated page's device pixels, as
|
|
74
|
+
* the renderer takes it, rounded out to whole pixels and kept on the page.
|
|
75
|
+
*/
|
|
76
|
+
export declare function previewRender(region: PreviewRegion, size: PageSize, rotation: 0 | 90 | 180 | 270, dpr: number): PreviewRender;
|
|
77
|
+
//# sourceMappingURL=link-preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-preview.d.ts","sourceRoot":"","sources":["../../src/layers/link-preview.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,kFAAkF;AAClF,eAAO,MAAM,WAAW,IAAI,CAAC;AAG7B,sGAAsG;AACtG,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,0DAA0D;AAC1D,eAAO,MAAM,WAAW;aAAK,KAAK,EAAE,GAAG;aAAE,MAAM,EAAE,GAAG;CAAW,CAAC;AAGhE,qFAAqF;AACrF,eAAO,MAAM,YAAY;aAAK,KAAK,EAAE,GAAG;aAAE,MAAM,EAAE,EAAE;CAAW,CAAC;AAEhE,4CAA4C;AAC5C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,YAAY,GAAG,WAAW,EAAE,CAkB7F;AA6CD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,EACzC,OAAO,EAAE,MAAM,GACd,aAAa,CAef;AAuDD,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAM,GAAG,MAAM,CAa5F;AAED,8FAA8F;AAC9F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3G,mEAAmE;IACnE,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,EAC5B,GAAG,EAAE,MAAM,GACV,aAAa,CAgCf"}
|