@embedpdf/web 3.0.0-next.13 → 3.0.0-next.15
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.cjs +3697 -381
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2812 -137
- package/dist/index.d.ts +2812 -137
- package/dist/index.js +3570 -382
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ interface PickFileOptions {
|
|
|
7
7
|
}
|
|
8
8
|
/** Open the file dialog; resolve the picked file, or null if cancelled. */
|
|
9
9
|
declare function pickImageFile(options?: PickFileOptions): Promise<File | null>;
|
|
10
|
-
/** The same dialog with
|
|
10
|
+
/** The same dialog with no type filter — any file (attachments). */
|
|
11
11
|
declare const pickFile: (options?: PickFileOptions) => Promise<File | null>;
|
|
12
12
|
/**
|
|
13
13
|
* Hand bytes to the user as a browser download (a one-shot `<a download>`).
|
|
@@ -15,50 +15,112 @@ declare const pickFile: (options?: PickFileOptions) => Promise<File | null>;
|
|
|
15
15
|
* capability's `downloadAttachment` or the document `attachments.download`.
|
|
16
16
|
*/
|
|
17
17
|
declare function saveFile(bytes: Uint8Array | Blob, name: string, mimeType?: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* The browser's default for a plugin's file prompt (the annotation plugin's
|
|
20
|
+
* `FilePickerProvider`): the file dialog, honouring the request's `accept`
|
|
21
|
+
* filter. A picked `File` carries its own name and type, so it goes straight
|
|
22
|
+
* through as the engine's file source; a dismissed dialog answers `null`.
|
|
23
|
+
*/
|
|
24
|
+
declare function pickRequestedFile(request: {
|
|
25
|
+
accept?: string | null;
|
|
26
|
+
}): Promise<{
|
|
27
|
+
data: File;
|
|
28
|
+
} | null>;
|
|
29
|
+
/** Where a provider goes: the annotation plugin's port (its capability satisfies it). */
|
|
30
|
+
interface FilePickerPort<Provider> {
|
|
31
|
+
/** Install the provider, `null` to make click-then-pick tools do nothing. Returns its removal. */
|
|
32
|
+
setFilePickerProvider(provider: Provider | null): () => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Install `provider` as a document's file picker, until the call it returns
|
|
36
|
+
* removes it. A document has one port, so a second install while the first
|
|
37
|
+
* is there silently replaces it: `onRepeat` hears of it (an adapter warns in
|
|
38
|
+
* development, saying where to install it once).
|
|
39
|
+
*/
|
|
40
|
+
declare function installFilePickerProvider<Provider>(annotation: FilePickerPort<Provider>, provider: Provider | null, onRepeat: () => void): () => void;
|
|
18
41
|
//#endregion
|
|
19
|
-
//#region src/
|
|
42
|
+
//#region src/clock.d.ts
|
|
20
43
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
* The browser's time, for the kernel: `createKernel({ clock: browserClock() })`.
|
|
45
|
+
* Timers, and frames from `requestAnimationFrame`, so plugins can animate and
|
|
46
|
+
* merge their wake-ups into one per painted frame. Structurally `HostClock`
|
|
47
|
+
* from `@embedpdf/core`, declared here so this package stays dependency-free.
|
|
48
|
+
*/
|
|
49
|
+
/** Structural twin of `HostClock` (`@embedpdf/core`). */
|
|
50
|
+
interface WebClock {
|
|
51
|
+
now(): number;
|
|
52
|
+
after(ms: number, run: () => void): () => void;
|
|
53
|
+
nextFrame?(run: (timeMs: number) => void): () => void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The browser's clock. A page without `requestAnimationFrame` (some test
|
|
57
|
+
* environments) gets a clock without frames, and plugins then skip animation.
|
|
58
|
+
*/
|
|
59
|
+
declare function browserClock(): WebClock;
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/css-text.d.ts
|
|
62
|
+
/**
|
|
63
|
+
* Style records as CSS text. This package hands styles out as records with
|
|
64
|
+
* camelCase names (`strokeWidth`, `fontFamily`) and lengths with their units,
|
|
65
|
+
* the shape a style object takes in React, Vue and Angular. A framework whose
|
|
66
|
+
* `style` is a string (Svelte) turns a record into CSS text with
|
|
67
|
+
* {@link cssText}: `stroke-width: …; font-family: …`. Paint values are
|
|
68
|
+
* `var(--epdf-…, …)`, which only work in `style`, never in an SVG
|
|
69
|
+
* presentation attribute.
|
|
28
70
|
*/
|
|
71
|
+
/** A style record: CSS property names in camelCase, each a value or left out. */
|
|
72
|
+
type StyleRecord<Style> = { readonly [Name in keyof Style]?: string | number | null; };
|
|
73
|
+
/** A style record as CSS text, leaving out what is `undefined` or `null`. */
|
|
74
|
+
declare function cssText<Style extends StyleRecord<Style>>(style: Style): string;
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/clipboard.d.ts
|
|
29
77
|
/** The slice of the selection capability clipboard wiring needs. */
|
|
30
78
|
interface ClipboardSelectionSource {
|
|
31
79
|
hasSelection(): boolean;
|
|
32
80
|
canCopy(): boolean;
|
|
33
81
|
readText(): Promise<string>;
|
|
34
|
-
|
|
35
|
-
|
|
82
|
+
onChanged(listener: () => void): () => void;
|
|
83
|
+
onCommitted(listener: () => void): () => void;
|
|
36
84
|
}
|
|
37
85
|
interface SelectionClipboardOptions {
|
|
38
86
|
/**
|
|
39
87
|
* Prefetch the selected text when the selection settles (default true).
|
|
40
|
-
* This is what makes the
|
|
88
|
+
* This is what makes the native copy path work: a `copy` event handler
|
|
41
89
|
* must call `clipboardData.setData` synchronously — awaiting a page-text
|
|
42
90
|
* read inside it is too late — and it also keeps the async path instant.
|
|
43
91
|
* The fetch is one versioned, cached, permission-gated read per page;
|
|
44
92
|
* pass false to make copying strictly on-demand.
|
|
45
93
|
*/
|
|
46
94
|
prefetch?: boolean;
|
|
47
|
-
/**
|
|
48
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Whose keys and copies these are (default `document`, the whole page). An element takes
|
|
97
|
+
* them only while focus is inside it, for a page with more than one viewer; a copy from the
|
|
98
|
+
* browser's Edit menu included, which reaches the page's body when nothing is selected there.
|
|
99
|
+
*/
|
|
100
|
+
target?: Document | HTMLElement;
|
|
101
|
+
/**
|
|
102
|
+
* Called when Ctrl/Cmd+C or a copy (Edit → Copy) meets a selection the user may not copy.
|
|
103
|
+
* The browser's own copy is prevented either way; this is where to say so.
|
|
104
|
+
*/
|
|
105
|
+
onRefused?: () => void;
|
|
49
106
|
}
|
|
50
107
|
/**
|
|
51
108
|
* Wire clipboard copy for a selection. Two delivery paths, both fed by the
|
|
52
109
|
* prefetched text:
|
|
53
110
|
*
|
|
54
111
|
* - the native `copy` event (menu Edit→Copy, or ctrl/cmd+C while the page
|
|
55
|
-
* has a DOM selection
|
|
56
|
-
* focus sink): answered SYNCHRONOUSLY from the cache;
|
|
112
|
+
* has a DOM selection): answered synchronously from the cache;
|
|
57
113
|
* - ctrl/cmd+C with no DOM selection (canvas-rendered viewers usually
|
|
58
114
|
* have none, and browsers don't dispatch `copy` then): a keydown
|
|
59
115
|
* fallback writes via the async Clipboard API inside the keystroke's
|
|
60
116
|
* user-activation window.
|
|
61
117
|
*
|
|
118
|
+
* A selection the user may not copy is never copied by either path, nor by
|
|
119
|
+
* the browser: the key and the copy are prevented, and `onRefused` says so.
|
|
120
|
+
* Keys and copies in a text field are the field's, and left alone. With an
|
|
121
|
+
* element as `target`, only the keys and copies made while focus is inside it
|
|
122
|
+
* are its own.
|
|
123
|
+
*
|
|
62
124
|
* Returns the unwire function. Mount once per document view (not per page).
|
|
63
125
|
*/
|
|
64
126
|
declare function wireSelectionClipboard(selection: ClipboardSelectionSource, options?: SelectionClipboardOptions): () => void;
|
|
@@ -69,29 +131,67 @@ declare function wireSelectionClipboard(selection: ClipboardSelectionSource, opt
|
|
|
69
131
|
* with what was copied ('' when nothing was — nothing is written then, so an
|
|
70
132
|
* empty selection never clobbers the user's clipboard).
|
|
71
133
|
*/
|
|
72
|
-
declare function copySelection(selection: ClipboardSelectionSource): Promise<string>;
|
|
134
|
+
declare function copySelection(selection: Pick<ClipboardSelectionSource, 'readText'>): Promise<string>;
|
|
73
135
|
//#endregion
|
|
74
|
-
//#region src/
|
|
136
|
+
//#region src/command-shortcuts.d.ts
|
|
137
|
+
/** Why a matched command won't run whatever the moment, as the commands plugin says it. */
|
|
138
|
+
interface ShortcutRefusal {
|
|
139
|
+
/** Turned off in this viewer, or not allowed by the scope. */
|
|
140
|
+
readonly reason: 'turned-off' | 'not-allowed';
|
|
141
|
+
/** A sentence for the user. */
|
|
142
|
+
readonly message: string;
|
|
143
|
+
}
|
|
144
|
+
/** The part of the commands capability shortcuts need. */
|
|
145
|
+
interface ShortcutCommands {
|
|
146
|
+
/**
|
|
147
|
+
* The command a keystroke's shortcut names, with its refusal when it's refused, or `null`.
|
|
148
|
+
* With `inTextField`, only a command that runs from text fields.
|
|
149
|
+
*/
|
|
150
|
+
matchStroke(stroke: KeyboardEvent, options: {
|
|
151
|
+
isMac: boolean;
|
|
152
|
+
inTextField: boolean;
|
|
153
|
+
}): {
|
|
154
|
+
readonly commandId: string;
|
|
155
|
+
readonly refusal: ShortcutRefusal | null;
|
|
156
|
+
} | null;
|
|
157
|
+
canExecute(id: string): boolean;
|
|
158
|
+
execute(id: string): Promise<unknown>;
|
|
159
|
+
}
|
|
160
|
+
interface CommandShortcutOptions {
|
|
161
|
+
/** Whether `Mod` is Cmd (a Mac) or Ctrl. Default: what the browser says. */
|
|
162
|
+
isMac?: boolean;
|
|
163
|
+
/** Where to listen. Default: `window`. */
|
|
164
|
+
target?: Pick<Window, 'addEventListener' | 'removeEventListener'>;
|
|
165
|
+
/** Called when a key's command is turned off or not allowed, with why: say so to the user. */
|
|
166
|
+
onRefused?: (commandId: string, refusal: ShortcutRefusal) => void;
|
|
167
|
+
}
|
|
168
|
+
/** Whether this is an Apple platform, where `Mod` is Cmd and shortcuts show as `⌘K`. */
|
|
169
|
+
declare const isMacPlatform: () => boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Run a command when its shortcut is pressed, and return the function that stops listening.
|
|
172
|
+
* Keys typed into a text field are left alone, except a command's that says it runs from text
|
|
173
|
+
* fields (`shortcutInTextFields`, as Find does). A command that's turned off or not allowed
|
|
174
|
+
* still takes its key, so the browser doesn't do something else with it (Cmd+P printing the
|
|
175
|
+
* page), and `onRefused` says why. A key whose command only can't run right now keeps its
|
|
176
|
+
* browser default.
|
|
177
|
+
*/
|
|
178
|
+
declare function bindCommandShortcuts(commands: ShortcutCommands, options?: CommandShortcutOptions): () => void;
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/page-ref.d.ts
|
|
75
181
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* reactivity (context revision, signals, computed, $derived).
|
|
83
|
-
*
|
|
84
|
-
* The boundary laws:
|
|
85
|
-
* - Placement policy lives HERE, above the projector seam: a projector
|
|
86
|
-
* only knows geometry — never what is being positioned nor where it
|
|
87
|
-
* prefers to sit.
|
|
88
|
-
* - A projector describes the CURRENT projection; it never implements a
|
|
89
|
-
* framework-style reactive lifecycle. State-driven changes (the Stage
|
|
90
|
-
* camera) must reach consumers through the framework's own render
|
|
91
|
-
* cycle so surface and overlay commit TOGETHER; only genuinely
|
|
92
|
-
* browser-driven changes (a PageView moving because the document
|
|
93
|
-
* scrolled) use an external listener ({@link observeClientGeometry}).
|
|
182
|
+
* A page address — structurally the kernel's `PageRef` from `@embedpdf/core`
|
|
183
|
+
* (`{ kind: 'objectNumber', objectNumber }`), mirrored here like the
|
|
184
|
+
* rect/point shapes so this package stays free of EmbedPDF imports. Every
|
|
185
|
+
* `PageRef` the kernel or a plugin hands out satisfies it; the surfaces pass
|
|
186
|
+
* it through untouched (a stage's `pageAt` result, an anchor's page) — the
|
|
187
|
+
* number is never read here.
|
|
94
188
|
*/
|
|
189
|
+
interface PageRef {
|
|
190
|
+
readonly kind: 'objectNumber';
|
|
191
|
+
readonly objectNumber: number;
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/anchored-position.d.ts
|
|
95
195
|
interface AnchoredRect {
|
|
96
196
|
x: number;
|
|
97
197
|
y: number;
|
|
@@ -102,36 +202,68 @@ interface AnchoredPoint {
|
|
|
102
202
|
x: number;
|
|
103
203
|
y: number;
|
|
104
204
|
}
|
|
105
|
-
|
|
205
|
+
/** A side of the box. */
|
|
206
|
+
type AnchoredSide = 'top' | 'right' | 'bottom' | 'left';
|
|
207
|
+
/**
|
|
208
|
+
* Where anchored UI sits: a side of the box, centred on it, or lined up with
|
|
209
|
+
* the side's start or end (`'top-end'`: above the box, right edges lined up).
|
|
210
|
+
*/
|
|
211
|
+
type AnchoredPlacement = AnchoredSide | `${AnchoredSide}-${'start' | 'end'}`;
|
|
212
|
+
/** How anchored UI is placed: where, how far from the box, and whether it may move to fit. */
|
|
213
|
+
interface AnchoredOptions {
|
|
214
|
+
placement: AnchoredPlacement;
|
|
215
|
+
/** Screen px between the box and the UI; negative overlaps the box. */
|
|
216
|
+
gap: number;
|
|
217
|
+
/** Stays where `placement` puts it: never flips, never moves to stay in view. */
|
|
218
|
+
pinned?: boolean;
|
|
219
|
+
}
|
|
106
220
|
/** CSS-ready output: absolute/fixed `left`/`top` plus a centering transform. */
|
|
107
221
|
interface AnchoredPosition {
|
|
108
222
|
left: number;
|
|
109
223
|
top: number;
|
|
110
224
|
transform: string;
|
|
225
|
+
/** Where it sits: the placement asked for, or its opposite side when that had no room. */
|
|
226
|
+
placement: AnchoredPlacement;
|
|
227
|
+
}
|
|
228
|
+
interface AnchoredSize {
|
|
229
|
+
width: number;
|
|
230
|
+
height: number;
|
|
111
231
|
}
|
|
112
232
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
|
|
233
|
+
* What placement needs to keep anchored UI on screen: the element's size, and
|
|
234
|
+
* the area it must stay inside, in the projector's space (the Stage's own box,
|
|
235
|
+
* or the browser window).
|
|
236
|
+
*/
|
|
237
|
+
interface AnchoredFit {
|
|
238
|
+
size: AnchoredSize;
|
|
239
|
+
view: AnchoredRect;
|
|
240
|
+
}
|
|
241
|
+
/** How a page is shown right now: its view scale, its rotation on screen, and its zoom (1 = 100%). */
|
|
242
|
+
interface PageViewEnv {
|
|
243
|
+
scale: number;
|
|
244
|
+
rotation: 0 | 90 | 180 | 270;
|
|
245
|
+
zoom: number;
|
|
246
|
+
}
|
|
247
|
+
/** What anchored UI attaches to: a page-space rect on a page, plus
|
|
248
|
+
* optional page-space points the UI must clear (e.g. a rotate knob).
|
|
123
249
|
* Structural — plugin anchor reads satisfy it without importing this
|
|
124
250
|
* package. */
|
|
125
251
|
interface AnchorTarget {
|
|
126
|
-
|
|
252
|
+
page: PageRef;
|
|
127
253
|
bounds: AnchoredRect;
|
|
254
|
+
/**
|
|
255
|
+
* Where the box is in a given view, for a box whose size or orientation
|
|
256
|
+
* depends on it (a note that keeps its size on screen). The projection
|
|
257
|
+
* calls it, so the anchor itself never has to follow the view.
|
|
258
|
+
*/
|
|
259
|
+
boundsIn?: (view: PageViewEnv) => AnchoredRect | null;
|
|
128
260
|
avoid?: AnchoredPoint[];
|
|
129
261
|
}
|
|
130
262
|
/**
|
|
131
|
-
* A page surface's
|
|
263
|
+
* A page surface's projection snapshot: how a page-space rect on a page
|
|
132
264
|
* becomes screen coordinates, right now. Provided by `<Stage>`
|
|
133
265
|
* (camera-driven, pure state, no DOM reads) and `<PageView>` (DOM-measured).
|
|
134
|
-
* Deliberately
|
|
266
|
+
* Deliberately no subscribe here — when projection changes is a framework
|
|
135
267
|
* binding concern (see the module doc), not part of the snapshot.
|
|
136
268
|
*/
|
|
137
269
|
interface ViewProjector {
|
|
@@ -144,38 +276,163 @@ interface ViewProjector {
|
|
|
144
276
|
* position:fixed, so no ancestor overflow can clip. (PageView)
|
|
145
277
|
*/
|
|
146
278
|
space: 'overlay' | 'client';
|
|
147
|
-
/**
|
|
279
|
+
/** Page-space rect on a page → coords in `space`. Null: not projectable
|
|
148
280
|
* right now (page not shown / not measurable yet). */
|
|
149
|
-
toScreen(
|
|
150
|
-
toScreenPoint(
|
|
281
|
+
toScreen(page: PageRef, rect: AnchoredRect): AnchoredRect | null;
|
|
282
|
+
toScreenPoint(page: PageRef, at: AnchoredPoint): AnchoredPoint | null;
|
|
151
283
|
/** The page's live view facts (for anchor reads that need them — e.g. the
|
|
152
284
|
* screen-constant rotate-knob stalk), or null when the page isn't shown. */
|
|
153
|
-
viewEnv(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
} | null;
|
|
285
|
+
viewEnv(page: PageRef): PageViewEnv | null;
|
|
286
|
+
/** The area anchored UI can be seen in, in `space`: the surface's box, or
|
|
287
|
+
* the window. Null while it isn't measurable yet. */
|
|
288
|
+
view(): AnchoredRect | null;
|
|
158
289
|
}
|
|
159
290
|
/**
|
|
160
|
-
*
|
|
291
|
+
* The anchored projection: anchor → screen position, in one pure call —
|
|
161
292
|
* projection, avoid-point transform, and the shared placement policy.
|
|
162
293
|
* Frameworks recompute this inside their native reactive primitive
|
|
163
294
|
* (a React render, a Vue `computed`, an Angular signal, a Svelte
|
|
164
295
|
* `$derived`); nothing here schedules anything.
|
|
296
|
+
*
|
|
297
|
+
* Null when there is nothing to show: the page isn't shown, or the box is so
|
|
298
|
+
* far out of view that the UI around it can't reach into it.
|
|
165
299
|
*/
|
|
166
|
-
declare function projectAnchoredTarget(projector: ViewProjector, anchor: AnchorTarget, placement
|
|
300
|
+
declare function projectAnchoredTarget(projector: ViewProjector, anchor: AnchorTarget, { placement, gap, pinned }: AnchoredOptions, fit?: AnchoredFit | null): AnchoredPosition | null;
|
|
167
301
|
/**
|
|
168
|
-
* The one genuinely
|
|
302
|
+
* The one genuinely browser-driven invalidation: an element in normal
|
|
169
303
|
* document flow moves when the document scrolls or the window resizes —
|
|
170
304
|
* no state change announces it. `<PageView>`'s binding registers this;
|
|
171
305
|
* the Stage never does (its camera is state, delivered through render).
|
|
172
306
|
*/
|
|
173
307
|
declare function observeClientGeometry(callback: () => void): () => void;
|
|
308
|
+
/**
|
|
309
|
+
* The area anchored UI stays inside: the surface's own box (`'overlay'` space, the element's
|
|
310
|
+
* positioned parent) or the window (`'client'` space). Null while the element has no
|
|
311
|
+
* positioned parent to measure.
|
|
312
|
+
*/
|
|
313
|
+
declare function anchoredViewOf(element: HTMLElement, space: ViewProjector['space']): AnchoredRect | null;
|
|
314
|
+
/** Whether two measurements give the same sizes, so a placement made from the first still holds. */
|
|
315
|
+
declare function sameAnchoredFit(left: AnchoredFit | null, right: AnchoredFit): boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Measure anchored UI's `element` and the area it stays inside ({@link anchoredViewOf}) now, and
|
|
318
|
+
* again whenever either resizes: `report` hears every measurement (keep it when
|
|
319
|
+
* {@link sameAnchoredFit} says it changed). A camera move changes neither, so it measures nothing.
|
|
320
|
+
* Returns the function that stops measuring.
|
|
321
|
+
*/
|
|
322
|
+
declare function observeAnchoredFit(element: HTMLElement, space: ViewProjector['space'], report: (fit: AnchoredFit) => void): () => void;
|
|
323
|
+
/**
|
|
324
|
+
* Place an upright element around `box` (screen px). `avoid` is a screen
|
|
325
|
+
* point the element must clear (e.g. the rotate knob): the element extends
|
|
326
|
+
* only the edge it sits on, and only when the point protrudes past that
|
|
327
|
+
* edge — so it clears the obstacle without ever shifting along the side.
|
|
328
|
+
* When the point is on another side (e.g. a 90° shape, knob at mid-height
|
|
329
|
+
* for a `top` placement) the edge is untouched.
|
|
330
|
+
*/
|
|
174
331
|
declare function positionAnchoredRect(box: AnchoredRect, placement: AnchoredPlacement, gap: number, avoid?: AnchoredPoint | null): AnchoredPosition;
|
|
332
|
+
/**
|
|
333
|
+
* Place an element of a known size around `box`, inside `fit.view`. It sits
|
|
334
|
+
* where `placement` says when it fits there; otherwise on the opposite side,
|
|
335
|
+
* lined up the same way, when that fits or has more room. Then, while `box`
|
|
336
|
+
* is in view, it moves along both axes to stay inside the view, `gap` from
|
|
337
|
+
* its edges; UI whose box scrolled out of view goes with it. The result is
|
|
338
|
+
* the element's top-left corner, with no transform.
|
|
339
|
+
*/
|
|
340
|
+
declare function fitAnchoredRect(box: AnchoredRect, placement: AnchoredPlacement, gap: number, fit: AnchoredFit, avoid?: AnchoredPoint | null): AnchoredPosition;
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/annotation-frame.d.ts
|
|
343
|
+
/**
|
|
344
|
+
* An annotation's frame in pixels. The annotation plugin hands out each
|
|
345
|
+
* render item's frame (a box, its turn, and how large the page draws it) and
|
|
346
|
+
* the raster inside it, in page points; these put them in the page layer's
|
|
347
|
+
* pixels, with the CSS turn about the middle. Plain geometry over structural
|
|
348
|
+
* shapes, the same for every framework adapter, so none of them converts,
|
|
349
|
+
* turns or scales anything itself.
|
|
350
|
+
*/
|
|
351
|
+
/** A box in page points and its turn, degrees clockwise about its middle. */
|
|
352
|
+
interface TurnedBox {
|
|
353
|
+
box: {
|
|
354
|
+
x: number;
|
|
355
|
+
y: number;
|
|
356
|
+
width: number;
|
|
357
|
+
height: number;
|
|
358
|
+
};
|
|
359
|
+
rotation: number;
|
|
360
|
+
}
|
|
361
|
+
/** A frame: its box and turn, and how large the page draws it relative to its own size. */
|
|
362
|
+
interface FrameBox extends TurnedBox {
|
|
363
|
+
scale: number;
|
|
364
|
+
}
|
|
365
|
+
/** What a page layer converts with: its transform's `toPixels`, its turn, and its zoom (1 = 100%). */
|
|
366
|
+
interface PageLayerTransform {
|
|
367
|
+
toPixels(point: {
|
|
368
|
+
x: number;
|
|
369
|
+
y: number;
|
|
370
|
+
}): {
|
|
371
|
+
x: number;
|
|
372
|
+
y: number;
|
|
373
|
+
};
|
|
374
|
+
rotation: number;
|
|
375
|
+
zoom: number;
|
|
376
|
+
}
|
|
377
|
+
/** A box in pixels and the CSS that turns it about its middle (`undefined` for no turn). */
|
|
378
|
+
interface PixelBox {
|
|
379
|
+
left: number;
|
|
380
|
+
top: number;
|
|
381
|
+
width: number;
|
|
382
|
+
height: number;
|
|
383
|
+
transform: string | undefined;
|
|
384
|
+
}
|
|
385
|
+
/** A frame in the page layer's pixels, and what a look drawn inside it needs. */
|
|
386
|
+
interface FramePixels extends PixelBox {
|
|
387
|
+
/** Its turn on screen: its own and the page's, degrees clockwise. */
|
|
388
|
+
rotationOnScreen: number;
|
|
389
|
+
/**
|
|
390
|
+
* How large the frame is on screen relative to the annotation at its 100%
|
|
391
|
+
* size: the zoom, or for a body that keeps its size on screen, the zoom
|
|
392
|
+
* capped at 1. A look drawn at `design` size is scaled by this.
|
|
393
|
+
*/
|
|
394
|
+
scale: number;
|
|
395
|
+
/** The frame's size at the annotation's 100% size, in pixels: the size a look is drawn at. */
|
|
396
|
+
design: {
|
|
397
|
+
width: number;
|
|
398
|
+
height: number;
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
/** A box inside its frame as CSS percentages of the frame, so it lands in place at any size. */
|
|
402
|
+
interface FrameFraction {
|
|
403
|
+
left: string;
|
|
404
|
+
top: string;
|
|
405
|
+
width: string;
|
|
406
|
+
height: string;
|
|
407
|
+
transform: string | undefined;
|
|
408
|
+
}
|
|
409
|
+
/** A frame in the page layer's pixels: where it is, its turn, and the size and scale a look is drawn at. */
|
|
410
|
+
declare function frameInPixels(frame: FrameBox, page: PageLayerTransform): FramePixels;
|
|
411
|
+
/**
|
|
412
|
+
* A raster inside its frame, as CSS percentages of the frame. `raster`'s box
|
|
413
|
+
* is relative to the frame's box, as the annotation plugin hands it out.
|
|
414
|
+
*/
|
|
415
|
+
declare function rasterInFrame(raster: TurnedBox, frame: TurnedBox): FrameFraction;
|
|
416
|
+
/** The frame a renderer's look draws into: the size to draw at, its turn on screen, and its scale. */
|
|
417
|
+
interface AnnotationLookFrame {
|
|
418
|
+
width: number;
|
|
419
|
+
height: number;
|
|
420
|
+
/** Its turn on screen, the page's and its own, degrees clockwise. */
|
|
421
|
+
rotation: number;
|
|
422
|
+
/** How much the layer scales what the look draws. */
|
|
423
|
+
scale: number;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* The frame a look draws into. A `scaled` look (the default) draws at the
|
|
427
|
+
* annotation's 100% size (`design`) inside an element of that size, which
|
|
428
|
+
* the layer scales by `scale` from its top-left corner; an unscaled look
|
|
429
|
+
* draws at the frame's size on screen.
|
|
430
|
+
*/
|
|
431
|
+
declare function lookFrameOf(frame: FramePixels, scaled: boolean): AnnotationLookFrame;
|
|
175
432
|
//#endregion
|
|
176
433
|
//#region src/cursor.d.ts
|
|
177
434
|
/**
|
|
178
|
-
* SVG → CSS cursor string. The armed-tool indicator is the
|
|
435
|
+
* SVG → CSS cursor string. The armed-tool indicator is the cursor itself (the
|
|
179
436
|
* only zero-latency pointer-locked pixel the web has — the OS composites it),
|
|
180
437
|
* so an app hands its toolbar icon here and assigns the result via the
|
|
181
438
|
* interaction hub's `setToolCursor`.
|
|
@@ -207,14 +464,43 @@ interface SvgCursorOptions {
|
|
|
207
464
|
}
|
|
208
465
|
/** Build the CSS cursor value: `url("data:image/svg+xml,…") x y, fallback`. */
|
|
209
466
|
declare function svgCursor({ svg, hotspot, fallback }: SvgCursorOptions): string;
|
|
467
|
+
/** One cursor slot: an SVG image ({@link SvgCursorOptions}) or a plain CSS cursor ('crosshair', 'url(…) 4 4, copy'). */
|
|
468
|
+
type ToolCursorImage = SvgCursorOptions | string;
|
|
469
|
+
/**
|
|
470
|
+
* A tool's cursors: the tool, and its cursors by keyword. Build `svg` from the same icon your
|
|
471
|
+
* toolbar shows, so the cursor and the button never drift apart.
|
|
472
|
+
*/
|
|
473
|
+
interface ToolCursorSpec {
|
|
474
|
+
toolId: string;
|
|
475
|
+
/**
|
|
476
|
+
* keyword → cursor: replace the keywords this tool can show (its own cursor, 'crosshair' or
|
|
477
|
+
* 'copy', and hover claims, 'text' over text) with the tool's look. Keywords left out show as
|
|
478
|
+
* they are: a markup tool's 'default' stays the bare arrow, a 'move' claim drops the icon. An
|
|
479
|
+
* SVG value's `fallback` defaults to the keyword it replaces.
|
|
480
|
+
*/
|
|
481
|
+
cursors: Record<string, ToolCursorImage>;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* A tool's cursors as CSS cursor values, for the interaction hub's `setToolCursor(toolId,
|
|
485
|
+
* cursors)`: a string stays as it is, an SVG becomes its `url(…)` cursor, falling back to the
|
|
486
|
+
* keyword it replaces unless it names its own fallback.
|
|
487
|
+
*/
|
|
488
|
+
declare function toolCursorsOf(cursors: Record<string, ToolCursorImage>): Record<string, string>;
|
|
210
489
|
//#endregion
|
|
211
490
|
//#region src/external-uri.d.ts
|
|
212
491
|
/**
|
|
213
|
-
* Validate a link URI for opening in the browser. Returns the URI when its
|
|
214
|
-
* scheme is allowed (scheme-relative and bare URIs
|
|
215
|
-
*
|
|
492
|
+
* Validate a link URI for opening in the browser. Returns the absolute URI to open when its
|
|
493
|
+
* scheme is allowed (scheme-relative and bare `www.` URIs become https), else `null`. Never
|
|
494
|
+
* throws — a malformed URI is just an unopenable one.
|
|
216
495
|
*/
|
|
217
496
|
declare function sanitizeExternalUri(uri: string, allowedSchemes?: Iterable<string>): string | null;
|
|
497
|
+
/**
|
|
498
|
+
* Open a link target in a new tab when its address is allowed (`http`,
|
|
499
|
+
* `https`, `mailto`, `tel`); anything else is refused. True when it opened.
|
|
500
|
+
* Call it inside the user's click (the link plugin's `activate()` does), so
|
|
501
|
+
* the click is still the gesture that opens the tab.
|
|
502
|
+
*/
|
|
503
|
+
declare function openExternalUri(uri: string): boolean;
|
|
218
504
|
//#endregion
|
|
219
505
|
//#region src/actions-ui.d.ts
|
|
220
506
|
/** Structural twin of plugin-actions' `ActionOrigin`. */
|
|
@@ -226,20 +512,20 @@ interface ActionsUiEffectContext {
|
|
|
226
512
|
}
|
|
227
513
|
/** Structural twin of plugin-actions' `ActionUiAdapter`. */
|
|
228
514
|
interface ActionsUiAdapterShape {
|
|
229
|
-
openUri(uri: string,
|
|
515
|
+
openUri(uri: string, options: {
|
|
230
516
|
isMap: boolean;
|
|
231
517
|
origin: ActionsUiOrigin;
|
|
232
518
|
}): void;
|
|
233
|
-
print(
|
|
234
|
-
alert?(message: string,
|
|
519
|
+
print(options?: ActionsUiEffectContext): void;
|
|
520
|
+
alert?(message: string, options: ActionsUiEffectContext & {
|
|
235
521
|
icon: number;
|
|
236
522
|
title?: string;
|
|
237
523
|
}): void;
|
|
238
|
-
gotoPage?(page: number,
|
|
524
|
+
gotoPage?(page: number, options: ActionsUiEffectContext): void;
|
|
239
525
|
}
|
|
240
526
|
interface DefaultActionsUiAdapterOptions {
|
|
241
527
|
/**
|
|
242
|
-
* Per-handler overrides. Pass a
|
|
528
|
+
* Per-handler overrides. Pass a function for late binding (a binding's
|
|
243
529
|
* mutable handlers ref) — it is consulted on every effect, so a fresh
|
|
244
530
|
* closure never needs a reinstall.
|
|
245
531
|
*/
|
|
@@ -250,12 +536,18 @@ interface DefaultActionsUiAdapterOptions {
|
|
|
250
536
|
declare const createDefaultActionsUiAdapter: (options?: DefaultActionsUiAdapterOptions) => ActionsUiAdapterShape;
|
|
251
537
|
//#endregion
|
|
252
538
|
//#region src/painted-image.d.ts
|
|
253
|
-
/**
|
|
539
|
+
/**
|
|
540
|
+
* A browser image source whose object URL has an explicit lifetime: an
|
|
541
|
+
* engine `PageImageHandle`, whose `objectUrl()` is cancellable and follows an
|
|
542
|
+
* `AbortSignal` through `abortWith()`.
|
|
543
|
+
*/
|
|
254
544
|
interface ObjectUrlImageSource {
|
|
255
|
-
objectUrl(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
545
|
+
objectUrl(): {
|
|
546
|
+
abortWith(signal: AbortSignal): PromiseLike<{
|
|
547
|
+
url: string;
|
|
548
|
+
revoke(): void;
|
|
549
|
+
}>;
|
|
550
|
+
};
|
|
259
551
|
}
|
|
260
552
|
interface PaintedImageCallbacks {
|
|
261
553
|
onPainted(): void;
|
|
@@ -280,9 +572,9 @@ declare function bindPaintedImage(image: HTMLImageElement, source: ObjectUrlImag
|
|
|
280
572
|
* stays plugin-free, per the layering law).
|
|
281
573
|
*
|
|
282
574
|
* Honesty about reach: `navigator.vibrate` works on Android browsers and is
|
|
283
|
-
*
|
|
575
|
+
* not implemented in iOS Safari — there the default provider is a silent
|
|
284
576
|
* no-op until Apple ships a haptics API. (The community switch-control hacks
|
|
285
|
-
* were evaluated and deliberately
|
|
577
|
+
* were evaluated and deliberately not shipped: Apple patched programmatic
|
|
286
578
|
* triggering in iOS 26.5, leaving only tap-on-control tricks that don't fit a
|
|
287
579
|
* viewer's gesture moments.) The real iPhone haptic today comes through a
|
|
288
580
|
* native shell: a WKWebView embedder installs a script message handler and
|
|
@@ -303,7 +595,7 @@ interface WebPlatformFeedback {
|
|
|
303
595
|
declare const vibrationFeedback: WebPlatformFeedback;
|
|
304
596
|
/**
|
|
305
597
|
* A provider for native iOS shells: forwards each call to a WKWebView script
|
|
306
|
-
* message handler the
|
|
598
|
+
* message handler the host app installed under `handlerName` — an explicit
|
|
307
599
|
* contract between the embedder and their own app, never a global this library
|
|
308
600
|
* sniffs on its own. The message shape is
|
|
309
601
|
* `{ family: 'selection' } | { family: 'impact', weight } | { family: 'notify', kind }`;
|
|
@@ -315,40 +607,40 @@ declare const wkFeedback: (handlerName: string, fallback?: WebPlatformFeedback)
|
|
|
315
607
|
//#endregion
|
|
316
608
|
//#region src/stage-gestures.d.ts
|
|
317
609
|
/**
|
|
318
|
-
* Stage gesture controller — the
|
|
610
|
+
* Stage gesture controller — the one DOM input binding for a Stage surface,
|
|
319
611
|
* shared by every framework adapter (React, Angular, …) so the feel can never
|
|
320
612
|
* drift between them.
|
|
321
613
|
*
|
|
322
614
|
* The premise (see the stage plugin's camera doctrine): desktop inputs arrive
|
|
323
615
|
* with physics already applied by the OS — momentum lives in the wheel stream,
|
|
324
|
-
* a trackpad pinch is one pre-arbitrated gesture stream. Touch arrives
|
|
616
|
+
* a trackpad pinch is one pre-arbitrated gesture stream. Touch arrives raw:
|
|
325
617
|
* with `touch-action: none` the platform scroller is out of the loop, so the
|
|
326
618
|
* ballistics (velocity → fling) and the arbitration (is this contact a scroll,
|
|
327
619
|
* a pinch, a tap, or a tool gesture?) must be synthesized here.
|
|
328
620
|
*
|
|
329
|
-
* Arbitration is
|
|
621
|
+
* Arbitration is modality-aware:
|
|
330
622
|
* - touch — navigation-first: one finger pans (whatever tool is armed), two
|
|
331
623
|
* fingers pinch-zoom around their centroid, release velocity flings, a tap
|
|
332
624
|
* forwards as a click, a double-tap zoom-toggles, a long-press hands the
|
|
333
625
|
* gesture to the interaction hub (text selection), and a second finger
|
|
334
|
-
* landing mid-tool-gesture
|
|
626
|
+
* landing mid-tool-gesture cancels it into a pinch (the Notes/Procreate
|
|
335
627
|
* convention).
|
|
336
628
|
* - mouse/pen — tool-first, exactly the pre-existing behavior: with a hub,
|
|
337
629
|
* every down/move/up forwards (pan is the pan tool's job); without one,
|
|
338
630
|
* dragging pans. Wheel and Safari-trackpad gesture events are unchanged.
|
|
339
631
|
*
|
|
340
|
-
* Camera writes are rAF-
|
|
632
|
+
* Camera writes are rAF-coalesced: pointer events only update gesture state;
|
|
341
633
|
* one animation-frame tick applies at most one pan and one zoom per frame,
|
|
342
634
|
* inside the host's begin/endGesture transaction. Events may arrive at 120 Hz;
|
|
343
635
|
* the camera moves at display rate.
|
|
344
636
|
*
|
|
345
|
-
* Dependency note: this module speaks to the stage through the
|
|
346
|
-
* {@link StageGestureHost} interface (satisfied by `
|
|
637
|
+
* Dependency note: this module speaks to the stage through the structural
|
|
638
|
+
* {@link StageGestureHost} interface (satisfied by `StageHostCapability`) and to
|
|
347
639
|
* the interaction hub through {@link StageGestureSink} (a closure the adapter
|
|
348
640
|
* builds) — @embedpdf/web stays free of plugin imports, per the layering law.
|
|
349
641
|
*/
|
|
350
642
|
type StagePointerKind = 'mouse' | 'pen' | 'touch';
|
|
351
|
-
/** What the controller needs from the camera — `
|
|
643
|
+
/** What the controller needs from the camera — `StageHostCapability` satisfies it. */
|
|
352
644
|
interface StageGestureHost {
|
|
353
645
|
panBy(dxScreen: number, dyScreen: number): void;
|
|
354
646
|
zoomAround(screenPt: {
|
|
@@ -362,7 +654,7 @@ interface StageGestureHost {
|
|
|
362
654
|
/** Momentum pan from a release velocity in screen px/s. */
|
|
363
655
|
fling(velocityX: number, velocityY: number): void;
|
|
364
656
|
/** True while a tween/fling runs — a touch-down then is a "catch", not a tap. */
|
|
365
|
-
|
|
657
|
+
isMoving(): boolean;
|
|
366
658
|
doubleTapZoom(screenPt: {
|
|
367
659
|
x: number;
|
|
368
660
|
y: number;
|
|
@@ -370,25 +662,25 @@ interface StageGestureHost {
|
|
|
370
662
|
}
|
|
371
663
|
/**
|
|
372
664
|
* Where non-navigation gestures go — the adapter's bridge to the interaction
|
|
373
|
-
* hub. Every callback receives the
|
|
665
|
+
* hub. Every callback receives the original PointerEvent so the adapter can
|
|
374
666
|
* resolve pages/points exactly as it always has. Omit the sink entirely for a
|
|
375
667
|
* hub-less (built-in pan) stage.
|
|
376
668
|
*/
|
|
377
669
|
interface StageGestureSink {
|
|
378
|
-
down(
|
|
379
|
-
move(
|
|
380
|
-
up(
|
|
670
|
+
down(event: PointerEvent, clickCount: number): void;
|
|
671
|
+
move(event: PointerEvent): void;
|
|
672
|
+
up(event: PointerEvent): void;
|
|
381
673
|
/** The gesture was taken over by navigation (second finger → pinch) or
|
|
382
674
|
* cancelled by the system — abort, don't commit. */
|
|
383
|
-
cancel(
|
|
675
|
+
cancel(event: PointerEvent): void;
|
|
384
676
|
/** Pointer travel with no gesture in flight — cursor feedback. */
|
|
385
|
-
hover(
|
|
677
|
+
hover(event: PointerEvent): void;
|
|
386
678
|
/** A touch press held still: hand the gesture to the hub (the adapter
|
|
387
679
|
* typically forwards it as a word-select down). Subsequent move/up arrive
|
|
388
680
|
* via {@link move}/{@link up}. */
|
|
389
|
-
longPress(
|
|
681
|
+
longPress(event: PointerEvent): void;
|
|
390
682
|
/**
|
|
391
|
-
* Touch-consent pre-flight, asked at touch-down
|
|
683
|
+
* Touch-consent pre-flight, asked at touch-down before the contact is
|
|
392
684
|
* classified: does a tool have standing to own this contact? True when the
|
|
393
685
|
* armed tool takes fingers wholesale (a drawing tool) or something under
|
|
394
686
|
* the point claims its drags (a selected annotation's body or handles).
|
|
@@ -396,7 +688,7 @@ interface StageGestureSink {
|
|
|
396
688
|
* where a second finger still cancels it into a pinch. Must be a pure
|
|
397
689
|
* read. Absent = never; the contact navigates.
|
|
398
690
|
*/
|
|
399
|
-
claimsPoint?(
|
|
691
|
+
claimsPoint?(event: PointerEvent): boolean;
|
|
400
692
|
}
|
|
401
693
|
/** The wheel fields the zoom classifier reads (see `./wheel`'s `WheelSample`). */
|
|
402
694
|
interface StageWheelSample {
|
|
@@ -411,7 +703,7 @@ interface StageGestureOptions {
|
|
|
411
703
|
* swallowed, never page-zooming the browser. Default true. */
|
|
412
704
|
zoomGestures?: boolean;
|
|
413
705
|
/** The wheel → zoom-factor classifier. Defaults to this package's
|
|
414
|
-
* `wheelZoomFactor` (browser wheel classification lives
|
|
706
|
+
* `wheelZoomFactor` (browser wheel classification lives here, with the rest
|
|
415
707
|
* of the browser input handling); inject to override or to fake in tests. */
|
|
416
708
|
wheelZoomFactor?: (sample: StageWheelSample) => number;
|
|
417
709
|
/** Tool routing for non-navigation gestures; omit for built-in-pan stages. */
|
|
@@ -429,7 +721,7 @@ interface StageGestureOptions {
|
|
|
429
721
|
* Release velocity from a trail of pointer samples: the mean velocity over the
|
|
430
722
|
* trailing `windowMs` (first-to-last inside the window). Null when the trail is
|
|
431
723
|
* too thin or too stale to trust — the standard "held still, then let go"
|
|
432
|
-
* case, which must
|
|
724
|
+
* case, which must not fling. Pure; exported for tests.
|
|
433
725
|
*/
|
|
434
726
|
declare function computeReleaseVelocity(samples: ReadonlyArray<{
|
|
435
727
|
t: number;
|
|
@@ -440,7 +732,7 @@ declare function computeReleaseVelocity(samples: ReadonlyArray<{
|
|
|
440
732
|
vy: number;
|
|
441
733
|
} | null;
|
|
442
734
|
/** Attach the gesture controller to a Stage container. Returns the detach fn. */
|
|
443
|
-
declare function createStageGestureController(
|
|
735
|
+
declare function createStageGestureController(element: HTMLElement, host: StageGestureHost, options: StageGestureOptions): () => void;
|
|
444
736
|
//#endregion
|
|
445
737
|
//#region src/selection-handles.d.ts
|
|
446
738
|
/**
|
|
@@ -450,12 +742,12 @@ declare function createStageGestureController(el: HTMLElement, host: StageGestur
|
|
|
450
742
|
* `handles` module; this file never imports it, per the layering law:
|
|
451
743
|
* structural interfaces only).
|
|
452
744
|
*
|
|
453
|
-
* The load-bearing subtlety this module owns: the pointer-
|
|
454
|
-
* a
|
|
745
|
+
* The load-bearing subtlety this module owns: the pointer-down shield must be
|
|
746
|
+
* a native listener. The stage's gesture controller listens natively on the
|
|
455
747
|
* container, so a framework-synthetic stopPropagation (React runs its
|
|
456
|
-
* handlers at the root,
|
|
748
|
+
* handlers at the root, after the container's native ones) would be too late
|
|
457
749
|
* — the stage would already be panning underneath the handle drag. Once the
|
|
458
|
-
* down is captured here, movement tracks by
|
|
750
|
+
* down is captured here, movement tracks by client deltas from the handle's
|
|
459
751
|
* own base point: no DOM geometry reads, and the client↔overlay conversion
|
|
460
752
|
* cancels out.
|
|
461
753
|
*/
|
|
@@ -472,7 +764,7 @@ interface SelectionHandleSession {
|
|
|
472
764
|
interface AttachSelectionHandleOptions {
|
|
473
765
|
/**
|
|
474
766
|
* Called at pointer-down to arm a drag: return the drag session plus the
|
|
475
|
-
* handle's current
|
|
767
|
+
* handle's current base point in overlay space (the bar's midpoint — the
|
|
476
768
|
* point the user grabbed). Return null to decline (endpoint vanished, page
|
|
477
769
|
* not laid out) — the press then does nothing and nothing is captured.
|
|
478
770
|
*/
|
|
@@ -482,30 +774,30 @@ interface AttachSelectionHandleOptions {
|
|
|
482
774
|
} | null;
|
|
483
775
|
}
|
|
484
776
|
/** Bind one handle element. Returns the detach fn. */
|
|
485
|
-
declare function attachSelectionHandle(
|
|
777
|
+
declare function attachSelectionHandle(element: HTMLElement, options: AttachSelectionHandleOptions): () => void;
|
|
486
778
|
//#endregion
|
|
487
779
|
//#region src/stage-surface.d.ts
|
|
488
780
|
interface SurfacePoint {
|
|
489
781
|
x: number;
|
|
490
782
|
y: number;
|
|
491
783
|
}
|
|
492
|
-
/** What the binding needs from the stage — `
|
|
784
|
+
/** What the binding needs from the stage — `StageHostCapability` satisfies it. */
|
|
493
785
|
interface StageSurfaceHost extends StageGestureHost {
|
|
494
|
-
|
|
786
|
+
setViewportSize(size: {
|
|
495
787
|
width: number;
|
|
496
788
|
height: number;
|
|
497
789
|
}): void;
|
|
498
790
|
setDevicePixelRatio(ratio: number): void;
|
|
499
791
|
/** Viewport point → the page under it (with per-page display context), or null over a gap. */
|
|
500
|
-
|
|
501
|
-
|
|
792
|
+
getPageAt(screen: SurfacePoint): {
|
|
793
|
+
ref: PageRef;
|
|
502
794
|
point: SurfacePoint;
|
|
503
795
|
scale?: number;
|
|
504
796
|
rotation?: 0 | 90 | 180 | 270;
|
|
505
797
|
zoom?: number;
|
|
506
798
|
} | null;
|
|
507
|
-
/** Viewport point → a
|
|
508
|
-
|
|
799
|
+
/** Viewport point → a specific page's page space, unclamped (frame-stable projection). */
|
|
800
|
+
viewportToPage(page: PageRef, screen: SurfacePoint): SurfacePoint | null;
|
|
509
801
|
}
|
|
510
802
|
/**
|
|
511
803
|
* The page-resolved sample the binding hands the hub — structurally a
|
|
@@ -517,13 +809,13 @@ interface StageSurfaceSample {
|
|
|
517
809
|
phase: 'down' | 'move' | 'up' | 'cancel';
|
|
518
810
|
viewport: SurfacePoint;
|
|
519
811
|
page?: {
|
|
520
|
-
|
|
812
|
+
ref: PageRef;
|
|
521
813
|
point: SurfacePoint;
|
|
522
814
|
scale?: number;
|
|
523
815
|
rotation?: 0 | 90 | 180 | 270;
|
|
524
816
|
zoom?: number;
|
|
525
817
|
};
|
|
526
|
-
project: (
|
|
818
|
+
project: (page: PageRef) => SurfacePoint | null;
|
|
527
819
|
modifiers: {
|
|
528
820
|
shift: boolean;
|
|
529
821
|
alt: boolean;
|
|
@@ -535,11 +827,11 @@ interface StageSurfaceSample {
|
|
|
535
827
|
gesture?: 'long-press';
|
|
536
828
|
source?: string;
|
|
537
829
|
}
|
|
538
|
-
/** What the binding needs from the interaction hub — `
|
|
830
|
+
/** What the binding needs from the interaction hub — `InteractionHostCapability` satisfies it. */
|
|
539
831
|
interface StageSurfaceHub {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
832
|
+
dispatchPointer(sample: StageSurfaceSample): void;
|
|
833
|
+
getActiveTool(): {
|
|
834
|
+
touch?: 'draw' | 'tap';
|
|
543
835
|
};
|
|
544
836
|
wouldClaimTouch(sample: StageSurfaceSample): boolean;
|
|
545
837
|
}
|
|
@@ -547,7 +839,7 @@ interface StageSurfaceOptions {
|
|
|
547
839
|
/** Route pointer input to the interaction hub (page-resolved samples) instead
|
|
548
840
|
* of built-in drag-to-pan. Omit/null for a hub-less stage. */
|
|
549
841
|
hub?: StageSurfaceHub | null;
|
|
550
|
-
/** The lens identity stamped on every sample (`
|
|
842
|
+
/** The lens identity stamped on every sample (`StageHostCapability.getLensId()`),
|
|
551
843
|
* so lens-scoped handlers only see their own stage's input. */
|
|
552
844
|
source?: string;
|
|
553
845
|
/** Ambient zoom gestures (see {@link StageGestureOptions}). Default true. */
|
|
@@ -556,7 +848,7 @@ interface StageSurfaceOptions {
|
|
|
556
848
|
wheelZoomFactor?: (sample: StageWheelSample) => number;
|
|
557
849
|
}
|
|
558
850
|
/** Attach the full surface binding. Returns the detach fn. */
|
|
559
|
-
declare function createStageSurface(
|
|
851
|
+
declare function createStageSurface(element: HTMLElement, stage: StageSurfaceHost, options?: StageSurfaceOptions): () => void;
|
|
560
852
|
//#endregion
|
|
561
853
|
//#region src/wheel.d.ts
|
|
562
854
|
/**
|
|
@@ -566,14 +858,14 @@ declare function createStageSurface(el: HTMLElement, stage: StageSurfaceHost, op
|
|
|
566
858
|
* A ctrl/cmd wheel event is one of three physically different inputs that
|
|
567
859
|
* happen to share an event type, each with its own unit system:
|
|
568
860
|
*
|
|
569
|
-
* • trackpad
|
|
861
|
+
* • trackpad pinch — browsers (Chrome/Edge/Firefox) synthesize ctrl+wheel
|
|
570
862
|
* px-deltas scaled to the de-facto convention that `exp(-Δ/100)` tracks
|
|
571
863
|
* the physical finger scale 1:1. Anything weaker feels dead (the content
|
|
572
864
|
* must track the fingers — the Figma/maps feel).
|
|
573
|
-
* • mouse
|
|
865
|
+
* • mouse notches — coarse steps: ±100/±120 px in Chrome, lines/pages mode
|
|
574
866
|
* in Firefox. The pinch mapping would triple per click; a notch instead
|
|
575
867
|
* steps by 1.2, the same ratio as the zoom buttons.
|
|
576
|
-
* • cmd + continuous
|
|
868
|
+
* • cmd + continuous scroll — real scroll px, big and streaming (with
|
|
577
869
|
* momentum): a gentle scrub coefficient. A cmd+mouse notch (±120 px)
|
|
578
870
|
* lands within 0.3% of the 1.2 button step, so it needs no special case.
|
|
579
871
|
*
|
|
@@ -588,7 +880,7 @@ interface WheelSample {
|
|
|
588
880
|
metaKey: boolean;
|
|
589
881
|
}
|
|
590
882
|
/** Zoom factor for a ctrl/cmd wheel event (the caller decides zoom vs pan). */
|
|
591
|
-
declare function wheelZoomFactor(
|
|
883
|
+
declare function wheelZoomFactor(sample: WheelSample): number;
|
|
592
884
|
//#endregion
|
|
593
885
|
//#region src/byte-store.d.ts
|
|
594
886
|
/**
|
|
@@ -614,11 +906,11 @@ interface IndexedDbByteStoreOptions {
|
|
|
614
906
|
storeName?: string;
|
|
615
907
|
}
|
|
616
908
|
/** Open (creating on first use) one IndexedDB object store keyed by id. */
|
|
617
|
-
declare function indexedDbByteStore(dbName: string,
|
|
909
|
+
declare function indexedDbByteStore(dbName: string, options?: IndexedDbByteStoreOptions): ByteStore;
|
|
618
910
|
//#endregion
|
|
619
911
|
//#region src/rich-text-editor.d.ts
|
|
620
912
|
/**
|
|
621
|
-
* Rich text editor binding — the
|
|
913
|
+
* Rich text editor binding — the one contentEditable mechanics module for a
|
|
622
914
|
* FreeText annotation, shared by every framework adapter (React, Angular,
|
|
623
915
|
* Vue, Svelte…) so editing can never drift between them:
|
|
624
916
|
*
|
|
@@ -631,7 +923,7 @@ declare function indexedDbByteStore(dbName: string, opts?: IndexedDbByteStoreOpt
|
|
|
631
923
|
* • hold re-renders during IME composition, paste as plain text, forward
|
|
632
924
|
* Cmd/Ctrl+B/I/U as commands
|
|
633
925
|
*
|
|
634
|
-
* The browser owns typing; this module only translates. The
|
|
926
|
+
* The browser owns typing; this module only translates. The policy — what a
|
|
635
927
|
* command does to the document, when to commit, what a family maps to —
|
|
636
928
|
* belongs to the host (the annotation plugin), reached through the
|
|
637
929
|
* structural {@link RichTextEditorHost}: @embedpdf/web imports no plugin,
|
|
@@ -642,9 +934,9 @@ declare function indexedDbByteStore(dbName: string, opts?: IndexedDbByteStoreOpt
|
|
|
642
934
|
* runs concatenated, a hard break inside a run is a `\r` too. The same
|
|
643
935
|
* arithmetic the core's run algebra uses.
|
|
644
936
|
*
|
|
645
|
-
* Known limits
|
|
646
|
-
*
|
|
647
|
-
* the
|
|
937
|
+
* Known limits, by design: the browser's native undo stack does not span a
|
|
938
|
+
* host-driven restyle; DOM line wrapping approximates the engine's layout,
|
|
939
|
+
* the appearance stream is the truth.
|
|
648
940
|
*/
|
|
649
941
|
type RichTextEditorDecoration = 'underline' | 'line-through' | 'word';
|
|
650
942
|
type RichTextEditorScript = 'normal' | 'sub' | 'super';
|
|
@@ -689,12 +981,12 @@ interface RichTextEditorHost {
|
|
|
689
981
|
/** A keyboard command the host applies to the current selection. */
|
|
690
982
|
onCommand(command: RichTextEditorCommand): void;
|
|
691
983
|
/** The CSS family list for a PDF family ("Helvetica" → a web stack, a
|
|
692
|
-
* registered family →
|
|
984
|
+
* registered family → the family its face is mounted under, see `mountWebFont`). */
|
|
693
985
|
cssFontFamily(family: string): string;
|
|
694
986
|
}
|
|
695
987
|
interface RichTextEditorProps {
|
|
696
988
|
document: RichTextEditorDocument;
|
|
697
|
-
/** Screen px per
|
|
989
|
+
/** Screen px per page unit (the page scale): sizes are page points. */
|
|
698
990
|
scale: number;
|
|
699
991
|
}
|
|
700
992
|
interface RichTextEditorBinding {
|
|
@@ -768,26 +1060,166 @@ declare function offsetOfPosition(root: EditorNode, position: EditorPosition): n
|
|
|
768
1060
|
* else the empty block / the slot after a hard break the offset names. */
|
|
769
1061
|
declare function positionOfOffset(root: EditorNode, offset: number): EditorPosition | null;
|
|
770
1062
|
/** Bind one contentEditable element. Returns the Svelte-action-shaped handle. */
|
|
771
|
-
declare function attachRichTextEditor(
|
|
1063
|
+
declare function attachRichTextEditor(element: HTMLElement, host: RichTextEditorHost, initial: RichTextEditorProps): RichTextEditorBinding;
|
|
772
1064
|
//#endregion
|
|
773
1065
|
//#region src/web-font.d.ts
|
|
774
1066
|
/**
|
|
775
1067
|
* Mount a registered font for the DOM: the engine lays text out with the
|
|
776
1068
|
* font's bytes, the browser needs the same face as a `@font-face` so the
|
|
777
1069
|
* live editor and the vector renderer show the glyphs the appearance stream
|
|
778
|
-
* will bake. The family
|
|
779
|
-
* annotation plugin emits for a registered font (`cssFontFamily`) — so
|
|
780
|
-
* mounting under the key is what makes the two agree.
|
|
1070
|
+
* will bake. The face's family is {@link webFontFamily} of the key.
|
|
781
1071
|
*
|
|
782
1072
|
* Returns the unmount. Idempotent per (document, key): a second mount of a
|
|
783
1073
|
* key already in the document's font set is a no-op that still returns an
|
|
784
|
-
* unmount of its own (the face leaves when the
|
|
1074
|
+
* unmount of its own (the face leaves when the last holder unmounts).
|
|
785
1075
|
*/
|
|
786
1076
|
declare function mountWebFont(key: string, data: ArrayBuffer | Uint8Array, options?: {
|
|
787
1077
|
document?: Document;
|
|
788
1078
|
weight?: number | string;
|
|
789
1079
|
style?: 'normal' | 'italic';
|
|
790
1080
|
}): Promise<() => void>;
|
|
1081
|
+
/**
|
|
1082
|
+
* A font program to mount: its CSS family, its style, and its bytes. The
|
|
1083
|
+
* structural twin of `@embedpdf/core-fonts`' `FontProgram`, whose family is
|
|
1084
|
+
* named by the program's hash, so it never shadows another font.
|
|
1085
|
+
*/
|
|
1086
|
+
interface MountableFontProgram {
|
|
1087
|
+
readonly family: string;
|
|
1088
|
+
readonly weight: number;
|
|
1089
|
+
readonly style: 'normal' | 'italic';
|
|
1090
|
+
load(): Promise<Uint8Array>;
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Mount a program under its own family, as it is (already in the viewer's
|
|
1094
|
+
* namespace), in its own weight and style, so CSS asking for that style takes
|
|
1095
|
+
* it as it is and never fakes a bold or an italic. Refcounted per document
|
|
1096
|
+
* like {@link mountWebFont}; resolves with the unmount.
|
|
1097
|
+
*/
|
|
1098
|
+
declare function mountFontProgram(program: MountableFontProgram, options?: {
|
|
1099
|
+
document?: Document;
|
|
1100
|
+
}): Promise<() => void>;
|
|
1101
|
+
/**
|
|
1102
|
+
* The programs one layer has mounted: each mounted once, however often it's
|
|
1103
|
+
* asked for, and all let go together when the layer goes (a program another
|
|
1104
|
+
* layer holds stays, refcounted per document). A mount after the release
|
|
1105
|
+
* holds again, for a layer that comes back (React's strict mode runs effects
|
|
1106
|
+
* twice).
|
|
1107
|
+
*/
|
|
1108
|
+
declare function createFontMounts(options?: {
|
|
1109
|
+
document?: Document;
|
|
1110
|
+
}): {
|
|
1111
|
+
mount(programs: readonly MountableFontProgram[]): void;
|
|
1112
|
+
release(): void;
|
|
1113
|
+
};
|
|
1114
|
+
//#endregion
|
|
1115
|
+
//#region src/object-urls.d.ts
|
|
1116
|
+
/** Bytes and their type, as the stamp and annotation plugins hand out previews. */
|
|
1117
|
+
interface PictureBytes {
|
|
1118
|
+
readonly bytes: Uint8Array;
|
|
1119
|
+
readonly mimeType?: string | null;
|
|
1120
|
+
}
|
|
1121
|
+
/** An object URL, and how to release it. */
|
|
1122
|
+
interface ObjectUrl {
|
|
1123
|
+
readonly url: string;
|
|
1124
|
+
revoke(): void;
|
|
1125
|
+
}
|
|
1126
|
+
/** An object URL for bytes. Revoke it when nothing shows it any more. */
|
|
1127
|
+
declare function objectUrlOf(picture: PictureBytes): ObjectUrl;
|
|
1128
|
+
/**
|
|
1129
|
+
* Load a picture and hand its object URL to `onUrl` once it's there (nothing
|
|
1130
|
+
* for `null`). What it returns cancels: a load still running is dropped, and
|
|
1131
|
+
* the URL is revoked. Keep showing the previous URL until `onUrl` brings the
|
|
1132
|
+
* next one, so a swap never flickers.
|
|
1133
|
+
*/
|
|
1134
|
+
declare function loadObjectUrl(load: () => Promise<PictureBytes | null>, onUrl: (url: string) => void): () => void;
|
|
1135
|
+
/**
|
|
1136
|
+
* One picture as its owner hands it out (the annotation plugin's or the form
|
|
1137
|
+
* plugin's `renderAppearances`): an item in one of its states, at its version.
|
|
1138
|
+
*/
|
|
1139
|
+
interface AppearancePicture<Ref> {
|
|
1140
|
+
readonly ref: Ref;
|
|
1141
|
+
/** The state it draws (`/AS`), or `null` for an item without states. */
|
|
1142
|
+
readonly state: string | null;
|
|
1143
|
+
/** The box it was rendered into, in page points. */
|
|
1144
|
+
readonly rect: {
|
|
1145
|
+
x: number;
|
|
1146
|
+
y: number;
|
|
1147
|
+
width: number;
|
|
1148
|
+
height: number;
|
|
1149
|
+
};
|
|
1150
|
+
/** The version of its item it shows: an item at another version looks different now. */
|
|
1151
|
+
readonly version: number;
|
|
1152
|
+
readonly image: ObjectUrlImageSource;
|
|
1153
|
+
}
|
|
1154
|
+
/** A picture's URL, the box it was rendered into, and the version of its item it shows. */
|
|
1155
|
+
interface AppearanceUrl {
|
|
1156
|
+
url: string;
|
|
1157
|
+
box: {
|
|
1158
|
+
x: number;
|
|
1159
|
+
y: number;
|
|
1160
|
+
width: number;
|
|
1161
|
+
height: number;
|
|
1162
|
+
};
|
|
1163
|
+
version: number;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* The picture an item shows, from {@link loadAppearanceUrls}: the one of the
|
|
1167
|
+
* state it's in (`'Off'` when it names none), or its only picture when it has
|
|
1168
|
+
* no states; `null` until it's loaded.
|
|
1169
|
+
*/
|
|
1170
|
+
declare function shownAppearance(urls: Readonly<Record<string, AppearanceUrl>>, itemKey: string, appearanceState: string | null): AppearanceUrl | null;
|
|
1171
|
+
/**
|
|
1172
|
+
* The engine's picture of an annotation as a renderer gets it (its
|
|
1173
|
+
* `appearance`): `{ url }` once {@link loadAppearanceUrls} has loaded the one
|
|
1174
|
+
* of the state it shows, else `null`.
|
|
1175
|
+
*/
|
|
1176
|
+
declare function bakedAppearanceOf(urls: Readonly<Record<string, AppearanceUrl>>, itemKey: string, appearanceState: string | null): {
|
|
1177
|
+
url: string;
|
|
1178
|
+
} | null;
|
|
1179
|
+
/**
|
|
1180
|
+
* The URLs a layer shows, kept from one load to the next: a set stays valid
|
|
1181
|
+
* until the set after it is shown, so a picture that shows again before the
|
|
1182
|
+
* next set arrives (an annotation an undo brings back) still has a live URL.
|
|
1183
|
+
* One per layer, passed to every load; `release()` when the layer goes.
|
|
1184
|
+
*/
|
|
1185
|
+
interface ShownUrls {
|
|
1186
|
+
/** Revoke the URLs shown now: the layer is going. A later load starts afresh. */
|
|
1187
|
+
release(): void;
|
|
1188
|
+
}
|
|
1189
|
+
/** What a layer shows, for {@link loadAppearanceUrls}. */
|
|
1190
|
+
declare function createShownUrls(): ShownUrls;
|
|
1191
|
+
/**
|
|
1192
|
+
* Load a page's pictures, every state of every item, and hand their URLs to
|
|
1193
|
+
* `onLoaded` once all of them are there; the set `shown` held before is
|
|
1194
|
+
* revoked then. {@link shownAppearance} picks an item's: a check box that
|
|
1195
|
+
* changes shows its other picture at once. What it returns cancels: the load
|
|
1196
|
+
* is aborted and the URLs it made are revoked, unless it already handed them
|
|
1197
|
+
* over. Start it again when the page's appearance epoch or the appearance
|
|
1198
|
+
* scale changes, never mid-gesture.
|
|
1199
|
+
*/
|
|
1200
|
+
declare function loadAppearanceUrls<Ref>(shown: ShownUrls, load: (signal: AbortSignal) => Promise<readonly AppearancePicture<Ref>[]>, keyOf: (ref: Ref) => string, onLoaded: (urls: Record<string, AppearanceUrl>) => void): () => void;
|
|
1201
|
+
//#endregion
|
|
1202
|
+
//#region src/picture-or-painting.d.ts
|
|
1203
|
+
type PictureOrPainting<Painting> = {
|
|
1204
|
+
readonly kind: 'picture';
|
|
1205
|
+
readonly picture: AppearanceUrl;
|
|
1206
|
+
} | {
|
|
1207
|
+
readonly kind: 'painting';
|
|
1208
|
+
readonly painting: Painting;
|
|
1209
|
+
} | null;
|
|
1210
|
+
interface LookState<Painting> {
|
|
1211
|
+
/** The owner draws the item live now: a pending change, a widget's look not confirmed yet. */
|
|
1212
|
+
readonly pending: boolean;
|
|
1213
|
+
/** Its picture, for the state it shows; `null` when there is none. */
|
|
1214
|
+
readonly picture: AppearanceUrl | null;
|
|
1215
|
+
/** The item's picture version now. */
|
|
1216
|
+
readonly version: number;
|
|
1217
|
+
/** The page's pictures have loaded at least once. */
|
|
1218
|
+
readonly loaded: boolean;
|
|
1219
|
+
/** Its live drawing; `null` for an item that has none. */
|
|
1220
|
+
readonly paint: () => Painting | null;
|
|
1221
|
+
}
|
|
1222
|
+
declare function pictureOrPainting<Painting>(look: LookState<Painting>): PictureOrPainting<Painting>;
|
|
791
1223
|
//#endregion
|
|
792
1224
|
//#region src/web-font-metrics.d.ts
|
|
793
1225
|
/**
|
|
@@ -848,5 +1280,2248 @@ declare function lineModelFor(cssFamily: string, measure?: (cssFamily: string) =
|
|
|
848
1280
|
*/
|
|
849
1281
|
declare function firstLineShiftFor(cssFamily: string, fontSize: number, measure?: (cssFamily: string) => WebFontMetrics | null): number;
|
|
850
1282
|
//#endregion
|
|
851
|
-
|
|
1283
|
+
//#region src/theme.d.ts
|
|
1284
|
+
/**
|
|
1285
|
+
* The `--epdf-*` CSS variables that theme EmbedPDF, and the CSS value each
|
|
1286
|
+
* painted part uses. Every paint setting (a color, a line width, a dash, a
|
|
1287
|
+
* shadow, an opacity) can also come from a variable, and any variable wins over
|
|
1288
|
+
* any setting: a part looks for its own variable, then the variables of the
|
|
1289
|
+
* parts its default follows (another part, its plugin's accent, the viewer's
|
|
1290
|
+
* accent), and only then uses its setting's value. Parts you style yourself
|
|
1291
|
+
* have no setting, only a variable and a built-in look.
|
|
1292
|
+
*
|
|
1293
|
+
* {@link EPDF_VARIABLES} is plain data with no imports, so a script can read the
|
|
1294
|
+
* list without a browser. {@link epdfThemeVariables} turns a theme written with
|
|
1295
|
+
* setting names into the variables.
|
|
1296
|
+
*/
|
|
1297
|
+
/**
|
|
1298
|
+
* A part other parts' defaults follow: an accent, or a part whose setting is
|
|
1299
|
+
* another part's default, such as the handles the rotation handle looks like.
|
|
1300
|
+
*/
|
|
1301
|
+
type EpdfFollowedVariable = 'accent' | 'annotation-accent' | 'annotation-handle-fill' | 'annotation-handle-stroke';
|
|
1302
|
+
/** One themable part, named by its variable without the `--epdf-` prefix. */
|
|
1303
|
+
interface EpdfVariableDefinition {
|
|
1304
|
+
/**
|
|
1305
|
+
* The setting the variable overrides, as `<plugin>.<path>`: `viewer.` for the
|
|
1306
|
+
* viewer's own settings, `[]` for every entry of a list. Absent for a part you
|
|
1307
|
+
* style yourself, which only has CSS.
|
|
1308
|
+
*/
|
|
1309
|
+
readonly setting?: string;
|
|
1310
|
+
/**
|
|
1311
|
+
* The part whose setting is this part's default, looked up right after the
|
|
1312
|
+
* part's own variable, and followed in turn: the rotation handle's stroke
|
|
1313
|
+
* follows the handles' stroke, which follows the annotation accent, which
|
|
1314
|
+
* follows the viewer's. So `--epdf-annotation-handle-stroke` reaches the
|
|
1315
|
+
* rotation handle before any accent does.
|
|
1316
|
+
*/
|
|
1317
|
+
readonly follows?: EpdfFollowedVariable;
|
|
1318
|
+
/** A translucent default, the accent it follows at this percent: see {@link mixAccent}. */
|
|
1319
|
+
readonly accentPercent?: number;
|
|
1320
|
+
/**
|
|
1321
|
+
* The CSS value of each keyword, for a setting that takes keywords instead of
|
|
1322
|
+
* a CSS value.
|
|
1323
|
+
*/
|
|
1324
|
+
readonly keywords?: Readonly<Record<string, string>>;
|
|
1325
|
+
/** What the part paints when neither its setting nor a variable is set. */
|
|
1326
|
+
readonly default: string;
|
|
1327
|
+
}
|
|
1328
|
+
/** Every theming variable, in the order the theming page lists them. */
|
|
1329
|
+
declare const EPDF_VARIABLES: {
|
|
1330
|
+
readonly accent: {
|
|
1331
|
+
readonly setting: "viewer.accent";
|
|
1332
|
+
readonly default: "#3858e9";
|
|
1333
|
+
};
|
|
1334
|
+
readonly 'page-background': {
|
|
1335
|
+
readonly setting: "viewer.page.background";
|
|
1336
|
+
readonly default: "#ffffff";
|
|
1337
|
+
};
|
|
1338
|
+
readonly 'page-shadow': {
|
|
1339
|
+
readonly setting: "viewer.page.shadow";
|
|
1340
|
+
readonly default: "0 6px 18px rgb(0 0 0 / 0.18)";
|
|
1341
|
+
};
|
|
1342
|
+
readonly 'annotation-accent': {
|
|
1343
|
+
readonly setting: "annotation.chrome.accent";
|
|
1344
|
+
readonly follows: "accent";
|
|
1345
|
+
readonly default: "#3858e9";
|
|
1346
|
+
};
|
|
1347
|
+
readonly 'annotation-outline': {
|
|
1348
|
+
readonly setting: "annotation.chrome.outline.color";
|
|
1349
|
+
readonly follows: "annotation-accent";
|
|
1350
|
+
readonly default: "#3858e9";
|
|
1351
|
+
};
|
|
1352
|
+
readonly 'annotation-outline-width': {
|
|
1353
|
+
readonly setting: "annotation.chrome.outline.width";
|
|
1354
|
+
readonly default: "1";
|
|
1355
|
+
};
|
|
1356
|
+
readonly 'annotation-outline-dash': {
|
|
1357
|
+
readonly setting: "annotation.chrome.outline.style";
|
|
1358
|
+
readonly keywords: {
|
|
1359
|
+
readonly solid: "none";
|
|
1360
|
+
readonly dashed: "4 3";
|
|
1361
|
+
};
|
|
1362
|
+
readonly default: "none";
|
|
1363
|
+
};
|
|
1364
|
+
readonly 'annotation-handle-fill': {
|
|
1365
|
+
readonly setting: "annotation.chrome.handles.fill";
|
|
1366
|
+
readonly default: "#ffffff";
|
|
1367
|
+
};
|
|
1368
|
+
readonly 'annotation-handle-stroke': {
|
|
1369
|
+
readonly setting: "annotation.chrome.handles.stroke";
|
|
1370
|
+
readonly follows: "annotation-accent";
|
|
1371
|
+
readonly default: "#3858e9";
|
|
1372
|
+
};
|
|
1373
|
+
readonly 'annotation-rotation-handle-fill': {
|
|
1374
|
+
readonly setting: "annotation.chrome.rotationHandle.fill";
|
|
1375
|
+
readonly follows: "annotation-handle-fill";
|
|
1376
|
+
readonly default: "#ffffff";
|
|
1377
|
+
};
|
|
1378
|
+
readonly 'annotation-rotation-handle-stroke': {
|
|
1379
|
+
readonly setting: "annotation.chrome.rotationHandle.stroke";
|
|
1380
|
+
readonly follows: "annotation-handle-stroke";
|
|
1381
|
+
readonly default: "#3858e9";
|
|
1382
|
+
};
|
|
1383
|
+
readonly 'annotation-guide': {
|
|
1384
|
+
readonly setting: "annotation.chrome.guides.color";
|
|
1385
|
+
readonly default: "#e91e63";
|
|
1386
|
+
};
|
|
1387
|
+
readonly 'annotation-rotation-guide': {
|
|
1388
|
+
readonly setting: "annotation.chrome.guides.rotationColor";
|
|
1389
|
+
readonly follows: "annotation-accent";
|
|
1390
|
+
readonly default: "#3858e9";
|
|
1391
|
+
};
|
|
1392
|
+
readonly 'annotation-guide-width': {
|
|
1393
|
+
readonly setting: "annotation.chrome.guides.width";
|
|
1394
|
+
readonly default: "1.5";
|
|
1395
|
+
};
|
|
1396
|
+
readonly 'annotation-guide-dash': {
|
|
1397
|
+
readonly setting: "annotation.chrome.guides.style";
|
|
1398
|
+
readonly keywords: {
|
|
1399
|
+
readonly solid: "none";
|
|
1400
|
+
readonly dashed: "4 3";
|
|
1401
|
+
};
|
|
1402
|
+
readonly default: "none";
|
|
1403
|
+
};
|
|
1404
|
+
readonly 'annotation-marquee-fill': {
|
|
1405
|
+
readonly setting: "annotation.chrome.marquee.fill";
|
|
1406
|
+
readonly follows: "annotation-accent";
|
|
1407
|
+
readonly accentPercent: 8;
|
|
1408
|
+
readonly default: "color-mix(in srgb, #3858e9 8%, transparent)";
|
|
1409
|
+
};
|
|
1410
|
+
readonly 'annotation-marquee-stroke': {
|
|
1411
|
+
readonly setting: "annotation.chrome.marquee.stroke";
|
|
1412
|
+
readonly follows: "annotation-accent";
|
|
1413
|
+
readonly default: "#3858e9";
|
|
1414
|
+
};
|
|
1415
|
+
readonly 'annotation-text-outline': {
|
|
1416
|
+
readonly setting: "annotation.chrome.textOutline";
|
|
1417
|
+
readonly follows: "annotation-accent";
|
|
1418
|
+
readonly default: "#3858e9";
|
|
1419
|
+
};
|
|
1420
|
+
readonly 'readout-background': {
|
|
1421
|
+
readonly setting: "annotation.chrome.readout.background";
|
|
1422
|
+
readonly default: "rgb(0 0 0 / 0.8)";
|
|
1423
|
+
};
|
|
1424
|
+
readonly 'readout-color': {
|
|
1425
|
+
readonly setting: "annotation.chrome.readout.color";
|
|
1426
|
+
readonly default: "#ffffff";
|
|
1427
|
+
};
|
|
1428
|
+
readonly 'ghost-opacity': {
|
|
1429
|
+
readonly setting: "annotation.tools[].ghost.opacity";
|
|
1430
|
+
readonly default: "0.5";
|
|
1431
|
+
};
|
|
1432
|
+
readonly 'text-selection': {
|
|
1433
|
+
readonly setting: "selection.color";
|
|
1434
|
+
readonly follows: "accent";
|
|
1435
|
+
readonly accentPercent: 35;
|
|
1436
|
+
readonly default: "color-mix(in srgb, #3858e9 35%, transparent)";
|
|
1437
|
+
};
|
|
1438
|
+
readonly 'text-selection-handle': {
|
|
1439
|
+
readonly setting: "selection.handles.color";
|
|
1440
|
+
readonly follows: "accent";
|
|
1441
|
+
readonly default: "#3858e9";
|
|
1442
|
+
};
|
|
1443
|
+
readonly 'text-selection-handle-shadow': {
|
|
1444
|
+
readonly setting: "selection.handles.shadow";
|
|
1445
|
+
readonly default: "0 1px 4px rgb(0 0 0 / 0.35)";
|
|
1446
|
+
};
|
|
1447
|
+
readonly 'search-highlight': {
|
|
1448
|
+
readonly setting: "search.highlight.color";
|
|
1449
|
+
readonly default: "#ffd500";
|
|
1450
|
+
};
|
|
1451
|
+
readonly 'search-highlight-active': {
|
|
1452
|
+
readonly setting: "search.highlight.activeColor";
|
|
1453
|
+
readonly default: "#ff9632";
|
|
1454
|
+
};
|
|
1455
|
+
readonly 'search-blend-mode': {
|
|
1456
|
+
readonly setting: "search.highlight.blendMode";
|
|
1457
|
+
readonly default: "multiply";
|
|
1458
|
+
};
|
|
1459
|
+
readonly 'form-focus': {
|
|
1460
|
+
readonly setting: "form.focus.color";
|
|
1461
|
+
readonly follows: "accent";
|
|
1462
|
+
readonly default: "#3858e9";
|
|
1463
|
+
};
|
|
1464
|
+
readonly 'form-field-border': {
|
|
1465
|
+
readonly setting: "form.fields.border";
|
|
1466
|
+
readonly follows: "accent";
|
|
1467
|
+
readonly accentPercent: 55;
|
|
1468
|
+
readonly default: "color-mix(in srgb, #3858e9 55%, transparent)";
|
|
1469
|
+
};
|
|
1470
|
+
readonly 'form-field-background': {
|
|
1471
|
+
readonly setting: "form.fields.background";
|
|
1472
|
+
readonly default: "rgb(255 255 255 / 0.92)";
|
|
1473
|
+
};
|
|
1474
|
+
readonly 'form-field-color': {
|
|
1475
|
+
readonly setting: "form.fields.color";
|
|
1476
|
+
readonly default: "#1f2a44";
|
|
1477
|
+
};
|
|
1478
|
+
readonly 'scrollbar-thumb': {
|
|
1479
|
+
readonly default: "rgb(0 0 0 / 0.4)";
|
|
1480
|
+
};
|
|
1481
|
+
readonly 'toolbar-surface': {
|
|
1482
|
+
readonly default: "#ffffff";
|
|
1483
|
+
};
|
|
1484
|
+
readonly 'toolbar-border': {
|
|
1485
|
+
readonly default: "rgb(0 0 0 / 0.15)";
|
|
1486
|
+
};
|
|
1487
|
+
readonly 'toolbar-active': {
|
|
1488
|
+
readonly default: "rgb(0 0 0 / 0.12)";
|
|
1489
|
+
};
|
|
1490
|
+
readonly 'font-mono': {
|
|
1491
|
+
readonly default: "ui-monospace, monospace";
|
|
1492
|
+
};
|
|
1493
|
+
};
|
|
1494
|
+
type Definitions = typeof EPDF_VARIABLES;
|
|
1495
|
+
/** A theming variable's name, without its `--epdf-` prefix. */
|
|
1496
|
+
type EpdfVariable = keyof Definitions;
|
|
1497
|
+
/** A variable that overrides a setting: its part paints with {@link paint}. */
|
|
1498
|
+
type EpdfSettingVariable = { [Name in EpdfVariable]: Definitions[Name] extends {
|
|
1499
|
+
readonly setting: string;
|
|
1500
|
+
} ? Name : never; }[EpdfVariable];
|
|
1501
|
+
/** A part you style yourself, which has no setting: it paints with {@link paintDefault}. */
|
|
1502
|
+
type EpdfCssOnlyVariable = Exclude<EpdfVariable, EpdfSettingVariable>;
|
|
1503
|
+
/** A part whose default is the accent at a percent: that default comes from {@link mixAccent}. */
|
|
1504
|
+
type EpdfTranslucentVariable = { [Name in EpdfVariable]: Definitions[Name] extends {
|
|
1505
|
+
readonly accentPercent: number;
|
|
1506
|
+
} ? Name : never; }[EpdfVariable];
|
|
1507
|
+
/**
|
|
1508
|
+
* The CSS value for a painted part: its own variable, then the variables of the
|
|
1509
|
+
* parts its default follows (the part it follows, its plugin's accent,
|
|
1510
|
+
* `--epdf-accent`), then the setting's value. Put it in a style (`style.stroke`),
|
|
1511
|
+
* not an SVG attribute, because attributes don't read `var()`.
|
|
1512
|
+
*
|
|
1513
|
+
* `paint('annotation-outline', '#3858e9')` is
|
|
1514
|
+
* `var(--epdf-annotation-outline, var(--epdf-annotation-accent, var(--epdf-accent, #3858e9)))`,
|
|
1515
|
+
* `paint('annotation-rotation-handle-fill', '#ffffff')` is
|
|
1516
|
+
* `var(--epdf-annotation-rotation-handle-fill, var(--epdf-annotation-handle-fill, #ffffff))`,
|
|
1517
|
+
* and `paint('search-highlight', '#ffd500')` is `var(--epdf-search-highlight, #ffd500)`.
|
|
1518
|
+
*/
|
|
1519
|
+
declare function paint(name: EpdfSettingVariable, settingValue: string | number): string;
|
|
1520
|
+
/**
|
|
1521
|
+
* The default of a translucent part, such as "the accent at 35%": the accent it
|
|
1522
|
+
* follows, variables included, mixed with transparent. Use it as the setting's
|
|
1523
|
+
* value while the part's own setting is unset.
|
|
1524
|
+
*
|
|
1525
|
+
* The accent variables sit inside the mix, not in {@link paint}'s lookup: there
|
|
1526
|
+
* a set `--epdf-accent` would paint at full strength, and CSS can't mix a
|
|
1527
|
+
* variable only when it's set. So a part's own setting, when you give one, wins
|
|
1528
|
+
* over the accent variables, though not over the part's own variable.
|
|
1529
|
+
*
|
|
1530
|
+
* `mixAccent('text-selection', '#3858e9')` is
|
|
1531
|
+
* `color-mix(in srgb, var(--epdf-accent, #3858e9) 35%, transparent)`.
|
|
1532
|
+
*/
|
|
1533
|
+
declare function mixAccent(name: EpdfTranslucentVariable, accentValue: string): string;
|
|
1534
|
+
/**
|
|
1535
|
+
* The CSS value for a part you style yourself, which has no setting: its
|
|
1536
|
+
* variable, then its built-in look.
|
|
1537
|
+
*
|
|
1538
|
+
* `paintDefault('scrollbar-thumb')` is `var(--epdf-scrollbar-thumb, rgb(0 0 0 / 0.4))`.
|
|
1539
|
+
*/
|
|
1540
|
+
declare function paintDefault(name: EpdfCssOnlyVariable): string;
|
|
1541
|
+
/** A setting's path as a theme writes it: the viewer's own at the top, a list's entries as one. */
|
|
1542
|
+
type ThemePath<Setting extends string> = Setting extends `viewer.${infer Rest}` ? Rest : Setting extends `${infer Head}[]${infer Tail}` ? `${Head}${Tail}` : Setting;
|
|
1543
|
+
/** What a part takes: one of its keywords, or a CSS value. */
|
|
1544
|
+
type ThemeValue<Name extends EpdfSettingVariable> = Definitions[Name] extends {
|
|
1545
|
+
readonly keywords: infer Keywords;
|
|
1546
|
+
} ? keyof Keywords & string : string | number;
|
|
1547
|
+
/** One setting as a nested object: `'page.shadow'` is `{ page?: { shadow?: … } }`. */
|
|
1548
|
+
type ThemeBranch<Path extends string, Value> = Path extends `${infer Head}.${infer Rest}` ? { readonly [Key in Head]?: ThemeBranch<Rest, Value>; } : { readonly [Key in Path]?: Value; };
|
|
1549
|
+
type Intersection<Union> = (Union extends unknown ? (value: Union) => void : never) extends ((value: infer Both) => void) ? Both : never;
|
|
1550
|
+
/**
|
|
1551
|
+
* A theme by setting names, every part optional: `{ accent: '#e91e63', search: { highlight:
|
|
1552
|
+
* { color: '#7dd3fc' } } }`. The viewer's own settings sit at the top; each plugin's under its
|
|
1553
|
+
* name, as the theming page lists them.
|
|
1554
|
+
*/
|
|
1555
|
+
type EpdfTheme = Intersection<{ [Name in EpdfSettingVariable]: ThemeBranch<ThemePath<Definitions[Name]['setting']>, ThemeValue<Name>>; }[EpdfSettingVariable]>;
|
|
1556
|
+
/** The CSS variables of a theme, by their full name: `{ '--epdf-accent': '#e91e63' }`. */
|
|
1557
|
+
type EpdfThemeVariables = Readonly<Record<`--epdf-${EpdfVariable}`, string>>;
|
|
1558
|
+
/**
|
|
1559
|
+
* The CSS variables that set a theme, for a style on an element around the viewer: CSS variables
|
|
1560
|
+
* win over settings, and reach everything inside the element. A part left out keeps its own
|
|
1561
|
+
* look, so the parts that follow the accent follow a new `accent`.
|
|
1562
|
+
*
|
|
1563
|
+
* `epdfThemeVariables({ accent: '#e91e63', page: { shadow: 'none' } })` is
|
|
1564
|
+
* `{ '--epdf-accent': '#e91e63', '--epdf-page-shadow': 'none' }`.
|
|
1565
|
+
*/
|
|
1566
|
+
declare function epdfThemeVariables(theme: EpdfTheme): Partial<EpdfThemeVariables>;
|
|
1567
|
+
//#endregion
|
|
1568
|
+
//#region src/page-pixels.d.ts
|
|
1569
|
+
/**
|
|
1570
|
+
* Page-space shapes in a page layer's pixels. Every layer over a page (the
|
|
1571
|
+
* annotation, form, link, selection and search layers) gets boxes and quads
|
|
1572
|
+
* in page points and places its elements in the page layer's own pixels,
|
|
1573
|
+
* always through the page's `toPixels`: never by multiplying with a scale of
|
|
1574
|
+
* its own. Plain geometry over structural shapes, the same for every
|
|
1575
|
+
* framework adapter.
|
|
1576
|
+
*/
|
|
1577
|
+
/** A point in page points or in pixels. */
|
|
1578
|
+
interface PagePoint {
|
|
1579
|
+
x: number;
|
|
1580
|
+
y: number;
|
|
1581
|
+
}
|
|
1582
|
+
/** What a page layer converts with: its transform's `toPixels`. */
|
|
1583
|
+
interface PageToPixels {
|
|
1584
|
+
toPixels(point: PagePoint): PagePoint;
|
|
1585
|
+
}
|
|
1586
|
+
/** A box in a page layer's pixels, the shape a positioned element takes. */
|
|
1587
|
+
interface PixelRect {
|
|
1588
|
+
left: number;
|
|
1589
|
+
top: number;
|
|
1590
|
+
width: number;
|
|
1591
|
+
height: number;
|
|
1592
|
+
}
|
|
1593
|
+
/** A quad's four corners, as the engine names them. */
|
|
1594
|
+
interface PageQuad {
|
|
1595
|
+
upperLeft: PagePoint;
|
|
1596
|
+
upperRight: PagePoint;
|
|
1597
|
+
lowerRight: PagePoint;
|
|
1598
|
+
lowerLeft: PagePoint;
|
|
1599
|
+
}
|
|
1600
|
+
/** A box in page points as a box in the page layer's pixels. */
|
|
1601
|
+
declare function rectInPixels(rect: {
|
|
1602
|
+
x: number;
|
|
1603
|
+
y: number;
|
|
1604
|
+
width: number;
|
|
1605
|
+
height: number;
|
|
1606
|
+
}, page: PageToPixels): PixelRect;
|
|
1607
|
+
/**
|
|
1608
|
+
* A quad's corners in the page layer's pixels, in drawing order (upper left,
|
|
1609
|
+
* upper right, lower right, lower left). The map is affine, so mapping the
|
|
1610
|
+
* corners is exact, for turned text too.
|
|
1611
|
+
*/
|
|
1612
|
+
declare function quadInPixels(quad: PageQuad, page: PageToPixels): PagePoint[];
|
|
1613
|
+
/** Points as an SVG `points` attribute: `"x,y x,y …"`. */
|
|
1614
|
+
declare function svgPoints(points: readonly PagePoint[]): string;
|
|
1615
|
+
/** Whether a quad is an upright box: drawn as a positioned box instead of a polygon. */
|
|
1616
|
+
declare function isUprightQuad(quad: PageQuad): boolean;
|
|
1617
|
+
//#endregion
|
|
1618
|
+
//#region src/event-isolation.d.ts
|
|
1619
|
+
/**
|
|
1620
|
+
* Keeping a page's own listeners out of controls drawn over it. The Stage
|
|
1621
|
+
* listens natively on an ancestor of every page: a press that bubbles to it
|
|
1622
|
+
* starts a tool gesture or reads as a click outside (ending an edit), and a
|
|
1623
|
+
* wheel pans or zooms the page. A control that owns its gestures stops them
|
|
1624
|
+
* with a native listener on itself, which runs during real DOM bubbling,
|
|
1625
|
+
* before the Stage's. A framework's own event system may run too late: React
|
|
1626
|
+
* dispatches from its root, above the Stage.
|
|
1627
|
+
*/
|
|
1628
|
+
/**
|
|
1629
|
+
* Stop presses that begin inside `element` from reaching the page, and tell `onPress` about each
|
|
1630
|
+
* one. A control that needs the press itself (a link or a form field sending its PDF "mouse down"
|
|
1631
|
+
* action) must take it here: once the press stops at the element, a framework that dispatches
|
|
1632
|
+
* from its root (React) never sees it. Returns the detach.
|
|
1633
|
+
*/
|
|
1634
|
+
declare function isolatePointerDown(element: HTMLElement, onPress?: (event: PointerEvent) => void): () => void;
|
|
1635
|
+
/**
|
|
1636
|
+
* Stop wheel events inside `element` from reaching the page, so the browser
|
|
1637
|
+
* scrolls the element itself (a list box) instead of the Stage panning or
|
|
1638
|
+
* zooming. Returns the detach.
|
|
1639
|
+
*/
|
|
1640
|
+
declare function isolateWheel(element: HTMLElement): () => void;
|
|
1641
|
+
//#endregion
|
|
1642
|
+
//#region src/outside-press.d.ts
|
|
1643
|
+
/**
|
|
1644
|
+
* Call `onPress` when a pointer press starts anywhere in `element`'s document
|
|
1645
|
+
* outside `element`: how a menu closes when the user presses somewhere else,
|
|
1646
|
+
* in the viewer or on the page around it. Where the press landed is read from
|
|
1647
|
+
* its composed path: at the document, an event from inside a shadow root is
|
|
1648
|
+
* retargeted to the shadow host, so `element.contains(event.target)` would
|
|
1649
|
+
* call every press inside a shadow-rooted menu an outside one. Listens in the
|
|
1650
|
+
* capture phase, so a handler that stops the press can't keep a menu open.
|
|
1651
|
+
* Returns the stop.
|
|
1652
|
+
*/
|
|
1653
|
+
declare function observeOutsidePress(element: Element, onPress: (event: PointerEvent) => void): () => void;
|
|
1654
|
+
//#endregion
|
|
1655
|
+
//#region src/anchor-equality.d.ts
|
|
1656
|
+
/**
|
|
1657
|
+
* Equality for the anchors plugins hand out. An anchor read (where a menu, a
|
|
1658
|
+
* badge or a selection handle attaches) returns a new object every time; a
|
|
1659
|
+
* framework adapter compares reads with these, so the UI attached to an
|
|
1660
|
+
* anchor renders again only when the anchor moved. The anchors are mirrored
|
|
1661
|
+
* structurally, so this package stays free of EmbedPDF imports.
|
|
1662
|
+
*/
|
|
1663
|
+
interface AnchorPoint {
|
|
1664
|
+
readonly x: number;
|
|
1665
|
+
readonly y: number;
|
|
1666
|
+
}
|
|
1667
|
+
interface AnchorBox {
|
|
1668
|
+
readonly x: number;
|
|
1669
|
+
readonly y: number;
|
|
1670
|
+
readonly width: number;
|
|
1671
|
+
readonly height: number;
|
|
1672
|
+
}
|
|
1673
|
+
interface AnchorPage {
|
|
1674
|
+
readonly objectNumber: number;
|
|
1675
|
+
}
|
|
1676
|
+
/** A box on a page: a text selection's anchor, and the core of every other one. */
|
|
1677
|
+
interface PageBoundsAnchor {
|
|
1678
|
+
readonly page: AnchorPage;
|
|
1679
|
+
readonly bounds: AnchorBox;
|
|
1680
|
+
}
|
|
1681
|
+
/** The same page and box (a text selection's menu anchor). */
|
|
1682
|
+
declare function samePageBounds(left: PageBoundsAnchor | null, right: PageBoundsAnchor | null): boolean;
|
|
1683
|
+
/** The annotation selection's anchor: its page, its box, and its rotation handle when it has one. */
|
|
1684
|
+
interface SelectionAnchorShape extends PageBoundsAnchor {
|
|
1685
|
+
readonly rotationHandle?: AnchorPoint | null;
|
|
1686
|
+
}
|
|
1687
|
+
/** The same annotation selection anchor: page, box and rotation handle. */
|
|
1688
|
+
declare function sameSelectionAnchor(left: SelectionAnchorShape | null, right: SelectionAnchorShape | null): boolean;
|
|
1689
|
+
/** One annotation's anchor: page, box, and the view-dependent box of one that keeps its size on screen. */
|
|
1690
|
+
interface AnnotationAnchorShape extends PageBoundsAnchor {
|
|
1691
|
+
readonly boundsIn?: unknown;
|
|
1692
|
+
}
|
|
1693
|
+
/** The same annotation anchor: page, box, and how it follows the view. */
|
|
1694
|
+
declare function sameAnnotationAnchor(left: AnnotationAnchorShape | null, right: AnnotationAnchorShape | null): boolean;
|
|
1695
|
+
/** A shape being drawn click by click (a polygon): where it is and how far it got. */
|
|
1696
|
+
interface CreationDraftAnchorShape extends PageBoundsAnchor {
|
|
1697
|
+
readonly kind: string;
|
|
1698
|
+
readonly subtype: string;
|
|
1699
|
+
readonly pointCount: number;
|
|
1700
|
+
readonly minPoints: number;
|
|
1701
|
+
readonly canFinish: boolean;
|
|
1702
|
+
}
|
|
1703
|
+
/** The same creation draft: what it draws, its points so far, whether it can finish, and its box. */
|
|
1704
|
+
declare function sameCreationDraftAnchor(left: CreationDraftAnchorShape | null, right: CreationDraftAnchorShape | null): boolean;
|
|
1705
|
+
/** A turn in progress: the pointer's page point and the angle. */
|
|
1706
|
+
interface RotationAnchorShape {
|
|
1707
|
+
readonly page: AnchorPage;
|
|
1708
|
+
readonly at: AnchorPoint;
|
|
1709
|
+
readonly angle: number;
|
|
1710
|
+
}
|
|
1711
|
+
/** The same turn in progress: page, pointer and angle. */
|
|
1712
|
+
declare function sameRotationAnchor(left: RotationAnchorShape | null, right: RotationAnchorShape | null): boolean;
|
|
1713
|
+
interface AnchorQuad {
|
|
1714
|
+
readonly upperLeft: AnchorPoint;
|
|
1715
|
+
readonly upperRight: AnchorPoint;
|
|
1716
|
+
readonly lowerLeft: AnchorPoint;
|
|
1717
|
+
readonly lowerRight: AnchorPoint;
|
|
1718
|
+
}
|
|
1719
|
+
/** One end of a text selection: its page, the boundary glyph's quad, and the side of the glyph. */
|
|
1720
|
+
interface SelectionEndpointShape {
|
|
1721
|
+
readonly page: AnchorPage;
|
|
1722
|
+
readonly glyphQuad: AnchorQuad;
|
|
1723
|
+
readonly advance: unknown;
|
|
1724
|
+
}
|
|
1725
|
+
/** Both ends of a text selection, where its handles sit. */
|
|
1726
|
+
interface SelectionEndpointsShape {
|
|
1727
|
+
readonly start: SelectionEndpointShape;
|
|
1728
|
+
readonly end: SelectionEndpointShape;
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* The same selection ends. The glyph quads compare corner by corner, so an
|
|
1732
|
+
* end that turns without moving its bounding box still counts as moved.
|
|
1733
|
+
*/
|
|
1734
|
+
declare function sameSelectionEndpoints(left: SelectionEndpointsShape | null, right: SelectionEndpointsShape | null): boolean;
|
|
1735
|
+
//#endregion
|
|
1736
|
+
//#region src/annotation-scene.d.ts
|
|
1737
|
+
/** How a scene node paints: the structural twin of core-annotation's `Paint`. */
|
|
1738
|
+
interface ScenePaint {
|
|
1739
|
+
fill?: string;
|
|
1740
|
+
stroke?: string;
|
|
1741
|
+
/** Stroke width, in page points. */
|
|
1742
|
+
width?: number;
|
|
1743
|
+
opacity?: number;
|
|
1744
|
+
/** Stroke dash, in page points. */
|
|
1745
|
+
dash?: number[];
|
|
1746
|
+
blend?: string;
|
|
1747
|
+
lineCap?: 'round';
|
|
1748
|
+
join?: 'round';
|
|
1749
|
+
fillRule?: 'evenodd';
|
|
1750
|
+
}
|
|
1751
|
+
interface SceneBox {
|
|
1752
|
+
x: number;
|
|
1753
|
+
y: number;
|
|
1754
|
+
width: number;
|
|
1755
|
+
height: number;
|
|
1756
|
+
}
|
|
1757
|
+
interface ScenePoint {
|
|
1758
|
+
x: number;
|
|
1759
|
+
y: number;
|
|
1760
|
+
}
|
|
1761
|
+
/** One painted node: the structural twin of core-annotation's `SceneNode`. */
|
|
1762
|
+
type SceneShapeNode = ({
|
|
1763
|
+
kind: 'rect';
|
|
1764
|
+
rect: SceneBox;
|
|
1765
|
+
paint: ScenePaint;
|
|
1766
|
+
} | {
|
|
1767
|
+
kind: 'ellipse';
|
|
1768
|
+
rect: SceneBox;
|
|
1769
|
+
paint: ScenePaint;
|
|
1770
|
+
} | {
|
|
1771
|
+
kind: 'line';
|
|
1772
|
+
a: ScenePoint;
|
|
1773
|
+
b: ScenePoint;
|
|
1774
|
+
paint: ScenePaint;
|
|
1775
|
+
} | {
|
|
1776
|
+
kind: 'poly';
|
|
1777
|
+
points: ScenePoint[];
|
|
1778
|
+
closed: boolean;
|
|
1779
|
+
paint: ScenePaint;
|
|
1780
|
+
} | {
|
|
1781
|
+
kind: 'path';
|
|
1782
|
+
d: string;
|
|
1783
|
+
paint: ScenePaint;
|
|
1784
|
+
} | {
|
|
1785
|
+
kind: 'text';
|
|
1786
|
+
at: ScenePoint;
|
|
1787
|
+
text: string;
|
|
1788
|
+
fontSize: number;
|
|
1789
|
+
fontFamily?: string;
|
|
1790
|
+
rotation?: number;
|
|
1791
|
+
paint: ScenePaint;
|
|
1792
|
+
} | {
|
|
1793
|
+
kind: 'glyphs';
|
|
1794
|
+
at: ScenePoint;
|
|
1795
|
+
text: string;
|
|
1796
|
+
offsets: number[];
|
|
1797
|
+
fontSize: number;
|
|
1798
|
+
fontFamily: string;
|
|
1799
|
+
fontWeight?: number;
|
|
1800
|
+
fontStyle?: 'normal' | 'italic';
|
|
1801
|
+
rotation?: number;
|
|
1802
|
+
/** The face it draws in: whatever draws it mounts it. */
|
|
1803
|
+
program?: MountableFontProgram;
|
|
1804
|
+
paint: ScenePaint;
|
|
1805
|
+
}) & {
|
|
1806
|
+
/** Drawn only inside this upright box. */
|
|
1807
|
+
clip?: SceneBox;
|
|
1808
|
+
};
|
|
1809
|
+
/** The SVG elements a scene draws with; a nested `svg` clips what's inside it to its box. */
|
|
1810
|
+
type SvgShapeTag = 'rect' | 'ellipse' | 'line' | 'path' | 'text' | 'polygon' | 'polyline' | 'svg';
|
|
1811
|
+
/**
|
|
1812
|
+
* One SVG element: its tag, its attributes under their SVG names
|
|
1813
|
+
* (`stroke-width`, `fill-rule`; an attribute left out is not set), the text
|
|
1814
|
+
* inside it, and its blend mode, which is CSS (`mix-blend-mode` in its
|
|
1815
|
+
* `style`), never an attribute.
|
|
1816
|
+
*/
|
|
1817
|
+
interface SvgShape {
|
|
1818
|
+
tag: SvgShapeTag;
|
|
1819
|
+
attributes: Readonly<Record<string, string | number>>;
|
|
1820
|
+
text?: string;
|
|
1821
|
+
blend?: string;
|
|
1822
|
+
/** What a clipping `svg` holds, in drawing order. */
|
|
1823
|
+
children?: SvgShape[];
|
|
1824
|
+
/** The face a `text` draws in: the renderer mounts it (`fontProgramsOf`). */
|
|
1825
|
+
program?: MountableFontProgram;
|
|
1826
|
+
}
|
|
1827
|
+
/** The faces shapes draw their text in, each once: a renderer mounts them while it shows the shapes. */
|
|
1828
|
+
declare function fontProgramsOf(shapes: readonly SvgShape[]): MountableFontProgram[];
|
|
1829
|
+
interface SvgShapesOptions {
|
|
1830
|
+
/**
|
|
1831
|
+
* The stroke miter limit, core-annotation's `MITER_LIMIT`: it must be the
|
|
1832
|
+
* one the core's bounds math uses, so a sharp corner spikes or bevels the
|
|
1833
|
+
* same way in both.
|
|
1834
|
+
*/
|
|
1835
|
+
miterLimit: number;
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Each scene node as one SVG element, in drawing order, in the scene's own
|
|
1839
|
+
* page-point units. A clipped node comes inside an `svg` of its clip box,
|
|
1840
|
+
* which shows only what's inside it (no ids, so every framework draws it the
|
|
1841
|
+
* same).
|
|
1842
|
+
*/
|
|
1843
|
+
declare function svgShapesOf(nodes: readonly SceneShapeNode[], options: SvgShapesOptions): SvgShape[];
|
|
1844
|
+
/**
|
|
1845
|
+
* The `viewBox` an item's scene draws in: its box, in page points. `null`
|
|
1846
|
+
* while the box has no area (a drawing at its first press): draw nothing then.
|
|
1847
|
+
*
|
|
1848
|
+
* The `<svg>` fills the item's frame, so the viewBox and the element's size
|
|
1849
|
+
* stay proportional (their ratio is the zoom). Never clamp either one: a
|
|
1850
|
+
* clamped element with a shrinking viewBox scales its content up, and a
|
|
1851
|
+
* cloudy border's scallops flood the page.
|
|
1852
|
+
*/
|
|
1853
|
+
declare function sceneViewBox(box: SceneBox): string | null;
|
|
1854
|
+
/** How opaque a tool's ghost paints: `--epdf-ghost-opacity` wins over the tool's own. */
|
|
1855
|
+
declare function ghostOpacity(opacity: number): string;
|
|
1856
|
+
//#endregion
|
|
1857
|
+
//#region src/annotation-chrome.d.ts
|
|
1858
|
+
/** The chrome settings the paint reads: the structural twin of the annotation plugin's `ChromeSettings`. */
|
|
1859
|
+
interface ChromePaintSettings {
|
|
1860
|
+
readonly accent: string | null;
|
|
1861
|
+
readonly outline: {
|
|
1862
|
+
readonly color: string | null;
|
|
1863
|
+
readonly style: string;
|
|
1864
|
+
readonly width: number;
|
|
1865
|
+
};
|
|
1866
|
+
readonly handles: {
|
|
1867
|
+
readonly fill: string;
|
|
1868
|
+
readonly stroke: string | null;
|
|
1869
|
+
};
|
|
1870
|
+
readonly rotationHandle: {
|
|
1871
|
+
readonly fill: string | null;
|
|
1872
|
+
readonly stroke: string | null;
|
|
1873
|
+
};
|
|
1874
|
+
readonly guides: {
|
|
1875
|
+
readonly color: string;
|
|
1876
|
+
readonly rotationColor: string | null;
|
|
1877
|
+
readonly style: string;
|
|
1878
|
+
readonly width: number;
|
|
1879
|
+
};
|
|
1880
|
+
readonly marquee: {
|
|
1881
|
+
readonly fill: string | null;
|
|
1882
|
+
readonly stroke: string | null;
|
|
1883
|
+
};
|
|
1884
|
+
readonly textOutline: string | null;
|
|
1885
|
+
}
|
|
1886
|
+
/** A line's paint as CSS: its color, width and dash. */
|
|
1887
|
+
interface ChromeLinePaint {
|
|
1888
|
+
readonly stroke: string;
|
|
1889
|
+
readonly strokeWidth: string;
|
|
1890
|
+
readonly strokeDasharray: string;
|
|
1891
|
+
}
|
|
1892
|
+
/** A shape's paint as CSS: its fill and its stroke color. */
|
|
1893
|
+
interface ChromeShapePaint {
|
|
1894
|
+
readonly fill: string;
|
|
1895
|
+
readonly stroke: string;
|
|
1896
|
+
}
|
|
1897
|
+
/**
|
|
1898
|
+
* Every chrome color, width and dash as CSS, each its `--epdf-annotation-*`
|
|
1899
|
+
* variable first, then the setting. Put them in `style`: an SVG attribute
|
|
1900
|
+
* doesn't read `var()`.
|
|
1901
|
+
*/
|
|
1902
|
+
interface AnnotationChromePaint {
|
|
1903
|
+
/** The selection box. */
|
|
1904
|
+
readonly outline: ChromeLinePaint;
|
|
1905
|
+
/** The resize and point handles. */
|
|
1906
|
+
readonly handle: ChromeShapePaint;
|
|
1907
|
+
/** The rotation handle; its stalk takes the `stroke`. */
|
|
1908
|
+
readonly rotationHandle: ChromeShapePaint;
|
|
1909
|
+
/** A snapped move's alignment guide. */
|
|
1910
|
+
readonly guide: ChromeLinePaint;
|
|
1911
|
+
/** The reference cross and the angle line while turning. */
|
|
1912
|
+
readonly rotationGuide: ChromeLinePaint;
|
|
1913
|
+
/** The box dragged to select. */
|
|
1914
|
+
readonly marquee: ChromeShapePaint;
|
|
1915
|
+
/** The outline color of a text box while someone types in it. */
|
|
1916
|
+
readonly textOutline: string;
|
|
1917
|
+
}
|
|
1918
|
+
/**
|
|
1919
|
+
* The chrome settings as paint. A color left `null` follows the part it
|
|
1920
|
+
* names, and in the end the accent: the chrome's own, else the viewer's.
|
|
1921
|
+
*/
|
|
1922
|
+
declare function annotationChromePaint(chrome: ChromePaintSettings, viewerAccent: string): AnnotationChromePaint;
|
|
1923
|
+
/**
|
|
1924
|
+
* One chrome node as the annotation plugin lists it: the structural twin of
|
|
1925
|
+
* core-annotation's `ChromeNode`. `Role` is what a handle reshapes.
|
|
1926
|
+
*/
|
|
1927
|
+
type ChromeNodeShape<Role extends string = string> = {
|
|
1928
|
+
kind: 'outline';
|
|
1929
|
+
rect: {
|
|
1930
|
+
x: number;
|
|
1931
|
+
y: number;
|
|
1932
|
+
width: number;
|
|
1933
|
+
height: number;
|
|
1934
|
+
};
|
|
1935
|
+
} | {
|
|
1936
|
+
kind: 'obb';
|
|
1937
|
+
corners: readonly PagePoint[];
|
|
1938
|
+
} | {
|
|
1939
|
+
kind: 'handle';
|
|
1940
|
+
at: PagePoint;
|
|
1941
|
+
rot?: number;
|
|
1942
|
+
role: Role;
|
|
1943
|
+
active: boolean;
|
|
1944
|
+
} | {
|
|
1945
|
+
kind: 'rotate-knob';
|
|
1946
|
+
at: PagePoint;
|
|
1947
|
+
from: PagePoint;
|
|
1948
|
+
} | {
|
|
1949
|
+
kind: 'guide';
|
|
1950
|
+
axis: 'x' | 'y';
|
|
1951
|
+
at: number;
|
|
1952
|
+
lo: number;
|
|
1953
|
+
hi: number;
|
|
1954
|
+
} | {
|
|
1955
|
+
kind: 'rotate-guides';
|
|
1956
|
+
lines: ReadonlyArray<{
|
|
1957
|
+
a: PagePoint;
|
|
1958
|
+
b: PagePoint;
|
|
1959
|
+
role: 'axis' | 'indicator';
|
|
1960
|
+
}>;
|
|
1961
|
+
} | {
|
|
1962
|
+
kind: 'marquee';
|
|
1963
|
+
rect: {
|
|
1964
|
+
x: number;
|
|
1965
|
+
y: number;
|
|
1966
|
+
width: number;
|
|
1967
|
+
height: number;
|
|
1968
|
+
};
|
|
1969
|
+
};
|
|
1970
|
+
/** A line in pixels. */
|
|
1971
|
+
interface ChromeLine {
|
|
1972
|
+
from: PagePoint;
|
|
1973
|
+
to: PagePoint;
|
|
1974
|
+
}
|
|
1975
|
+
/**
|
|
1976
|
+
* A chrome node in the page layer's pixels. What each one draws:
|
|
1977
|
+
* - `outline`, `marquee`: a rectangle, `box` (the marquee is always dashed `4 3`);
|
|
1978
|
+
* - `turned-outline`: a closed polygon through `points`, the outline of a turned selection;
|
|
1979
|
+
* - `handle`: a handle centred on `at`, turned by `rotation` (degrees clockwise) when square;
|
|
1980
|
+
* - `rotation-handle`: a round handle at `at`, its stalk from `from` on the box;
|
|
1981
|
+
* - `guide`: a crisp line, a snapped move's alignment;
|
|
1982
|
+
* - `rotation-guides`: the lines of a turn in progress, each at its `opacity`.
|
|
1983
|
+
*/
|
|
1984
|
+
type ChromeInPixels<Role extends string = string> = {
|
|
1985
|
+
kind: 'outline';
|
|
1986
|
+
box: PixelRect;
|
|
1987
|
+
} | {
|
|
1988
|
+
kind: 'marquee';
|
|
1989
|
+
box: PixelRect;
|
|
1990
|
+
} | {
|
|
1991
|
+
kind: 'turned-outline';
|
|
1992
|
+
points: string;
|
|
1993
|
+
} | {
|
|
1994
|
+
kind: 'handle';
|
|
1995
|
+
at: PagePoint;
|
|
1996
|
+
rotation: number;
|
|
1997
|
+
role: Role;
|
|
1998
|
+
active: boolean;
|
|
1999
|
+
} | {
|
|
2000
|
+
kind: 'rotation-handle';
|
|
2001
|
+
at: PagePoint;
|
|
2002
|
+
from: PagePoint;
|
|
2003
|
+
} | ({
|
|
2004
|
+
kind: 'guide';
|
|
2005
|
+
} & ChromeLine) | {
|
|
2006
|
+
kind: 'rotation-guides';
|
|
2007
|
+
lines: Array<ChromeLine & {
|
|
2008
|
+
opacity: number;
|
|
2009
|
+
}>;
|
|
2010
|
+
};
|
|
2011
|
+
/**
|
|
2012
|
+
* Each chrome node in the page layer's pixels, in drawing order. The plugin
|
|
2013
|
+
* already sized the screen-constant parts (handle grab zones, the rotation
|
|
2014
|
+
* handle's offset) for the page's zoom; this only places them.
|
|
2015
|
+
*/
|
|
2016
|
+
declare function chromeInPixels<Role extends string>(nodes: readonly ChromeNodeShape<Role>[], page: PageToPixels): ChromeInPixels<Role>[];
|
|
2017
|
+
//#endregion
|
|
2018
|
+
//#region src/text-box-editor.d.ts
|
|
2019
|
+
/** A text box as the annotation plugin lists it (`listTextItems`): the fields the editor reads. */
|
|
2020
|
+
interface TextBoxEditorItem<Ref> {
|
|
2021
|
+
readonly id: string;
|
|
2022
|
+
/** `null` for a box that isn't written yet: nothing to route typing to. */
|
|
2023
|
+
readonly ref: Ref | null;
|
|
2024
|
+
readonly richText: RichTextEditorDocument;
|
|
2025
|
+
/** True while someone types in this box. */
|
|
2026
|
+
readonly editing: boolean;
|
|
2027
|
+
}
|
|
2028
|
+
/** The annotation plugin's text-editing calls (its host capability satisfies it). */
|
|
2029
|
+
interface TextBoxEditorAnnotation<Ref> {
|
|
2030
|
+
draftRichText(ref: Ref, document: RichTextEditorDocument): void;
|
|
2031
|
+
setTextSelection(ref: Ref, range: RichTextEditorRange | null): void;
|
|
2032
|
+
readonly text: {
|
|
2033
|
+
toggleFormat(format: RichTextEditorCommand): unknown;
|
|
2034
|
+
};
|
|
2035
|
+
getCssFontFamily(family: string): string;
|
|
2036
|
+
getEditingId(): string | null;
|
|
2037
|
+
}
|
|
2038
|
+
/** An element made a text box's editor. */
|
|
2039
|
+
interface TextBoxEditor<Ref> {
|
|
2040
|
+
/**
|
|
2041
|
+
* The box as the plugin has it now, at `scale` pixels per point (or `null`
|
|
2042
|
+
* while there is none). Call it whenever either changes: the binding
|
|
2043
|
+
* redraws only when the text differs (so the caret never jumps while
|
|
2044
|
+
* typing), and focus follows `editing`.
|
|
2045
|
+
*/
|
|
2046
|
+
update(item: TextBoxEditorItem<Ref> | null, scale: number): void;
|
|
2047
|
+
/** Remove the listeners and the rich-text binding. */
|
|
2048
|
+
detach(): void;
|
|
2049
|
+
}
|
|
2050
|
+
/**
|
|
2051
|
+
* Make `element` the editor of a text box. Typing shows at once and reaches
|
|
2052
|
+
* the engine in one write after a pause (or when the edit ends), not one
|
|
2053
|
+
* write per keystroke.
|
|
2054
|
+
*/
|
|
2055
|
+
declare function attachTextBoxEditor<Ref>(element: HTMLElement, annotation: TextBoxEditorAnnotation<Ref>): TextBoxEditor<Ref>;
|
|
2056
|
+
/** Keeps an element the editor of a text box while what it edits with changes. */
|
|
2057
|
+
interface TextBoxEditorFollower<Ref> {
|
|
2058
|
+
/**
|
|
2059
|
+
* The element, the plugin, the box and the scale as they are now. Call it
|
|
2060
|
+
* whenever any of them changes: the editor attaches when there are an
|
|
2061
|
+
* element and a plugin, attaches again when either is another one (a
|
|
2062
|
+
* document that opens anew), and gets the box and the scale every time.
|
|
2063
|
+
*/
|
|
2064
|
+
follow(element: HTMLElement | null, annotation: TextBoxEditorAnnotation<Ref> | null, item: TextBoxEditorItem<Ref> | null, scale: number): void;
|
|
2065
|
+
/** Let go of the element, when the component that drew it goes away. */
|
|
2066
|
+
detach(): void;
|
|
2067
|
+
}
|
|
2068
|
+
/**
|
|
2069
|
+
* A text box editor that follows its inputs: what each framework's binding
|
|
2070
|
+
* holds between renders. The update runs right after an attach, in the same
|
|
2071
|
+
* call, so the element never shows an editor without its text.
|
|
2072
|
+
*/
|
|
2073
|
+
declare function createTextBoxEditorFollower<Ref>(): TextBoxEditorFollower<Ref>;
|
|
2074
|
+
/**
|
|
2075
|
+
* Pixels per point for an editor element you draw yourself (a renderer's own
|
|
2076
|
+
* text box): the box's width on the page over its width in points, or the
|
|
2077
|
+
* page's view scale while there is no box. Inside a look the layer scales
|
|
2078
|
+
* (`lookScale`, 1 outside one), the element draws at the annotation's 100%
|
|
2079
|
+
* size and the look's scale does the rest.
|
|
2080
|
+
*/
|
|
2081
|
+
declare function textBoxEditorScaleOf(item: {
|
|
2082
|
+
box: {
|
|
2083
|
+
x: number;
|
|
2084
|
+
y: number;
|
|
2085
|
+
width: number;
|
|
2086
|
+
height: number;
|
|
2087
|
+
};
|
|
2088
|
+
} | null, page: PageToPixels & {
|
|
2089
|
+
viewScale: number;
|
|
2090
|
+
}, lookScale: number): number;
|
|
2091
|
+
/** A free text body's look, as the plugin hands it (`TextItem.css`). */
|
|
2092
|
+
interface TextBoxCss {
|
|
2093
|
+
fontFamily: string;
|
|
2094
|
+
/** In page points. */
|
|
2095
|
+
fontSize: number;
|
|
2096
|
+
color: string;
|
|
2097
|
+
fontWeight: number;
|
|
2098
|
+
fontStyle: string;
|
|
2099
|
+
textDecoration: string;
|
|
2100
|
+
align: 'left' | 'center' | 'right';
|
|
2101
|
+
/** The plate's inset from the box, in page points. */
|
|
2102
|
+
padding: number;
|
|
2103
|
+
}
|
|
2104
|
+
/** A text box's body style as CSS: put it on the editor element. */
|
|
2105
|
+
interface TextBoxStyle {
|
|
2106
|
+
fontFamily: string;
|
|
2107
|
+
/** In pixels, with its unit. */
|
|
2108
|
+
fontSize: string;
|
|
2109
|
+
color: string;
|
|
2110
|
+
fontWeight: number;
|
|
2111
|
+
fontStyle: string;
|
|
2112
|
+
textDecoration: string;
|
|
2113
|
+
textAlign: 'left' | 'center' | 'right';
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* A text box's body style at `scale` pixels per point: font, size, color and
|
|
2117
|
+
* alignment. No line height: the editor binding states the engine's line
|
|
2118
|
+
* model per face on the element itself.
|
|
2119
|
+
*/
|
|
2120
|
+
declare function textBoxStyleOf(css: TextBoxCss, scale: number): TextBoxStyle;
|
|
2121
|
+
/** Where a free text's editor element goes, and the scale it draws at. */
|
|
2122
|
+
interface TextPlatePixels {
|
|
2123
|
+
left: number;
|
|
2124
|
+
top: number;
|
|
2125
|
+
width: number;
|
|
2126
|
+
height: number;
|
|
2127
|
+
/** Pixels per page point. */
|
|
2128
|
+
scale: number;
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* The editor element of a free text box in the page layer's pixels: the
|
|
2132
|
+
* engine's text plate (`SetPlateRect` and its `re W n` clip), the box inset
|
|
2133
|
+
* by its padding. Place it there with no CSS padding, so its edge is the
|
|
2134
|
+
* plate's: CSS padding doesn't clip overflow, and scrolled lines would paint
|
|
2135
|
+
* over the border band. The box never grows with its text.
|
|
2136
|
+
*/
|
|
2137
|
+
declare function textPlateInPixels(item: {
|
|
2138
|
+
box: {
|
|
2139
|
+
x: number;
|
|
2140
|
+
y: number;
|
|
2141
|
+
width: number;
|
|
2142
|
+
height: number;
|
|
2143
|
+
};
|
|
2144
|
+
css: {
|
|
2145
|
+
padding: number;
|
|
2146
|
+
};
|
|
2147
|
+
}, page: PageToPixels): TextPlatePixels;
|
|
2148
|
+
//#endregion
|
|
2149
|
+
//#region src/annotation-renderers.d.ts
|
|
2150
|
+
/**
|
|
2151
|
+
* The annotation layer's renderers: which drawing each annotation gets, and
|
|
2152
|
+
* the behaviors that `interactive` renderers register. A renderer is a rule
|
|
2153
|
+
* ("draw these annotations with this component"); a framework adapter keeps
|
|
2154
|
+
* the component, and these decide everything around it, the same for every
|
|
2155
|
+
* framework:
|
|
2156
|
+
*
|
|
2157
|
+
* - {@link registerRendererBehaviors}: an `interactive` renderer takes the
|
|
2158
|
+
* pointer through a behavior the annotation plugin knows, registered once
|
|
2159
|
+
* per capability and renderer entry however many pages mount the layer.
|
|
2160
|
+
* - {@link annotationDrawingOf}: per annotation, the layer's own drawing, a
|
|
2161
|
+
* look of yours, or a sibling plugin's control (ownership beats looks).
|
|
2162
|
+
* - {@link editingTextKeyOf} and {@link layerTextBoxesOf}: which text box is
|
|
2163
|
+
* typed in, and which text boxes the layer draws rather than a look.
|
|
2164
|
+
*
|
|
2165
|
+
* The plugin's types are mirrored structurally, so this package stays free of
|
|
2166
|
+
* EmbedPDF imports.
|
|
2167
|
+
*/
|
|
2168
|
+
/** A sibling plugin's renderer: it draws what the behavior `behavior` owns (the form plugin's controls). */
|
|
2169
|
+
interface BehaviorRendererEntry {
|
|
2170
|
+
behavior: string;
|
|
2171
|
+
}
|
|
2172
|
+
/** What an `interactive` function is asked: the annotation, and the active tool. */
|
|
2173
|
+
interface RendererInteractiveContext<Annotation> {
|
|
2174
|
+
annotation: Annotation;
|
|
2175
|
+
toolId: string;
|
|
2176
|
+
}
|
|
2177
|
+
/** A look of yours: draws the annotations `for` matches. */
|
|
2178
|
+
interface LookRendererEntry<Annotation> {
|
|
2179
|
+
/** A stable id for the registration (optional; generated). */
|
|
2180
|
+
id?: string;
|
|
2181
|
+
for(annotation: Annotation): boolean;
|
|
2182
|
+
/** Takes the pointer: always, or when the function says so (asked whenever it matters). */
|
|
2183
|
+
interactive?: boolean | ((context: RendererInteractiveContext<Annotation>) => boolean);
|
|
2184
|
+
}
|
|
2185
|
+
type RendererEntry<Annotation> = BehaviorRendererEntry | LookRendererEntry<Annotation>;
|
|
2186
|
+
/** The annotation plugin's behavior registry (its host capability satisfies it). */
|
|
2187
|
+
interface RendererBehaviorRegistry<Annotation> {
|
|
2188
|
+
registerBehavior(behavior: {
|
|
2189
|
+
id: string;
|
|
2190
|
+
matches(annotation: Annotation): boolean;
|
|
2191
|
+
engaged(annotation: Annotation): boolean;
|
|
2192
|
+
}): () => void;
|
|
2193
|
+
getBehaviorFor(annotation: Annotation): {
|
|
2194
|
+
id: string;
|
|
2195
|
+
} | null;
|
|
2196
|
+
}
|
|
2197
|
+
/**
|
|
2198
|
+
* Register a behavior for each `interactive` look in `renderers`, so the
|
|
2199
|
+
* plugin lets that renderer take the pointer. Call it when a layer mounts (and
|
|
2200
|
+
* again when its renderer list changes); call what it returns when it
|
|
2201
|
+
* unmounts. `activeToolId` is read whenever an `interactive` function is asked.
|
|
2202
|
+
*/
|
|
2203
|
+
declare function registerRendererBehaviors<Annotation>(annotation: RendererBehaviorRegistry<Annotation>, renderers: readonly RendererEntry<Annotation>[], activeToolId: () => string): () => void;
|
|
2204
|
+
/** The behavior id a renderer entry answers for: a sibling plugin's own, or the one registered for it. */
|
|
2205
|
+
declare function rendererBehaviorId<Annotation>(annotation: object, renderer: RendererEntry<Annotation>): string | null;
|
|
2206
|
+
/** The first of your looks that draws this annotation, or `null`. */
|
|
2207
|
+
declare function lookRendererFor<Annotation, Entry extends RendererEntry<Annotation>>(record: Annotation, renderers: readonly Entry[] | undefined): Extract<Entry, {
|
|
2208
|
+
for: unknown;
|
|
2209
|
+
}> | null;
|
|
2210
|
+
/**
|
|
2211
|
+
* How the layer draws one annotation:
|
|
2212
|
+
* - `native`: its own drawing (the scene or the engine's raster). `inert`
|
|
2213
|
+
* when an engaged behavior's plugin owns the input with no renderer of
|
|
2214
|
+
* yours (a link's anchor takes the click).
|
|
2215
|
+
* - `owned`: a sibling plugin's renderer draws it and takes the input (the
|
|
2216
|
+
* form plugin's fill controls); it places its own controls.
|
|
2217
|
+
* - `look`: your renderer draws it, in the annotation's frame. `interactive`
|
|
2218
|
+
* when an engaged behavior gave it the pointer; otherwise it only draws,
|
|
2219
|
+
* and the frame is `inert` (no pointer, no focus) unless its text box is
|
|
2220
|
+
* being typed in, where the renderer's editor takes the keys.
|
|
2221
|
+
*/
|
|
2222
|
+
type AnnotationDrawing<Entry> = {
|
|
2223
|
+
kind: 'native';
|
|
2224
|
+
inert: boolean;
|
|
2225
|
+
} | {
|
|
2226
|
+
kind: 'owned';
|
|
2227
|
+
entry: Extract<Entry, {
|
|
2228
|
+
behavior: string;
|
|
2229
|
+
}>;
|
|
2230
|
+
} | {
|
|
2231
|
+
kind: 'look';
|
|
2232
|
+
entry: Extract<Entry, {
|
|
2233
|
+
for: unknown;
|
|
2234
|
+
}>;
|
|
2235
|
+
interactive: boolean;
|
|
2236
|
+
inert: boolean;
|
|
2237
|
+
};
|
|
2238
|
+
/**
|
|
2239
|
+
* The drawing an annotation gets. Ownership beats looks: an engaged
|
|
2240
|
+
* behavior's renderer is authoritative; `for` rules apply only to what the
|
|
2241
|
+
* layer owns, and draw without the pointer. `typing` is whether this
|
|
2242
|
+
* annotation's text box is being typed in.
|
|
2243
|
+
*/
|
|
2244
|
+
declare function annotationDrawingOf<Annotation, Entry extends RendererEntry<Annotation>>(record: Annotation, annotation: RendererBehaviorRegistry<Annotation>, renderers: readonly Entry[] | undefined, typing: boolean): AnnotationDrawing<Entry>;
|
|
2245
|
+
/**
|
|
2246
|
+
* The key of the text box being typed in (the one that is `editing` and has a
|
|
2247
|
+
* ref), or `null`. An annotation with this key is `typing` for
|
|
2248
|
+
* {@link annotationDrawingOf}: while it is, a look's own editor takes the keys.
|
|
2249
|
+
*/
|
|
2250
|
+
declare function editingTextKeyOf<Ref>(texts: readonly {
|
|
2251
|
+
readonly editing: boolean;
|
|
2252
|
+
readonly ref: Ref | null;
|
|
2253
|
+
}[], keyOf: (ref: Ref) => string): string | null;
|
|
2254
|
+
/**
|
|
2255
|
+
* The text boxes the layer draws itself: all of them but the ones whose
|
|
2256
|
+
* annotation a look of yours draws, which that look edits with its own editor
|
|
2257
|
+
* (a renderer's rich text editor). `items` are the page's render items, which
|
|
2258
|
+
* carry each annotation; the same array comes back when there is no look.
|
|
2259
|
+
*/
|
|
2260
|
+
declare function layerTextBoxesOf<Annotation, Ref, Text extends {
|
|
2261
|
+
readonly ref: Ref | null;
|
|
2262
|
+
}>(texts: readonly Text[], items: readonly {
|
|
2263
|
+
readonly ref: Ref | null;
|
|
2264
|
+
readonly annotation?: Annotation | null;
|
|
2265
|
+
}[], renderers: readonly RendererEntry<Annotation>[] | undefined, keyOf: (ref: Ref) => string): readonly Text[];
|
|
2266
|
+
//#endregion
|
|
2267
|
+
//#region src/comment-threads.d.ts
|
|
2268
|
+
/**
|
|
2269
|
+
* Comment threads with where their page is shown: the join of the annotation
|
|
2270
|
+
* plugin's threads and the document's page list that a comments panel
|
|
2271
|
+
* prints. A thread's identity stays its page's address; the index and the
|
|
2272
|
+
* label are presentation, following page moves and deletes.
|
|
2273
|
+
*/
|
|
2274
|
+
/** Where a thread's page is shown now. */
|
|
2275
|
+
interface CommentThreadPage {
|
|
2276
|
+
/** Current 0-based display index of the thread's page; `-1` when the page is no longer in the document. */
|
|
2277
|
+
pageIndex: number;
|
|
2278
|
+
/**
|
|
2279
|
+
* The page's `/PageLabels` label when the PDF declares one ("iv", "A-2"),
|
|
2280
|
+
* else the 1-based position as a string; `'?'` for a page that's gone.
|
|
2281
|
+
* Print it as it is.
|
|
2282
|
+
*/
|
|
2283
|
+
pageLabel: string;
|
|
2284
|
+
}
|
|
2285
|
+
/** A page as the document's page list has it: its address, display index and label. */
|
|
2286
|
+
interface CommentPageLayout {
|
|
2287
|
+
readonly ref: {
|
|
2288
|
+
readonly objectNumber: number;
|
|
2289
|
+
};
|
|
2290
|
+
readonly index: number;
|
|
2291
|
+
readonly label?: string | null;
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* Each thread with its page's display index and label. A thread whose page
|
|
2295
|
+
* was just deleted reads `-1` and `'?'` for the one render before it goes.
|
|
2296
|
+
*/
|
|
2297
|
+
declare function enrichCommentThreads<Thread extends {
|
|
2298
|
+
readonly page: {
|
|
2299
|
+
readonly objectNumber: number;
|
|
2300
|
+
};
|
|
2301
|
+
}>(threads: readonly Thread[], pages: readonly CommentPageLayout[]): Array<Thread & CommentThreadPage>;
|
|
2302
|
+
//#endregion
|
|
2303
|
+
//#region src/form-field.d.ts
|
|
2304
|
+
/** The form settings the colors read: the structural twin of the form plugin's `focus` and `fields`. */
|
|
2305
|
+
interface FormColorSettings {
|
|
2306
|
+
readonly focus: {
|
|
2307
|
+
readonly color: string | null;
|
|
2308
|
+
};
|
|
2309
|
+
readonly fields: {
|
|
2310
|
+
readonly border: string | null;
|
|
2311
|
+
readonly background: string;
|
|
2312
|
+
readonly color: string;
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
/** The colors the viewer draws fields with, each its `--epdf-form-*` variable first, then the setting. */
|
|
2316
|
+
interface FormColors {
|
|
2317
|
+
/** The focus ring around the field being filled in. */
|
|
2318
|
+
readonly focus: string;
|
|
2319
|
+
/** The edge of a field without a border of its own. */
|
|
2320
|
+
readonly border: string;
|
|
2321
|
+
/** Inside a field without a background of its own, while it's filled in. */
|
|
2322
|
+
readonly background: string;
|
|
2323
|
+
/** The text of a field without a color of its own. */
|
|
2324
|
+
readonly text: string;
|
|
2325
|
+
}
|
|
2326
|
+
/** The form settings as colors: an unset focus color is the accent, an unset edge the accent at 55%. */
|
|
2327
|
+
declare function formColorsOf(settings: FormColorSettings, accent: string): FormColors;
|
|
2328
|
+
/** How a widget looks in the PDF: the structural twin of the form plugin's `FormWidgetLook`. */
|
|
2329
|
+
interface FieldLook {
|
|
2330
|
+
readonly border: string | null;
|
|
2331
|
+
/** In page points. */
|
|
2332
|
+
readonly borderWidth: number;
|
|
2333
|
+
readonly borderStyle: string;
|
|
2334
|
+
readonly background: string | null;
|
|
2335
|
+
readonly color: string | null;
|
|
2336
|
+
/** One of the 14 standard PDF fonts (`'helvetica-bold'`), or `null`. */
|
|
2337
|
+
readonly fontFamily: string | null;
|
|
2338
|
+
/** In page points; `0` or `null` fits the text to the box. */
|
|
2339
|
+
readonly fontSize: number | null;
|
|
2340
|
+
readonly textAlign: 'left' | 'center' | 'right';
|
|
2341
|
+
}
|
|
2342
|
+
/** A standard PDF font as CSS. */
|
|
2343
|
+
type CssFont = {
|
|
2344
|
+
fontFamily: string;
|
|
2345
|
+
fontWeight: number;
|
|
2346
|
+
fontStyle: 'normal' | 'italic';
|
|
2347
|
+
};
|
|
2348
|
+
/** One of the 14 standard PDF fonts as CSS: a family that looks like it, its weight and style. */
|
|
2349
|
+
declare function cssFontOf(pdfFont: string | null): CssFont;
|
|
2350
|
+
/** A field's text as CSS: its font, size, alignment and colors, the settings where it has none. */
|
|
2351
|
+
type FieldTextStyle = CssFont & {
|
|
2352
|
+
/** In pixels, with its unit. */
|
|
2353
|
+
fontSize: string;
|
|
2354
|
+
textAlign: 'left' | 'center' | 'right';
|
|
2355
|
+
color: string;
|
|
2356
|
+
background: string;
|
|
2357
|
+
};
|
|
2358
|
+
/** A text field as the layer's editor shows it while focused, in the field's own font. */
|
|
2359
|
+
type TextFieldStyle = FieldTextStyle & {
|
|
2360
|
+
/** A comb field's spacing (its box split into `maxLength` cells), in pixels with its unit. */
|
|
2361
|
+
letterSpacing?: string;
|
|
2362
|
+
};
|
|
2363
|
+
/**
|
|
2364
|
+
* A text field's editor style. A font size of 0 means "fit the box" in PDF:
|
|
2365
|
+
* the box height for one line, Acrobat's 12 pt for several.
|
|
2366
|
+
*/
|
|
2367
|
+
declare function textFieldStyleOf(field: {
|
|
2368
|
+
box: {
|
|
2369
|
+
width: number;
|
|
2370
|
+
};
|
|
2371
|
+
look: FieldLook;
|
|
2372
|
+
multiline: boolean;
|
|
2373
|
+
comb: boolean;
|
|
2374
|
+
maxLength: number | null;
|
|
2375
|
+
}, frame: PixelRect, colors: FormColors): TextFieldStyle;
|
|
2376
|
+
/** A list box as the layer draws it: the field's text look, and its border. */
|
|
2377
|
+
type ListBoxStyle = FieldTextStyle & {
|
|
2378
|
+
/** In pixels, with its unit; never thinner than one pixel. */
|
|
2379
|
+
borderWidth: string;
|
|
2380
|
+
borderStyle: 'solid' | 'dashed';
|
|
2381
|
+
borderColor: string;
|
|
2382
|
+
};
|
|
2383
|
+
/** A list box's style: the field's own look, the settings where it has none (12 pt for a fitted size). */
|
|
2384
|
+
declare function listBoxStyleOf(field: {
|
|
2385
|
+
box: {
|
|
2386
|
+
width: number;
|
|
2387
|
+
};
|
|
2388
|
+
look: FieldLook;
|
|
2389
|
+
}, frame: PixelRect, colors: FormColors): ListBoxStyle;
|
|
2390
|
+
/** The PDF events a widget's `/AA` actions answer, as the actions plugin names them. */
|
|
2391
|
+
type WidgetEventKind = 'cursorEnter' | 'cursorExit' | 'mouseDown' | 'mouseUp' | 'focus' | 'blur';
|
|
2392
|
+
/**
|
|
2393
|
+
* Send a widget's pointer and focus events (`/AA`: enter, exit, down, up,
|
|
2394
|
+
* focus, blur) to `notify`, from native listeners on the widget's box. Put
|
|
2395
|
+
* them on the always-active box, never on the control inside: "may edit this
|
|
2396
|
+
* field" and "may receive PDF action events" are different rights, and a
|
|
2397
|
+
* session that may not fill still sees hover tooltips. Focus is `focusin` and
|
|
2398
|
+
* `focusout`, so the control's focus reaches the box, and a blur arrives
|
|
2399
|
+
* after the control's own blur handler started its commit. Returns the
|
|
2400
|
+
* detach.
|
|
2401
|
+
*/
|
|
2402
|
+
declare function bindWidgetEvents(box: HTMLElement, notify: (event: WidgetEventKind) => void): () => void;
|
|
2403
|
+
/** What a toggle press writes with: the form plugin's `setValue`. */
|
|
2404
|
+
interface ToggleForm<Field> {
|
|
2405
|
+
setValue(field: Field, value: {
|
|
2406
|
+
value: string | null;
|
|
2407
|
+
}): Promise<unknown>;
|
|
2408
|
+
}
|
|
2409
|
+
/**
|
|
2410
|
+
* A checkbox or radio button pressed: a checked checkbox clears, a radio
|
|
2411
|
+
* button always selects its own value. The value is written first, then the
|
|
2412
|
+
* widget's action runs (Acrobat's order), so an action script reads the new
|
|
2413
|
+
* state; a read-only toggle writes nothing and still runs its action.
|
|
2414
|
+
*/
|
|
2415
|
+
declare function pressToggle<Field>(form: ToggleForm<Field>, toggle: {
|
|
2416
|
+
fieldRef: Field;
|
|
2417
|
+
kind: 'checkbox' | 'radio';
|
|
2418
|
+
checked: boolean;
|
|
2419
|
+
exportValue: string;
|
|
2420
|
+
disabled: boolean;
|
|
2421
|
+
}, activate: () => void): void;
|
|
2422
|
+
/** The form plugin's draft calls for a text field (its host capability satisfies it). */
|
|
2423
|
+
interface TextFieldDrafts<Field> {
|
|
2424
|
+
draftText(field: Field, text: string): void;
|
|
2425
|
+
/** Resolves with how the write ended (`'rejected'`: the form's validation refused it), or `null`. */
|
|
2426
|
+
commitDraftText(field: Field): Promise<{
|
|
2427
|
+
readonly status: string;
|
|
2428
|
+
} | null>;
|
|
2429
|
+
discardDraftText(field: Field): void;
|
|
2430
|
+
}
|
|
2431
|
+
/** What a text field's editor shows: whether it has focus, and the text in it. */
|
|
2432
|
+
interface TextFieldEditorState {
|
|
2433
|
+
readonly focused: boolean;
|
|
2434
|
+
readonly draft: string;
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* A text field being typed in, framework-free: the editor's `value` is
|
|
2438
|
+
* `draft`, and its events call the methods. Read the state with `getState`
|
|
2439
|
+
* and re-render on `subscribe`; the state object stays the same until it
|
|
2440
|
+
* changes.
|
|
2441
|
+
*/
|
|
2442
|
+
interface TextFieldEditor {
|
|
2443
|
+
getState(): TextFieldEditorState;
|
|
2444
|
+
subscribe(listener: () => void): () => void;
|
|
2445
|
+
/** The field's value as the form has it now. The draft follows it, except while focused. */
|
|
2446
|
+
setValue(value: string): void;
|
|
2447
|
+
/** The editor took focus. */
|
|
2448
|
+
focus(): void;
|
|
2449
|
+
/** Someone typed: the draft shows it, and the plugin keeps it so a download writes it. */
|
|
2450
|
+
input(text: string): void;
|
|
2451
|
+
/**
|
|
2452
|
+
* A key went down. True when the editor should blur now: Escape (which
|
|
2453
|
+
* puts the value back) and, in a one-line field, Enter (which commits).
|
|
2454
|
+
*/
|
|
2455
|
+
keyDown(key: string, multiline: boolean): boolean;
|
|
2456
|
+
/** The editor lost focus: commit what changed, discard what didn't or was cancelled. */
|
|
2457
|
+
blur(): void;
|
|
2458
|
+
}
|
|
2459
|
+
/**
|
|
2460
|
+
* The editing policy of one text field: typing drafts, blur or Enter
|
|
2461
|
+
* commits, Escape discards. A commit keeps the typed text until the field
|
|
2462
|
+
* shows it (at once, as the form shows a fill before the engine answers), so
|
|
2463
|
+
* a blur never shows the old value for a moment. A value the form's
|
|
2464
|
+
* validation refuses stays typed, as in Acrobat; a write the engine refuses
|
|
2465
|
+
* puts the field's value back.
|
|
2466
|
+
*/
|
|
2467
|
+
declare function createTextFieldEditor<Field>(form: TextFieldDrafts<Field>, field: Field, value: string): TextFieldEditor;
|
|
2468
|
+
/**
|
|
2469
|
+
* A list box's selection, shown at once while its write is on its way. The
|
|
2470
|
+
* native control must stay the same element (never remounted), so its own
|
|
2471
|
+
* scroll position stays where the user left it.
|
|
2472
|
+
*/
|
|
2473
|
+
interface OptimisticSelection {
|
|
2474
|
+
/** The selection the control shows. */
|
|
2475
|
+
get(): readonly string[];
|
|
2476
|
+
subscribe(listener: () => void): () => void;
|
|
2477
|
+
/** The selection the engine has now: the control shows it once it differs from the last one. */
|
|
2478
|
+
setConfirmed(values: readonly string[]): void;
|
|
2479
|
+
/** Show `values` now and write them; a write that fails puts the engine's selection back. */
|
|
2480
|
+
choose(values: string[], write: (values: string[]) => void | Promise<unknown>): void;
|
|
2481
|
+
}
|
|
2482
|
+
/** A list box's optimistic selection, starting at the engine's. */
|
|
2483
|
+
declare function createOptimisticSelection(confirmed: readonly string[]): OptimisticSelection;
|
|
2484
|
+
/** A native `<select>`, as {@link showSelectedOptions} reads it: its options. */
|
|
2485
|
+
interface SelectOptions {
|
|
2486
|
+
readonly options: ArrayLike<{
|
|
2487
|
+
readonly value: string;
|
|
2488
|
+
selected: boolean;
|
|
2489
|
+
}>;
|
|
2490
|
+
}
|
|
2491
|
+
/**
|
|
2492
|
+
* Show `values` as a native `<select>`'s selection, set on each option. A
|
|
2493
|
+
* `value` binding can't hold several values, and setting the options also
|
|
2494
|
+
* puts a choice back when its write fails before the framework renders
|
|
2495
|
+
* again. Setting the same selection again changes nothing the user sees,
|
|
2496
|
+
* scroll position included.
|
|
2497
|
+
*/
|
|
2498
|
+
declare function showSelectedOptions(select: SelectOptions, values: readonly string[]): void;
|
|
2499
|
+
//#endregion
|
|
2500
|
+
//#region src/form-styles.d.ts
|
|
2501
|
+
/** A control that fills the widget's box it sits in: every native control the layer draws. */
|
|
2502
|
+
declare const FORM_CONTROL_FILL: Readonly<{
|
|
2503
|
+
readonly position: "absolute";
|
|
2504
|
+
readonly inset: "0";
|
|
2505
|
+
readonly width: "100%";
|
|
2506
|
+
readonly height: "100%";
|
|
2507
|
+
readonly boxSizing: "border-box";
|
|
2508
|
+
readonly margin: "0";
|
|
2509
|
+
}>;
|
|
2510
|
+
/** {@link FORM_CONTROL_FILL}'s shape. */
|
|
2511
|
+
type FormControlFill = typeof FORM_CONTROL_FILL;
|
|
2512
|
+
/** The box a widget's control sits in, placed over the widget on the page. */
|
|
2513
|
+
type WidgetBoxStyle = {
|
|
2514
|
+
position: 'absolute';
|
|
2515
|
+
left: string;
|
|
2516
|
+
top: string;
|
|
2517
|
+
width: string;
|
|
2518
|
+
height: string;
|
|
2519
|
+
/** Always the widget's event surface: the control inside gates the edits. */
|
|
2520
|
+
pointerEvents: 'auto';
|
|
2521
|
+
/** The edge of a field without a border of its own, so people see where to fill in. */
|
|
2522
|
+
boxShadow?: string;
|
|
2523
|
+
};
|
|
2524
|
+
/**
|
|
2525
|
+
* The style of a widget's box at `frame` (the widget's box in the page
|
|
2526
|
+
* layer's pixels). `edge: false` leaves the edge out, for a control that draws
|
|
2527
|
+
* its own (a list box) or never has one (a button).
|
|
2528
|
+
*/
|
|
2529
|
+
declare function widgetBoxStyleOf(widget: {
|
|
2530
|
+
look: Pick<FieldLook, 'border'>;
|
|
2531
|
+
}, frame: PixelRect, colors: FormColors, { edge }?: {
|
|
2532
|
+
edge?: boolean;
|
|
2533
|
+
}): WidgetBoxStyle;
|
|
2534
|
+
/**
|
|
2535
|
+
* Where a text field's editor shows the text typed in it, so it sits where the engine will draw
|
|
2536
|
+
* it (the form plugin's `getTextEditorLayout`), in page points.
|
|
2537
|
+
*/
|
|
2538
|
+
interface TextEditorLayout {
|
|
2539
|
+
readonly fontFamily: string;
|
|
2540
|
+
readonly fontWeight: number;
|
|
2541
|
+
readonly fontStyle: 'normal' | 'italic';
|
|
2542
|
+
readonly fontSize: number;
|
|
2543
|
+
readonly lineHeight: number;
|
|
2544
|
+
readonly padding: {
|
|
2545
|
+
readonly top: number;
|
|
2546
|
+
readonly right: number;
|
|
2547
|
+
readonly bottom: number;
|
|
2548
|
+
readonly left: number;
|
|
2549
|
+
};
|
|
2550
|
+
/** A comb's room between characters; it starts at the left padding, whatever the alignment. */
|
|
2551
|
+
readonly letterSpacing: number;
|
|
2552
|
+
readonly comb: boolean;
|
|
2553
|
+
}
|
|
2554
|
+
/** A text field's editor: see-through at rest, the field's own look while focused. */
|
|
2555
|
+
type TextFieldEditorStyle = FormControlFill & TextFieldStyle & {
|
|
2556
|
+
border: 'none';
|
|
2557
|
+
outline: string;
|
|
2558
|
+
outlineOffset: string;
|
|
2559
|
+
padding: string;
|
|
2560
|
+
/** In pixels, with its unit: one line of the engine's layout. */
|
|
2561
|
+
lineHeight?: string;
|
|
2562
|
+
resize: 'none';
|
|
2563
|
+
cursor: 'text';
|
|
2564
|
+
/** 1 while focused, 0 at rest, where the field's picture shows through. */
|
|
2565
|
+
opacity: number;
|
|
2566
|
+
/** `none` for a disabled field: the box below runs the widget's action. */
|
|
2567
|
+
pointerEvents?: 'none';
|
|
2568
|
+
};
|
|
2569
|
+
/**
|
|
2570
|
+
* The style of a text field's editor, the `<input>` or `<textarea>` that is
|
|
2571
|
+
* always there: focused, it shows the field's text in its own font with a
|
|
2572
|
+
* focus ring; at rest it is see-through over the field's picture. A disabled
|
|
2573
|
+
* control would swallow clicks, and the box below runs the widget's action
|
|
2574
|
+
* (the read-only "button" pattern), so a disabled one lets them through.
|
|
2575
|
+
*
|
|
2576
|
+
* With the engine's `layout` of the text being typed, the editor writes it
|
|
2577
|
+
* where the engine will draw it: in the engine's face (mounted), at the size
|
|
2578
|
+
* it draws (a fitted size resolved), in the box inside the border, a line of
|
|
2579
|
+
* the face's height (one line centred, as the engine centres it).
|
|
2580
|
+
*/
|
|
2581
|
+
declare function textFieldEditorStyleOf(field: Parameters<typeof textFieldStyleOf>[0] & {
|
|
2582
|
+
disabled: boolean;
|
|
2583
|
+
}, frame: PixelRect, colors: FormColors, focused: boolean, layout?: TextEditorLayout | null): TextFieldEditorStyle;
|
|
2584
|
+
/** A list box: the visible native `<select>` in the field's own look. */
|
|
2585
|
+
type ListBoxControlStyle = FormControlFill & ListBoxStyle & {
|
|
2586
|
+
padding: string;
|
|
2587
|
+
borderRadius: string;
|
|
2588
|
+
outline: 'none';
|
|
2589
|
+
cursor: 'default' | 'pointer';
|
|
2590
|
+
/** `none` for a disabled field: the box below runs the widget's action. */
|
|
2591
|
+
pointerEvents?: 'none';
|
|
2592
|
+
};
|
|
2593
|
+
/**
|
|
2594
|
+
* The style of a list box's `<select>`, filling the widget's box: the field's
|
|
2595
|
+
* own look ({@link listBoxStyleOf}) with its own border, so the box adds no
|
|
2596
|
+
* edge. The focus ring is drawn above it ({@link formFocusRingStyleOf}).
|
|
2597
|
+
*/
|
|
2598
|
+
declare function listBoxControlStyleOf(field: Parameters<typeof listBoxStyleOf>[0] & {
|
|
2599
|
+
disabled: boolean;
|
|
2600
|
+
}, frame: PixelRect, colors: FormColors): ListBoxControlStyle;
|
|
2601
|
+
/** The focus ring of a field whose control is see-through, or is the box itself. */
|
|
2602
|
+
type FormFocusRingStyle = {
|
|
2603
|
+
position: 'absolute';
|
|
2604
|
+
inset: string;
|
|
2605
|
+
zIndex: number;
|
|
2606
|
+
boxSizing: 'border-box';
|
|
2607
|
+
outline: string;
|
|
2608
|
+
outlineOffset: string;
|
|
2609
|
+
pointerEvents: 'none';
|
|
2610
|
+
};
|
|
2611
|
+
/**
|
|
2612
|
+
* The style of a field's focus ring in `color` (the form's focus color): an
|
|
2613
|
+
* element of its own above the field's picture and its control. An outline on
|
|
2614
|
+
* the box would sit under an opaque child, so a rectangular checkbox or a
|
|
2615
|
+
* dropdown would look unfocused while it has the focus.
|
|
2616
|
+
*/
|
|
2617
|
+
declare function formFocusRingStyleOf(color: string): FormFocusRingStyle;
|
|
2618
|
+
//#endregion
|
|
2619
|
+
//#region src/link-anchor.d.ts
|
|
2620
|
+
/** A link as the link plugin lists it: the fields the anchor reads. */
|
|
2621
|
+
interface LinkAnchorShape {
|
|
2622
|
+
readonly target: {
|
|
2623
|
+
readonly kind: string;
|
|
2624
|
+
readonly uri?: string;
|
|
2625
|
+
};
|
|
2626
|
+
/** The full `/A` tree; a `/Next` after its root chains more actions. */
|
|
2627
|
+
readonly activate?: {
|
|
2628
|
+
readonly root: {
|
|
2629
|
+
readonly next: readonly unknown[];
|
|
2630
|
+
} | null;
|
|
2631
|
+
} | null;
|
|
2632
|
+
/** A link riding an editable annotation (its parent owns its pixels while annotations are edited). */
|
|
2633
|
+
readonly attached: boolean;
|
|
2634
|
+
}
|
|
2635
|
+
/**
|
|
2636
|
+
* The links a page layer shows anchors for. One owner per pixel: while the
|
|
2637
|
+
* active tool edits annotations, a link attached to an annotation stands
|
|
2638
|
+
* down so its parent can be selected and moved; a document's own links
|
|
2639
|
+
* navigate under every tool that enables link navigation.
|
|
2640
|
+
*/
|
|
2641
|
+
declare function navigableLinksOf<Link extends LinkAnchorShape>(links: readonly Link[], annotationEditEnabled: boolean): readonly Link[];
|
|
2642
|
+
/**
|
|
2643
|
+
* The anchor's native `href`: only for a website the browser may open and
|
|
2644
|
+
* nothing chained after it. Blocked schemes, targets inside the document and
|
|
2645
|
+
* action chains activate through the plugin instead: a native navigation
|
|
2646
|
+
* would run the first action and silently drop the rest.
|
|
2647
|
+
*/
|
|
2648
|
+
declare function linkHrefOf(link: LinkAnchorShape): string | null;
|
|
2649
|
+
/** A link's anchor, ready to draw. */
|
|
2650
|
+
interface LinkAnchor<Link> {
|
|
2651
|
+
readonly link: Link;
|
|
2652
|
+
/** Where the anchor sits, in the page layer's pixels. */
|
|
2653
|
+
readonly box: PixelRect;
|
|
2654
|
+
/** Its native `href` ({@link linkHrefOf}), or null. */
|
|
2655
|
+
readonly href: string | null;
|
|
2656
|
+
/** Its `title` and `aria-label`. */
|
|
2657
|
+
readonly label: string;
|
|
2658
|
+
}
|
|
2659
|
+
/**
|
|
2660
|
+
* The anchor for `link` on a page layer: its box from the link's `bounds`,
|
|
2661
|
+
* its `href`, and the label `labelOf` (the link plugin's `getLabel`) gives it.
|
|
2662
|
+
*/
|
|
2663
|
+
declare function linkAnchorOf<Link extends LinkAnchorShape & {
|
|
2664
|
+
readonly bounds: {
|
|
2665
|
+
x: number;
|
|
2666
|
+
y: number;
|
|
2667
|
+
width: number;
|
|
2668
|
+
height: number;
|
|
2669
|
+
};
|
|
2670
|
+
}>(link: Link, page: PageToPixels, labelOf: (link: Link) => string): LinkAnchor<Link>;
|
|
2671
|
+
/**
|
|
2672
|
+
* Whether a click on an anchor with an `href` stays the browser's: a click
|
|
2673
|
+
* with a modifier key opens a background tab or a new window. Every other
|
|
2674
|
+
* click is prevented and follows the link through the plugin.
|
|
2675
|
+
*/
|
|
2676
|
+
declare function isModifiedClick(event: {
|
|
2677
|
+
metaKey: boolean;
|
|
2678
|
+
ctrlKey: boolean;
|
|
2679
|
+
shiftKey: boolean;
|
|
2680
|
+
altKey: boolean;
|
|
2681
|
+
}): boolean;
|
|
2682
|
+
//#endregion
|
|
2683
|
+
//#region src/link-events.d.ts
|
|
2684
|
+
/**
|
|
2685
|
+
* What a page link's anchor tells the plugins: the context a click or a key
|
|
2686
|
+
* follows the link with (the link plugin's `activate()`), and the link's own
|
|
2687
|
+
* PDF events (`/AA`): entering and leaving through the layer's hover pump,
|
|
2688
|
+
* the press, the release, focus and blur through the actions plugin's
|
|
2689
|
+
* `dispatch()`. Only a link that is an annotation has events of its own. The
|
|
2690
|
+
* plugins' types are mirrored structurally and their refs stay opaque, so
|
|
2691
|
+
* this package stays free of EmbedPDF imports.
|
|
2692
|
+
*/
|
|
2693
|
+
/** The events an anchor sends the actions plugin itself; entering and leaving go through the hover pump. */
|
|
2694
|
+
type LinkAnchorEvent = 'mouseDown' | 'mouseUp' | 'focus' | 'blur';
|
|
2695
|
+
/** A link's fields these read: its `/A` tree, the annotation it is, and which hover trees it has. */
|
|
2696
|
+
interface LinkEventShape<Ref, Action = unknown, HoverEvents = unknown> {
|
|
2697
|
+
readonly activate?: Action;
|
|
2698
|
+
readonly ref?: Ref;
|
|
2699
|
+
readonly hoverEvents?: HoverEvents;
|
|
2700
|
+
}
|
|
2701
|
+
/** The link as the source of an actions-plugin event. */
|
|
2702
|
+
interface LinkActionSource<Ref, Page> {
|
|
2703
|
+
readonly kind: 'link';
|
|
2704
|
+
readonly annotation: Ref;
|
|
2705
|
+
readonly page: Page;
|
|
2706
|
+
}
|
|
2707
|
+
/** The actions plugin, as an anchor uses it. */
|
|
2708
|
+
interface LinkActionDispatcher<Ref, Page> {
|
|
2709
|
+
dispatch(trigger: {
|
|
2710
|
+
readonly scope: 'annotation';
|
|
2711
|
+
readonly event: LinkAnchorEvent;
|
|
2712
|
+
readonly ref: Ref;
|
|
2713
|
+
readonly page: Page;
|
|
2714
|
+
readonly source: LinkActionSource<Ref, Page>;
|
|
2715
|
+
}): unknown;
|
|
2716
|
+
}
|
|
2717
|
+
/** One link layer's hover pump (`createHoverPump` in the actions plugin's contract). */
|
|
2718
|
+
interface LinkHoverPump<Ref, Page, HoverEvents> {
|
|
2719
|
+
hover(target: {
|
|
2720
|
+
readonly ref: Ref;
|
|
2721
|
+
readonly page: Page;
|
|
2722
|
+
readonly source: LinkActionSource<Ref, Page>;
|
|
2723
|
+
readonly events: HoverEvents;
|
|
2724
|
+
} | null): void;
|
|
2725
|
+
}
|
|
2726
|
+
/**
|
|
2727
|
+
* The context a click or a key follows `link` with: its `/A` tree (the
|
|
2728
|
+
* actions plugin runs it instead of the target), the annotation it is, its
|
|
2729
|
+
* page, and the view it was followed in (a page destination moves that one).
|
|
2730
|
+
*/
|
|
2731
|
+
declare function linkActivateContextOf<Ref, Action, Page, Stage>(link: LinkEventShape<Ref, Action>, page: Page, stage: Stage | null): {
|
|
2732
|
+
activate?: Action;
|
|
2733
|
+
ref?: Ref;
|
|
2734
|
+
page: Page;
|
|
2735
|
+
stage?: Stage;
|
|
2736
|
+
};
|
|
2737
|
+
/**
|
|
2738
|
+
* Send `link`'s own event for a press, a release or a focus change: only for
|
|
2739
|
+
* a link that is an annotation, and only with the actions plugin.
|
|
2740
|
+
*/
|
|
2741
|
+
declare function sendLinkEvent<Ref, Page>(actions: NoInfer<LinkActionDispatcher<Ref, Page>> | null, link: LinkEventShape<Ref>, page: Page, event: LinkAnchorEvent): void;
|
|
2742
|
+
/**
|
|
2743
|
+
* Tell the layer's hover pump the pointer entered `link`: only a link that is
|
|
2744
|
+
* an annotation with hover trees has enter and exit events. Leaving is
|
|
2745
|
+
* `pump.hover(null)`.
|
|
2746
|
+
*/
|
|
2747
|
+
declare function hoverLink<Ref, Page, HoverEvents>(pump: NoInfer<LinkHoverPump<Ref, Page, HoverEvents>> | null, link: LinkEventShape<Ref, unknown, HoverEvents>, page: Page): void;
|
|
2748
|
+
//#endregion
|
|
2749
|
+
//#region src/search-highlights.d.ts
|
|
2750
|
+
/** A match as the search plugin lists it: the fields the paint reads. */
|
|
2751
|
+
interface SearchHitShape {
|
|
2752
|
+
/** Where the match starts in the document's text: with the line's index, its key. */
|
|
2753
|
+
readonly start: number;
|
|
2754
|
+
/** One per line the match spans, in page points. */
|
|
2755
|
+
readonly segments: readonly {
|
|
2756
|
+
readonly quad: PageQuad;
|
|
2757
|
+
}[];
|
|
2758
|
+
}
|
|
2759
|
+
/** One line of a match, ready to draw. */
|
|
2760
|
+
interface SearchHighlightPiece<Hit extends SearchHitShape> {
|
|
2761
|
+
readonly key: string;
|
|
2762
|
+
readonly hit: Hit;
|
|
2763
|
+
/** Whether it's a line of the active match. */
|
|
2764
|
+
readonly active: boolean;
|
|
2765
|
+
readonly fill: string;
|
|
2766
|
+
/** The line's box in the page layer's pixels when it's upright; null when it's turned. */
|
|
2767
|
+
readonly box: PixelRect | null;
|
|
2768
|
+
/** The four corners as SVG `points`, for a turned line; null when it's upright. */
|
|
2769
|
+
readonly points: string | null;
|
|
2770
|
+
}
|
|
2771
|
+
/** What {@link searchHighlightsOf} paints with. */
|
|
2772
|
+
interface SearchHighlightOptions<Hit extends SearchHitShape> {
|
|
2773
|
+
/** The search's active match (compared by identity), or null. */
|
|
2774
|
+
readonly active: Hit | null;
|
|
2775
|
+
/** The page layer's transform. */
|
|
2776
|
+
readonly page: PageToPixels;
|
|
2777
|
+
/** The fill of a match, and of the active one (`paint('search-highlight', …)`). */
|
|
2778
|
+
readonly color: string;
|
|
2779
|
+
readonly activeColor: string;
|
|
2780
|
+
}
|
|
2781
|
+
/** Every line of `hits` as a piece to draw, in hit order. */
|
|
2782
|
+
declare function searchHighlightsOf<Hit extends SearchHitShape>(hits: readonly Hit[], options: SearchHighlightOptions<Hit>): SearchHighlightPiece<Hit>[];
|
|
2783
|
+
//#endregion
|
|
2784
|
+
//#region src/press-click.d.ts
|
|
2785
|
+
/**
|
|
2786
|
+
* Telling a click from a drag on something drawn over a page (a search
|
|
2787
|
+
* match). The press still reaches the page, so a drag that starts there
|
|
2788
|
+
* selects text; only a press that stays put counts as a click.
|
|
2789
|
+
*/
|
|
2790
|
+
/** A click detector for one layer: feed it the `pointerdown`, ask it at the `click`. */
|
|
2791
|
+
interface ClickDetector {
|
|
2792
|
+
/** A press began (`pointerdown`). */
|
|
2793
|
+
press(event: {
|
|
2794
|
+
clientX: number;
|
|
2795
|
+
clientY: number;
|
|
2796
|
+
pointerType: string;
|
|
2797
|
+
}): void;
|
|
2798
|
+
/** Whether this `click` is a click, not the end of a drag. Forgets the press. */
|
|
2799
|
+
isClick(event: {
|
|
2800
|
+
clientX: number;
|
|
2801
|
+
clientY: number;
|
|
2802
|
+
}): boolean;
|
|
2803
|
+
}
|
|
2804
|
+
declare function createClickDetector(): ClickDetector;
|
|
2805
|
+
//#endregion
|
|
2806
|
+
//#region src/page-projector.d.ts
|
|
2807
|
+
/** The page transform members a projection reads; `PageTransform` satisfies it. */
|
|
2808
|
+
interface ProjectedTransform {
|
|
2809
|
+
readonly viewScale: number;
|
|
2810
|
+
readonly rotation: 0 | 90 | 180 | 270;
|
|
2811
|
+
readonly zoom: number;
|
|
2812
|
+
}
|
|
2813
|
+
/**
|
|
2814
|
+
* The page surface a client projector measures: the page context's members. `transform` may be
|
|
2815
|
+
* the transform or a function that returns the current one (a signal).
|
|
2816
|
+
*/
|
|
2817
|
+
interface ClientProjectedPage {
|
|
2818
|
+
readonly ref: PageRef;
|
|
2819
|
+
readonly transform: ProjectedTransform | (() => ProjectedTransform);
|
|
2820
|
+
toClientRect(rect: AnchoredRect): AnchoredRect;
|
|
2821
|
+
toClientPoint(point: {
|
|
2822
|
+
x: number;
|
|
2823
|
+
y: number;
|
|
2824
|
+
}): {
|
|
2825
|
+
x: number;
|
|
2826
|
+
y: number;
|
|
2827
|
+
};
|
|
2828
|
+
}
|
|
2829
|
+
/**
|
|
2830
|
+
* A client-space projector for one page. `mounted` says whether the page
|
|
2831
|
+
* element is in the document yet: until it is, every projection is `null`,
|
|
2832
|
+
* and the anchored UI waits for the first measurable pass. The view is the
|
|
2833
|
+
* window. Pair it with {@link observeClientGeometry}, which reports the
|
|
2834
|
+
* browser-driven moves (document scroll, window resize) no state announces.
|
|
2835
|
+
* Every member reads `page` when it runs, so a page context whose members
|
|
2836
|
+
* change keeps one projector.
|
|
2837
|
+
*/
|
|
2838
|
+
declare function clientPageProjector(page: ClientProjectedPage, mounted: () => boolean): ViewProjector;
|
|
2839
|
+
/** What a Stage projection reads from the Stage lens; `StageHostCapability` satisfies it. */
|
|
2840
|
+
interface StageProjection {
|
|
2841
|
+
pageRectToViewport(page: PageRef, rect: AnchoredRect): AnchoredRect | null;
|
|
2842
|
+
getPageFrame(page: PageRef): {
|
|
2843
|
+
readonly transform: ProjectedTransform;
|
|
2844
|
+
} | null;
|
|
2845
|
+
getViewportSize(): {
|
|
2846
|
+
width: number;
|
|
2847
|
+
height: number;
|
|
2848
|
+
};
|
|
2849
|
+
}
|
|
2850
|
+
/**
|
|
2851
|
+
* The Stage's projector: anchored UI positions through the camera, in the Stage's own box
|
|
2852
|
+
* (`'overlay'` space). `stage()` gives the lens when a projection runs, or null without one
|
|
2853
|
+
* (nothing projects then). It reads only the Stage's state, so the binding's revision (the
|
|
2854
|
+
* visible pages) is what tells anchored UI to place itself again, in the same render as the
|
|
2855
|
+
* pages.
|
|
2856
|
+
*/
|
|
2857
|
+
declare function stageViewProjector(stage: () => StageProjection | null): ViewProjector;
|
|
2858
|
+
//#endregion
|
|
2859
|
+
//#region src/page-context.d.ts
|
|
2860
|
+
interface ContextPoint {
|
|
2861
|
+
x: number;
|
|
2862
|
+
y: number;
|
|
2863
|
+
}
|
|
2864
|
+
interface ContextRect {
|
|
2865
|
+
x: number;
|
|
2866
|
+
y: number;
|
|
2867
|
+
width: number;
|
|
2868
|
+
height: number;
|
|
2869
|
+
}
|
|
2870
|
+
/** The bands reserved around a page for its chrome, in screen pixels per side. */
|
|
2871
|
+
interface PageFrameShape {
|
|
2872
|
+
top: number;
|
|
2873
|
+
right: number;
|
|
2874
|
+
bottom: number;
|
|
2875
|
+
left: number;
|
|
2876
|
+
}
|
|
2877
|
+
/** What the conversions need from the page transform; `PageTransform` satisfies it. */
|
|
2878
|
+
interface PageContextTransform {
|
|
2879
|
+
viewToPage(point: ContextPoint): ContextPoint;
|
|
2880
|
+
pageToView(point: ContextPoint): ContextPoint;
|
|
2881
|
+
pageToViewRect(rect: ContextRect): ContextRect;
|
|
2882
|
+
}
|
|
2883
|
+
/** Where the page's content box is on screen, in client pixels: `getBoundingClientRect()`. */
|
|
2884
|
+
interface ClientBox {
|
|
2885
|
+
readonly left: number;
|
|
2886
|
+
readonly top: number;
|
|
2887
|
+
}
|
|
2888
|
+
/** Between client (screen) pixels and points on one page. */
|
|
2889
|
+
interface PageClientSpace {
|
|
2890
|
+
/** A client (screen) point to a point on the page: the one platform-bound hit test. */
|
|
2891
|
+
toPagePoint(clientX: number, clientY: number): ContextPoint;
|
|
2892
|
+
/**
|
|
2893
|
+
* A point on the page to client pixels, the exact inverse of `toPagePoint` (rotation applied),
|
|
2894
|
+
* so UI in the view can anchor to a page point without a Stage camera.
|
|
2895
|
+
*/
|
|
2896
|
+
toClientPoint(point: ContextPoint): ContextPoint;
|
|
2897
|
+
/** A box on the page to the client-pixel box around it: the box twin of `toClientPoint`. */
|
|
2898
|
+
toClientRect(rect: ContextRect): ContextRect;
|
|
2899
|
+
}
|
|
2900
|
+
/**
|
|
2901
|
+
* The page context. `Transform` is the page transform (`PageTransform`), `Demand` what the view
|
|
2902
|
+
* wants rendered (`PageViewDemand`).
|
|
2903
|
+
*/
|
|
2904
|
+
interface PageContext<Transform extends PageContextTransform, Demand> extends PageClientSpace {
|
|
2905
|
+
documentId: string;
|
|
2906
|
+
/**
|
|
2907
|
+
* The page's durable address: use it for keys, rendering and annotations (read
|
|
2908
|
+
* `ref.objectNumber` where a map key is needed). The same object for the surface's lifetime,
|
|
2909
|
+
* so layers may key their work on it.
|
|
2910
|
+
*/
|
|
2911
|
+
ref: PageRef;
|
|
2912
|
+
/** The display index (page N), from 0: for ordering and page numbers people read. */
|
|
2913
|
+
pageIndex: number;
|
|
2914
|
+
/**
|
|
2915
|
+
* The bands reserved around the page, in screen pixels per side. The page chrome draws into
|
|
2916
|
+
* the outer box (content and frame): a label in the bottom band is
|
|
2917
|
+
* `bottom: 0; height: frame.bottom`.
|
|
2918
|
+
*/
|
|
2919
|
+
frame: PageFrameShape;
|
|
2920
|
+
/**
|
|
2921
|
+
* The one bridge between PDF points, view pixels and device pixels for this page: `toPixels`
|
|
2922
|
+
* to place content, `renderScale` and `deviceWidth` to render, `contentWidth` for sizes
|
|
2923
|
+
* relative to the page. Never multiply by the scale or the device pixel ratio yourself.
|
|
2924
|
+
*/
|
|
2925
|
+
transform: Transform;
|
|
2926
|
+
/**
|
|
2927
|
+
* What the page's view wants rendered, as a pull the host fills: a Stage reads the page's
|
|
2928
|
+
* visible part live at call time (a zero box while it is off screen, see
|
|
2929
|
+
* {@link stagePageDemand}); a surface without a camera leaves it out, which means the whole
|
|
2930
|
+
* page.
|
|
2931
|
+
*/
|
|
2932
|
+
getViewDemand?: () => Demand;
|
|
2933
|
+
/**
|
|
2934
|
+
* The hosting view's identity: the stage lens id (`stage.getLensId()`) or a per-instance
|
|
2935
|
+
* `PageView` id. Per-view raster planning (tiles) keys its state by it, so two views showing
|
|
2936
|
+
* the same page never fight over one plan.
|
|
2937
|
+
*/
|
|
2938
|
+
view: string;
|
|
2939
|
+
}
|
|
2940
|
+
/**
|
|
2941
|
+
* The client-space conversions of a page whose content box `box()` measures on screen when a
|
|
2942
|
+
* conversion runs: client pixels to box-local view pixels, then the transform undoes the turn
|
|
2943
|
+
* and the scale. `toPagePoint` and `toClientPoint` read the same live box, so they never drift.
|
|
2944
|
+
*/
|
|
2945
|
+
declare function pageClientSpace(transform: () => PageContextTransform, box: () => ClientBox): PageClientSpace;
|
|
2946
|
+
/**
|
|
2947
|
+
* Build a page context. `getRect` is the page's content box on screen (the turned content
|
|
2948
|
+
* element's bounding box), read when a conversion runs.
|
|
2949
|
+
*/
|
|
2950
|
+
declare function makePageContext<Transform extends PageContextTransform, Demand = never>(documentId: string, view: string, ref: PageRef, pageIndex: number, frame: PageFrameShape, transform: Transform, getRect: () => ClientBox, getViewDemand?: () => Demand): PageContext<Transform, Demand>;
|
|
2951
|
+
/**
|
|
2952
|
+
* A page context that reads every member through `current()`: the same object for a surface's
|
|
2953
|
+
* lifetime, current in what it answers. For an adapter whose layers keep the object they were
|
|
2954
|
+
* given once (a Svelte component reads `page.transform` in a template and follows the zoom).
|
|
2955
|
+
*/
|
|
2956
|
+
declare function livePageContext<Context extends PageContext<PageContextTransform, unknown>>(current: () => Context): Context;
|
|
2957
|
+
//#endregion
|
|
2958
|
+
//#region src/page-layers.d.ts
|
|
2959
|
+
/**
|
|
2960
|
+
* Which parts of a page the layers on it paint themselves. The annotation
|
|
2961
|
+
* layer paints the annotations, the form layer the form fields; while one is
|
|
2962
|
+
* on the page it says so here, and the page's picture (the render layer)
|
|
2963
|
+
* leaves that part out, so nothing is drawn twice and nobody passes a flag.
|
|
2964
|
+
*
|
|
2965
|
+
* Kept per page surface, by the page ref it hands its layers (`page.ref`):
|
|
2966
|
+
* each surface makes its own, and keeps it while it shows the page, through
|
|
2967
|
+
* zooms. Changes reach subscribers a microtask later, so a layer may say what
|
|
2968
|
+
* it paints from any point in its framework's lifecycle (React's insertion
|
|
2969
|
+
* effects included, which must not start updates); `painted()` is current at
|
|
2970
|
+
* once.
|
|
2971
|
+
*/
|
|
2972
|
+
/** A part of a page a layer can paint instead of the page's picture. */
|
|
2973
|
+
type PagePart = 'annotations' | 'formFields';
|
|
2974
|
+
/** Which parts the layers on one page paint. */
|
|
2975
|
+
interface PaintedParts {
|
|
2976
|
+
readonly annotations: boolean;
|
|
2977
|
+
readonly formFields: boolean;
|
|
2978
|
+
}
|
|
2979
|
+
/** One page's layers: which parts they paint. */
|
|
2980
|
+
interface PageLayers {
|
|
2981
|
+
/** Say this layer paints `part`, until the function it returns is called. */
|
|
2982
|
+
paint(part: PagePart): () => void;
|
|
2983
|
+
/** Which parts are painted now: the same object for the same answer. */
|
|
2984
|
+
painted(): PaintedParts;
|
|
2985
|
+
/** Hear when `painted()` changes. Returns the unsubscribe. */
|
|
2986
|
+
subscribe(listener: () => void): () => void;
|
|
2987
|
+
}
|
|
2988
|
+
/** The layers of one page surface, by the page ref it hands its layers. */
|
|
2989
|
+
declare function pageLayersOf(pageRef: object): PageLayers;
|
|
2990
|
+
/** The parts a render layer was told to draw (`true`) or leave out (`false`). */
|
|
2991
|
+
interface PicturePartProps {
|
|
2992
|
+
readonly annotations?: boolean;
|
|
2993
|
+
readonly formFields?: boolean;
|
|
2994
|
+
}
|
|
2995
|
+
/** What the user may read of each part (the render plugin's `getLayerRights()`). */
|
|
2996
|
+
interface PartRights {
|
|
2997
|
+
readonly annotations: boolean;
|
|
2998
|
+
readonly formFields: boolean;
|
|
2999
|
+
}
|
|
3000
|
+
/** The picture's layer options, as the render plugin takes them. */
|
|
3001
|
+
interface PictureLayerOptions {
|
|
3002
|
+
includeAnnotations: boolean;
|
|
3003
|
+
includeFormFields: boolean;
|
|
3004
|
+
}
|
|
3005
|
+
/**
|
|
3006
|
+
* What the page's picture draws, as the render plugin's layer options: a part
|
|
3007
|
+
* the props name is drawn or left out as they say; any other part is drawn
|
|
3008
|
+
* when no layer on the page paints it and the user may read it. Both are
|
|
3009
|
+
* always given, so a picture that leaves the annotations to a layer still
|
|
3010
|
+
* draws the form fields.
|
|
3011
|
+
*/
|
|
3012
|
+
declare function pictureLayerOptionsOf(painted: PaintedParts, props: PicturePartProps, may: PartRights): PictureLayerOptions;
|
|
3013
|
+
/**
|
|
3014
|
+
* The parts a picture draws that a layer on the page paints too, because the
|
|
3015
|
+
* props asked for them: drawn twice.
|
|
3016
|
+
*/
|
|
3017
|
+
declare function partsDrawnTwice(painted: PaintedParts, props: PicturePartProps): PagePart[];
|
|
3018
|
+
//#endregion
|
|
3019
|
+
//#region src/page-surface.d.ts
|
|
3020
|
+
/** A box in its parent's pixels. */
|
|
3021
|
+
interface SurfaceBox {
|
|
3022
|
+
left: number;
|
|
3023
|
+
top: number;
|
|
3024
|
+
width: number;
|
|
3025
|
+
height: number;
|
|
3026
|
+
}
|
|
3027
|
+
/** The transform members a surface is laid out from; `PageTransform` satisfies it. */
|
|
3028
|
+
interface SurfaceTransform {
|
|
3029
|
+
readonly rotation: 0 | 90 | 180 | 270;
|
|
3030
|
+
readonly viewWidth: number;
|
|
3031
|
+
readonly viewHeight: number;
|
|
3032
|
+
readonly contentWidth: number;
|
|
3033
|
+
readonly contentHeight: number;
|
|
3034
|
+
}
|
|
3035
|
+
/** The three boxes of a page surface. */
|
|
3036
|
+
interface PageSurfaceLayout {
|
|
3037
|
+
/** The footprint and the reserved bands, in the surface's parent; the page chrome fills it. */
|
|
3038
|
+
outer: SurfaceBox;
|
|
3039
|
+
/** The drop shadow at the footprint, in the outer box. */
|
|
3040
|
+
shadow: SurfaceBox;
|
|
3041
|
+
/** The page's content box in the outer box, before it turns; its layers draw in it. */
|
|
3042
|
+
content: SurfaceBox;
|
|
3043
|
+
/** The CSS transform that turns the content box about its centre, or null when it's upright. */
|
|
3044
|
+
turn: string | null;
|
|
3045
|
+
}
|
|
3046
|
+
/**
|
|
3047
|
+
* Lay out a page surface. `footprint` is where the page's footprint sits in the surface's
|
|
3048
|
+
* parent (a Stage page's device-snapped `screenX`/`screenY`); the outer box sits one band further
|
|
3049
|
+
* out, so the content keeps its place. Without it the outer box is at 0, 0 (a `PageView`, placed
|
|
3050
|
+
* by the page around it).
|
|
3051
|
+
*/
|
|
3052
|
+
declare function pageSurfaceLayout(transform: SurfaceTransform, frame: PageFrameShape, footprint?: {
|
|
3053
|
+
x: number;
|
|
3054
|
+
y: number;
|
|
3055
|
+
}): PageSurfaceLayout;
|
|
3056
|
+
/** What {@link stagePageDemand} reads from the Stage; `StageCapability` satisfies it. */
|
|
3057
|
+
interface StageDemandSource {
|
|
3058
|
+
listVisiblePages(): readonly {
|
|
3059
|
+
readonly ref: {
|
|
3060
|
+
readonly objectNumber: number;
|
|
3061
|
+
};
|
|
3062
|
+
readonly transform: {
|
|
3063
|
+
readonly deviceWidth: number;
|
|
3064
|
+
};
|
|
3065
|
+
readonly visibleRect: {
|
|
3066
|
+
x: number;
|
|
3067
|
+
y: number;
|
|
3068
|
+
width: number;
|
|
3069
|
+
height: number;
|
|
3070
|
+
};
|
|
3071
|
+
}[];
|
|
3072
|
+
}
|
|
3073
|
+
/** What a page's view wants rendered; the render plugin's `PageViewDemand` takes it. */
|
|
3074
|
+
interface StagePageDemand {
|
|
3075
|
+
desiredDeviceWidth: number;
|
|
3076
|
+
visibleRect: {
|
|
3077
|
+
x: number;
|
|
3078
|
+
y: number;
|
|
3079
|
+
width: number;
|
|
3080
|
+
height: number;
|
|
3081
|
+
};
|
|
3082
|
+
}
|
|
3083
|
+
/**
|
|
3084
|
+
* What a Stage page's view wants rendered, read live from the Stage when the render layer asks:
|
|
3085
|
+
* the page's visible part at its device width, or a zero box (want nothing) while the page is
|
|
3086
|
+
* off screen, at `offScreenDeviceWidth`. Visibility is the Stage's data, so no adapter derives
|
|
3087
|
+
* camera math or keeps a copy of it.
|
|
3088
|
+
*/
|
|
3089
|
+
declare function stagePageDemand(stage: StageDemandSource, pageObjectNumber: number, offScreenDeviceWidth: number): StagePageDemand;
|
|
3090
|
+
/** The page a `PageView` shows, as its document's page list has it. */
|
|
3091
|
+
interface PageViewPage {
|
|
3092
|
+
readonly size: {
|
|
3093
|
+
readonly width: number;
|
|
3094
|
+
readonly height: number;
|
|
3095
|
+
};
|
|
3096
|
+
readonly rotation: 0 | 90 | 180 | 270;
|
|
3097
|
+
readonly userUnit: number;
|
|
3098
|
+
}
|
|
3099
|
+
/** The input of `pageTransform()` (`@embedpdf/core-geometry`) for a `PageView`. */
|
|
3100
|
+
interface PageViewTransformInput {
|
|
3101
|
+
pageSize: {
|
|
3102
|
+
width: number;
|
|
3103
|
+
height: number;
|
|
3104
|
+
};
|
|
3105
|
+
rotation: 0 | 90 | 180 | 270;
|
|
3106
|
+
scale: number;
|
|
3107
|
+
baseScale: number;
|
|
3108
|
+
dpr: number;
|
|
3109
|
+
}
|
|
3110
|
+
/**
|
|
3111
|
+
* What a `PageView` builds its page transform from: no camera, so the scale (view pixels per
|
|
3112
|
+
* point) is `width` over the page's width. The base scale is physical 100% on the web, a point
|
|
3113
|
+
* at 96/72 CSS pixels times the page's /UserUnit, so `transform.zoom` still means something: a
|
|
3114
|
+
* thumbnail-sized page reads as zoomed out. Without a page yet, a 1 × 1 placeholder.
|
|
3115
|
+
*/
|
|
3116
|
+
declare function pageViewTransformInput(page: PageViewPage | null, width: number, dpr: number): PageViewTransformInput;
|
|
3117
|
+
//#endregion
|
|
3118
|
+
//#region src/page-pointer.d.ts
|
|
3119
|
+
interface PointerPoint {
|
|
3120
|
+
x: number;
|
|
3121
|
+
y: number;
|
|
3122
|
+
}
|
|
3123
|
+
/**
|
|
3124
|
+
* A multi-click counter. `pointerdown.detail` is 0 or 1 in several browsers, so clicks are
|
|
3125
|
+
* counted here from timing and distance: the standard double and triple click. Input is
|
|
3126
|
+
* normalized in the adapter; the hub and its handlers stay pure.
|
|
3127
|
+
*/
|
|
3128
|
+
declare function createClickCounter(maxGapMs?: number, maxDistancePx?: number): (now: number, x: number, y: number) => number;
|
|
3129
|
+
/** What the listener reads from the page context when an event arrives. */
|
|
3130
|
+
interface PagePointerPage {
|
|
3131
|
+
readonly ref: PageRef;
|
|
3132
|
+
readonly transform: {
|
|
3133
|
+
readonly viewScale: number;
|
|
3134
|
+
readonly rotation: 0 | 90 | 180 | 270;
|
|
3135
|
+
readonly zoom: number;
|
|
3136
|
+
};
|
|
3137
|
+
toPagePoint(clientX: number, clientY: number): PointerPoint;
|
|
3138
|
+
}
|
|
3139
|
+
/** The sample the listener hands the hub: structurally the interaction plugin's `PointerSample`. */
|
|
3140
|
+
interface PagePointerSample {
|
|
3141
|
+
phase: 'down' | 'move' | 'up';
|
|
3142
|
+
viewport: PointerPoint;
|
|
3143
|
+
page: {
|
|
3144
|
+
ref: PageRef;
|
|
3145
|
+
point: PointerPoint;
|
|
3146
|
+
scale: number;
|
|
3147
|
+
rotation: 0 | 90 | 180 | 270;
|
|
3148
|
+
zoom: number;
|
|
3149
|
+
};
|
|
3150
|
+
project: (page: PageRef) => PointerPoint | null;
|
|
3151
|
+
modifiers: {
|
|
3152
|
+
shift: boolean;
|
|
3153
|
+
alt: boolean;
|
|
3154
|
+
ctrl: boolean;
|
|
3155
|
+
meta: boolean;
|
|
3156
|
+
};
|
|
3157
|
+
clickCount: number;
|
|
3158
|
+
pointerType: 'mouse' | 'pen' | 'touch';
|
|
3159
|
+
}
|
|
3160
|
+
/** What the listener needs from the interaction hub; `InteractionHostCapability` satisfies it. */
|
|
3161
|
+
interface PagePointerHub {
|
|
3162
|
+
dispatchPointer(sample: PagePointerSample): void;
|
|
3163
|
+
}
|
|
3164
|
+
/**
|
|
3165
|
+
* Listen to the pointer on `element` for the page `page()` gives when an event arrives (a zoom
|
|
3166
|
+
* changes it, and a drag carries on through it), and dispatch every event to `hub`. A press
|
|
3167
|
+
* starts on the element; while it lasts the window listens, so a drag goes on outside the page.
|
|
3168
|
+
* Returns the function that stops listening.
|
|
3169
|
+
*/
|
|
3170
|
+
declare function attachPagePointer(element: HTMLElement, hub: PagePointerHub, page: () => PagePointerPage): () => void;
|
|
3171
|
+
//#endregion
|
|
3172
|
+
//#region src/scrollbar.d.ts
|
|
3173
|
+
/**
|
|
3174
|
+
* A Stage scrollbar's geometry and its press handling, shared by every framework's `Scrollbar`.
|
|
3175
|
+
*
|
|
3176
|
+
* The Stage gives its scroll position as a scrolling element has it (`scrollTop`,
|
|
3177
|
+
* `scrollHeight`, `clientHeight` and their horizontal twins, in screen pixels). From that and the
|
|
3178
|
+
* measured track this module draws the thumb, and turns presses into Stage calls the way a native
|
|
3179
|
+
* bar does: a thumb drag keeps the point it grabbed under the pointer, and a press on the track
|
|
3180
|
+
* pages toward the pointer, repeating while held and stopping when the thumb reaches it. A drag
|
|
3181
|
+
* is frozen at the press (grab point, travel, range) and applied as relative pans: absolute in
|
|
3182
|
+
* feel on a bounded Stage, and steady on an unbounded one, whose range moves under the pointer.
|
|
3183
|
+
*
|
|
3184
|
+
* The adapters keep their reactive glue: the track's size, auto-hide, hover and the markup.
|
|
3185
|
+
*/
|
|
3186
|
+
/** The scroll position a Stage reports (`ScrollMetrics` from the stage plugin satisfies it). */
|
|
3187
|
+
interface ScrollbarMetrics {
|
|
3188
|
+
readonly scrollLeft: number;
|
|
3189
|
+
readonly scrollTop: number;
|
|
3190
|
+
readonly scrollWidth: number;
|
|
3191
|
+
readonly scrollHeight: number;
|
|
3192
|
+
readonly clientWidth: number;
|
|
3193
|
+
readonly clientHeight: number;
|
|
3194
|
+
}
|
|
3195
|
+
/** The bar along one axis, in track pixels. */
|
|
3196
|
+
interface ScrollbarLayout {
|
|
3197
|
+
/** The view's length along the axis. */
|
|
3198
|
+
client: number;
|
|
3199
|
+
/** How far the view is scrolled. */
|
|
3200
|
+
offset: number;
|
|
3201
|
+
/** The farthest it can scroll. */
|
|
3202
|
+
maxOffset: number;
|
|
3203
|
+
thumbLength: number;
|
|
3204
|
+
/** How far the thumb can move along the track. */
|
|
3205
|
+
travel: number;
|
|
3206
|
+
thumbPosition: number;
|
|
3207
|
+
}
|
|
3208
|
+
/**
|
|
3209
|
+
* The thumb from the metrics and the track's length: one formula for drawing, dragging and
|
|
3210
|
+
* paging, so they never disagree. The thumb never gets shorter than `minThumbSize`, and its
|
|
3211
|
+
* position stays proportional over the travel that leaves.
|
|
3212
|
+
*/
|
|
3213
|
+
declare function scrollbarLayout(metrics: ScrollbarMetrics, vertical: boolean, trackPx: number, minThumbSize: number): ScrollbarLayout;
|
|
3214
|
+
/** The Stage calls a scrollbar makes; `StageCapability` satisfies it. */
|
|
3215
|
+
interface ScrollbarStage {
|
|
3216
|
+
scrollTo(position: {
|
|
3217
|
+
top?: number;
|
|
3218
|
+
left?: number;
|
|
3219
|
+
}): void;
|
|
3220
|
+
scrollBy(delta: {
|
|
3221
|
+
top?: number;
|
|
3222
|
+
left?: number;
|
|
3223
|
+
}): void;
|
|
3224
|
+
panBy(dx: number, dy: number): void;
|
|
3225
|
+
}
|
|
3226
|
+
/** The bar as it is at a press: what the press handlers read. */
|
|
3227
|
+
interface ScrollbarTrack {
|
|
3228
|
+
readonly stage: ScrollbarStage;
|
|
3229
|
+
readonly vertical: boolean;
|
|
3230
|
+
/** The track element: pointer positions are measured from its start. */
|
|
3231
|
+
readonly element: Element;
|
|
3232
|
+
/** The layout drawn now. */
|
|
3233
|
+
readonly layout: ScrollbarLayout;
|
|
3234
|
+
/** The layout from the Stage's metrics as they are now, for each paging step. */
|
|
3235
|
+
liveLayout(): ScrollbarLayout;
|
|
3236
|
+
}
|
|
3237
|
+
/**
|
|
3238
|
+
* The pointer event a press handler reads: a DOM `PointerEvent`, or a framework's own event
|
|
3239
|
+
* with the same members (React's), so `stopPropagation` and `currentTarget` mean what the
|
|
3240
|
+
* framework's handlers mean.
|
|
3241
|
+
*/
|
|
3242
|
+
interface ScrollbarPointerEvent {
|
|
3243
|
+
readonly button: number;
|
|
3244
|
+
readonly pointerId: number;
|
|
3245
|
+
readonly clientX: number;
|
|
3246
|
+
readonly clientY: number;
|
|
3247
|
+
readonly target: EventTarget | null;
|
|
3248
|
+
readonly currentTarget: EventTarget | null;
|
|
3249
|
+
preventDefault(): void;
|
|
3250
|
+
stopPropagation(): void;
|
|
3251
|
+
}
|
|
3252
|
+
/** A scrollbar's presses: wire the thumb's and the track's pointer events to these. */
|
|
3253
|
+
interface ScrollbarPresses {
|
|
3254
|
+
/** A press on the thumb starts a drag. */
|
|
3255
|
+
pressThumb(event: ScrollbarPointerEvent, track: ScrollbarTrack): void;
|
|
3256
|
+
/**
|
|
3257
|
+
* A press on the track itself: `'page'` steps 90% of a view toward the pointer, repeats while
|
|
3258
|
+
* held and stops at the pointer; `'jump'` puts the thumb under the pointer and goes on as a
|
|
3259
|
+
* drag. A press that reached the track from the thumb is the thumb's.
|
|
3260
|
+
*/
|
|
3261
|
+
pressTrack(event: ScrollbarPointerEvent, track: ScrollbarTrack, mode: 'page' | 'jump'): void;
|
|
3262
|
+
/** A pointer move on the track (pointer capture sends them there): drags, and paging's target. */
|
|
3263
|
+
move(event: ScrollbarPointerEvent, track: ScrollbarTrack): void;
|
|
3264
|
+
/** The press ended: no drag, no repeat. Also call it when the bar goes away. */
|
|
3265
|
+
release(): void;
|
|
3266
|
+
}
|
|
3267
|
+
/**
|
|
3268
|
+
* One scrollbar's press handling. `onDragging` hears when a drag starts and ends, for the bar's
|
|
3269
|
+
* `data-dragging` and to keep it shown.
|
|
3270
|
+
*/
|
|
3271
|
+
declare function createScrollbarPresses(onDragging: (dragging: boolean) => void): ScrollbarPresses;
|
|
3272
|
+
//#endregion
|
|
3273
|
+
//#region src/orientation.d.ts
|
|
3274
|
+
/**
|
|
3275
|
+
* Which way a row of controls runs, and which way its text reads: what a
|
|
3276
|
+
* toolbar measures along, and what its arrow keys move along.
|
|
3277
|
+
*/
|
|
3278
|
+
/** A row of controls side by side, or one under another (`aria-orientation`'s values). */
|
|
3279
|
+
type Orientation = 'horizontal' | 'vertical';
|
|
3280
|
+
/** The writing direction an element lays out in: its computed CSS `direction`. */
|
|
3281
|
+
declare function directionOf(element: Element): 'ltr' | 'rtl';
|
|
3282
|
+
//#endregion
|
|
3283
|
+
//#region src/toolbar-measure.d.ts
|
|
3284
|
+
/** The keys the measurement layer reports lengths under, the ones the metrics look up. */
|
|
3285
|
+
declare const toolbarMeasureKey: {
|
|
3286
|
+
/** A unit (`NormalizedUnit.key`) at one variant. */
|
|
3287
|
+
readonly unit: (unitKey: string, variant: string) => string;
|
|
3288
|
+
/** A group in its collapsed form. */
|
|
3289
|
+
readonly group: (groupId: string) => string;
|
|
3290
|
+
/** A shed group's disclosure trigger, measured with the whole group behind it. */
|
|
3291
|
+
readonly groupTrigger: (groupId: string) => string;
|
|
3292
|
+
/** The "More" button. */
|
|
3293
|
+
readonly overflowTrigger: "t:";
|
|
3294
|
+
};
|
|
3295
|
+
/** The lengths a fit needs: the structural twin of core-ui's `FitMetrics`. */
|
|
3296
|
+
interface ToolbarFitMetrics {
|
|
3297
|
+
unit(key: string, variant: string): number | undefined;
|
|
3298
|
+
groupCollapsed(groupId: string): number | undefined;
|
|
3299
|
+
groupTrigger(groupId: string): number | undefined;
|
|
3300
|
+
readonly overflowTrigger: number;
|
|
3301
|
+
readonly gap: number;
|
|
3302
|
+
readonly separator: number;
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* The measured lengths of one toolbar, kept apart per orientation: a toolbar
|
|
3306
|
+
* turned on its side never fits with the other axis's numbers.
|
|
3307
|
+
*/
|
|
3308
|
+
interface ToolbarLengths {
|
|
3309
|
+
/**
|
|
3310
|
+
* A measured element's length along `orientation`, under its
|
|
3311
|
+
* {@link toolbarMeasureKey}. True when it changed by more than half a pixel:
|
|
3312
|
+
* render (and solve) again.
|
|
3313
|
+
*/
|
|
3314
|
+
report(orientation: Orientation, key: string, length: number): boolean;
|
|
3315
|
+
/**
|
|
3316
|
+
* The lengths along `orientation` as fit metrics, for items `gap` px apart
|
|
3317
|
+
* and separators `separatorWidth` px thick (a separator's width is its
|
|
3318
|
+
* thickness, across a horizontal bar or down a vertical one). A separator is
|
|
3319
|
+
* one more flex child: its thickness plus one gap. Until the "More" button
|
|
3320
|
+
* is measured it counts as 32 px.
|
|
3321
|
+
*/
|
|
3322
|
+
metrics(orientation: Orientation, gap: number, separatorWidth: number): ToolbarFitMetrics;
|
|
3323
|
+
}
|
|
3324
|
+
declare function createToolbarLengths(): ToolbarLengths;
|
|
3325
|
+
/**
|
|
3326
|
+
* Report an element's width (its border box) now and whenever it resizes. Put
|
|
3327
|
+
* it on every element of a horizontal toolbar's measurement layer, and on a
|
|
3328
|
+
* custom slot's `<slot>` socket, which is measured live where it renders.
|
|
3329
|
+
* Returns the detach.
|
|
3330
|
+
*/
|
|
3331
|
+
declare function observeWidth(element: Element, onWidth: (width: number) => void): () => void;
|
|
3332
|
+
/** {@link observeWidth} for a vertical toolbar: an element's border-box height. */
|
|
3333
|
+
declare function observeHeight(element: Element, onHeight: (height: number) => void): () => void;
|
|
3334
|
+
/** An element's length along a toolbar: {@link observeWidth} or {@link observeHeight}. */
|
|
3335
|
+
declare function observeLength(element: Element, orientation: Orientation, onLength: (length: number) => void): () => void;
|
|
3336
|
+
/**
|
|
3337
|
+
* Report the width a toolbar has to fill (its content box) now and whenever
|
|
3338
|
+
* it changes by more than half a pixel. Returns the detach.
|
|
3339
|
+
*/
|
|
3340
|
+
declare function observeContentWidth(element: HTMLElement, onWidth: (width: number) => void): () => void;
|
|
3341
|
+
/**
|
|
3342
|
+
* The height a vertical toolbar has to fill, like {@link observeContentWidth}.
|
|
3343
|
+
* The toolbar fits the height it's given, so its container needs one.
|
|
3344
|
+
*/
|
|
3345
|
+
declare function observeContentHeight(element: HTMLElement, onHeight: (height: number) => void): () => void;
|
|
3346
|
+
/** The room along a toolbar: {@link observeContentWidth} or {@link observeContentHeight}. */
|
|
3347
|
+
declare function observeContentLength(element: HTMLElement, orientation: Orientation, onLength: (length: number) => void): () => void;
|
|
3348
|
+
//#endregion
|
|
3349
|
+
//#region src/focusable.d.ts
|
|
3350
|
+
/**
|
|
3351
|
+
* Which elements take keyboard focus, for the keyboard models (a toolbar's
|
|
3352
|
+
* stops, a menu's items, a dialog's tab order). Decided from the markup only,
|
|
3353
|
+
* never from layout, so it answers the same before the first paint: `hidden`,
|
|
3354
|
+
* `inert` and `disabled` count; a `display: none` from a stylesheet doesn't.
|
|
3355
|
+
*/
|
|
3356
|
+
/** Whether an element can take focus now: focusable markup, not disabled, not hidden or inert. */
|
|
3357
|
+
declare function canTakeFocus(element: Element): boolean;
|
|
3358
|
+
/** Whether Tab stops at an element: it takes focus and its `tabIndex` isn't negative. */
|
|
3359
|
+
declare function isTabbable(element: Element): element is HTMLElement;
|
|
3360
|
+
/**
|
|
3361
|
+
* The elements inside `root` that can take focus, in the order they show: through a `<slot>`,
|
|
3362
|
+
* the page's elements the browser shows there (a web component's slotted children).
|
|
3363
|
+
*/
|
|
3364
|
+
declare function focusablesIn(root: ParentNode): HTMLElement[];
|
|
3365
|
+
/** The elements inside `root` that Tab stops at, in document order. */
|
|
3366
|
+
declare function tabbablesIn(root: ParentNode): HTMLElement[];
|
|
3367
|
+
/**
|
|
3368
|
+
* The element that has focus, looking into shadow roots: the document's
|
|
3369
|
+
* `activeElement` is only the outermost shadow host. Null when nothing has
|
|
3370
|
+
* focus (the body).
|
|
3371
|
+
*/
|
|
3372
|
+
declare function deepActiveElementOf(doc: Document): Element | null;
|
|
3373
|
+
/**
|
|
3374
|
+
* Whether the element with focus is `container` or inside it, as the page shows it: through
|
|
3375
|
+
* shadow roots, and from an element slotted into a shadow root to its slot, so a control
|
|
3376
|
+
* slotted into a viewer counts as inside the viewer, as its keys do.
|
|
3377
|
+
*/
|
|
3378
|
+
declare function containsFocus(container: Element): boolean;
|
|
3379
|
+
/**
|
|
3380
|
+
* Whether a control says it can't be used now, through `disabled` or
|
|
3381
|
+
* `aria-disabled="true"`: the keyboard models pass over it.
|
|
3382
|
+
*/
|
|
3383
|
+
declare function isUnavailable(element: Element): boolean;
|
|
3384
|
+
/**
|
|
3385
|
+
* Whether a focused control uses `key` itself, so a keyboard model around it
|
|
3386
|
+
* must leave the key alone: a text field moves its caret with Left, Right,
|
|
3387
|
+
* Home and End; a select changes with Up and Down; a slider takes them all.
|
|
3388
|
+
*/
|
|
3389
|
+
declare function usesKey(element: Element, key: string): boolean;
|
|
3390
|
+
//#endregion
|
|
3391
|
+
//#region src/roving-focus.d.ts
|
|
3392
|
+
/** Where a key moves focus in a row. */
|
|
3393
|
+
type RovingMove = 'next' | 'previous' | 'first' | 'last';
|
|
3394
|
+
/** The move `key` asks for in a row running `orientation`, or null for a key the row leaves alone. */
|
|
3395
|
+
declare function rovingMoveOf(key: string, orientation: Orientation, direction: 'ltr' | 'rtl'): RovingMove | null;
|
|
3396
|
+
/**
|
|
3397
|
+
* The index `move` lands on among `count` stops, from `current` (-1 for
|
|
3398
|
+
* none), passing over the stops `available` rejects. With `loop`, next and
|
|
3399
|
+
* previous wrap around the ends; without it they stop there. -1 when there is
|
|
3400
|
+
* nowhere to go.
|
|
3401
|
+
*/
|
|
3402
|
+
declare function rovingTargetOf(move: RovingMove, current: number, count: number, available: (index: number) => boolean, loop: boolean): number;
|
|
3403
|
+
interface RovingFocusOptions {
|
|
3404
|
+
/** Which arrows move: Left and Right for `'horizontal'`, Up and Down for `'vertical'`. */
|
|
3405
|
+
readonly orientation: Orientation;
|
|
3406
|
+
/** The stops, in order; read again on every key and every {@link RovingFocus.refresh}. */
|
|
3407
|
+
readonly stops: () => readonly HTMLElement[];
|
|
3408
|
+
/** The writing direction. Default: the container's computed `direction`, read on each key. */
|
|
3409
|
+
readonly direction?: () => 'ltr' | 'rtl';
|
|
3410
|
+
/** Whether next and previous wrap around at the ends. Default true. */
|
|
3411
|
+
readonly loop?: boolean;
|
|
3412
|
+
}
|
|
3413
|
+
/** A row's roving focus, from {@link attachRovingFocus}. */
|
|
3414
|
+
interface RovingFocus {
|
|
3415
|
+
/**
|
|
3416
|
+
* Put the one tab stop back after the stops changed: on the stop that had
|
|
3417
|
+
* focus last while it's still there and usable, else on the first usable
|
|
3418
|
+
* one. Call it after every render that can add, remove or disable a stop.
|
|
3419
|
+
*/
|
|
3420
|
+
refresh(): void;
|
|
3421
|
+
/** Stop handling keys and focus. The stops keep their `tabIndex`. */
|
|
3422
|
+
detach(): void;
|
|
3423
|
+
}
|
|
3424
|
+
/**
|
|
3425
|
+
* Make the stops of `container` one tab stop with arrow keys between them.
|
|
3426
|
+
* Keys count only while a stop itself has focus, so keys inside a menu or
|
|
3427
|
+
* another control the row holds are theirs; a key with Alt, Control, Meta or
|
|
3428
|
+
* Shift, or one a handler already took (`defaultPrevented`), is left alone.
|
|
3429
|
+
*/
|
|
3430
|
+
declare function attachRovingFocus(container: HTMLElement, options: RovingFocusOptions): RovingFocus;
|
|
3431
|
+
//#endregion
|
|
3432
|
+
//#region src/toolbar-focus.d.ts
|
|
3433
|
+
/** The attribute on the element around each item of a toolbar's live row. */
|
|
3434
|
+
declare const TOOLBAR_ITEM_ATTRIBUTE = "data-epdf-toolbar-item";
|
|
3435
|
+
/**
|
|
3436
|
+
* A toolbar's stops: the first element of each item that takes focus, in
|
|
3437
|
+
* order. A menu an item holds open is not part of its stop.
|
|
3438
|
+
*/
|
|
3439
|
+
declare function toolbarStopsOf(toolbar: ParentNode): HTMLElement[];
|
|
3440
|
+
/** Arrow keys between a toolbar's items, along its orientation; `refresh()` after each render. */
|
|
3441
|
+
declare function attachToolbarFocus(toolbar: HTMLElement, orientation: Orientation): RovingFocus;
|
|
3442
|
+
//#endregion
|
|
3443
|
+
//#region src/menu-keys.d.ts
|
|
3444
|
+
/**
|
|
3445
|
+
* The item typeahead lands on: the first one from `current` on, wrapping, that
|
|
3446
|
+
* is available and whose label starts with `query` (any case). A one-letter
|
|
3447
|
+
* query starts after `current`, so typing the same letter again moves on, and
|
|
3448
|
+
* a query of one letter repeated ("ppp") cycles like that letter. -1 when no
|
|
3449
|
+
* item matches.
|
|
3450
|
+
*/
|
|
3451
|
+
declare function typeaheadMatchOf(labels: readonly string[], current: number, query: string, available: (index: number) => boolean): number;
|
|
3452
|
+
/**
|
|
3453
|
+
* The words typeahead matches an item by: its `aria-label`, else its text,
|
|
3454
|
+
* without the marks a row may start with (a bullet, a check, an icon glyph).
|
|
3455
|
+
*/
|
|
3456
|
+
declare function menuItemLabelOf(item: Element): string;
|
|
3457
|
+
interface MenuKeysOptions {
|
|
3458
|
+
/** The button that opened the menu: it says it's expanded, and gets focus back. */
|
|
3459
|
+
readonly trigger: HTMLElement | null;
|
|
3460
|
+
/** Close the menu; removing it is the caller's. */
|
|
3461
|
+
readonly close: () => void;
|
|
3462
|
+
/** The items, in order. Default: the menu's `menuitem`, `menuitemradio` and `menuitemcheckbox` elements. */
|
|
3463
|
+
readonly items?: () => readonly HTMLElement[];
|
|
3464
|
+
/** Which item takes focus when the menu opens. Default `'first'`. */
|
|
3465
|
+
readonly initialFocus?: 'first' | 'last' | 'none';
|
|
3466
|
+
}
|
|
3467
|
+
/**
|
|
3468
|
+
* Drive an open `menu` from the keyboard until the returned detach runs.
|
|
3469
|
+
* Detaching (the menu closed) gives focus back to the trigger when focus was
|
|
3470
|
+
* in the menu or went nowhere, and never when the user moved it elsewhere.
|
|
3471
|
+
*/
|
|
3472
|
+
declare function attachMenuKeys(menu: HTMLElement, options: MenuKeysOptions): () => void;
|
|
3473
|
+
//#endregion
|
|
3474
|
+
//#region src/focus-trap.d.ts
|
|
3475
|
+
/**
|
|
3476
|
+
* Move focus into `container` unless it's there already: to `initialFocus`, else its first
|
|
3477
|
+
* control Tab stops at, else the container itself. Focus already inside stays where it is, so a
|
|
3478
|
+
* control that took focus as it appeared (a search field asking for the cursor) keeps it.
|
|
3479
|
+
*/
|
|
3480
|
+
declare function moveFocusInto(container: HTMLElement, initialFocus?: HTMLElement | null): void;
|
|
3481
|
+
interface FocusTrapOptions {
|
|
3482
|
+
/**
|
|
3483
|
+
* What takes focus when the trap starts, unless focus is inside already. Default: the first
|
|
3484
|
+
* control Tab stops at.
|
|
3485
|
+
*/
|
|
3486
|
+
readonly initialFocus?: HTMLElement | null;
|
|
3487
|
+
/** Whether focus goes back to where it was when the trap is released. Default true. */
|
|
3488
|
+
readonly returnFocus?: boolean;
|
|
3489
|
+
}
|
|
3490
|
+
/** Trap focus in `container` until the returned release runs. */
|
|
3491
|
+
declare function attachFocusTrap(container: HTMLElement, options?: FocusTrapOptions): () => void;
|
|
3492
|
+
//#endregion
|
|
3493
|
+
//#region src/surface-focus.d.ts
|
|
3494
|
+
/**
|
|
3495
|
+
* Putting the cursor in a panel when it asks. The shell raises a surface's `focusRequest` on
|
|
3496
|
+
* every `open(id, { focus: true })` and clears it when the surface closes; the element that
|
|
3497
|
+
* follows it takes focus whenever the request changes to a new value above 0, and when it starts
|
|
3498
|
+
* following while the request is up (the panel opened, or its code loaded, because of it). The
|
|
3499
|
+
* adapters' surface-focus hooks bind a follower to their reactivity; the rule lives here.
|
|
3500
|
+
*/
|
|
3501
|
+
/** How an element takes focus when its surface asks. */
|
|
3502
|
+
interface SurfaceFocusOptions {
|
|
3503
|
+
/** Select the text of an input or a text area as it takes focus, so typing replaces it. */
|
|
3504
|
+
readonly select?: boolean;
|
|
3505
|
+
}
|
|
3506
|
+
/** One element following one surface's focus requests. */
|
|
3507
|
+
interface SurfaceFocusFollower {
|
|
3508
|
+
/**
|
|
3509
|
+
* Take the surface's request as it is now. `shell` is the capability it was read from (null
|
|
3510
|
+
* without a document): another document's shell starts over, as a new mount does. Without an
|
|
3511
|
+
* element yet, a request waits for it.
|
|
3512
|
+
*/
|
|
3513
|
+
follow(element: HTMLElement | null, shell: object | null, request: number, options?: SurfaceFocusOptions): void;
|
|
3514
|
+
}
|
|
3515
|
+
declare function createSurfaceFocusFollower(): SurfaceFocusFollower;
|
|
3516
|
+
//#endregion
|
|
3517
|
+
//#region src/standard-commands-platform.d.ts
|
|
3518
|
+
/** What the standard commands need from the browser: the structural twin of `StandardCommandsPlatform`. */
|
|
3519
|
+
interface StandardCommandsBrowser {
|
|
3520
|
+
copySelection: typeof copySelection;
|
|
3521
|
+
saveFile(bytes: Uint8Array, fileName: string): void;
|
|
3522
|
+
print(): void;
|
|
3523
|
+
}
|
|
3524
|
+
declare const standardCommandsBrowser: StandardCommandsBrowser;
|
|
3525
|
+
//#endregion
|
|
3526
|
+
export { type ActionsUiAdapterShape, type ActionsUiEffectContext, type ActionsUiOrigin, type AnchorTarget, type AnchoredFit, type AnchoredOptions, type AnchoredPlacement, type AnchoredPoint, type AnchoredPosition, type AnchoredRect, type AnchoredSide, type AnchoredSize, type AnnotationAnchorShape, type AnnotationChromePaint, type AnnotationDrawing, type AnnotationLookFrame, type AppearancePicture, type AppearanceUrl, type AttachSelectionHandleOptions, type BehaviorRendererEntry, type ByteStore, type ChromeInPixels, type ChromeLine, type ChromeLinePaint, type ChromeNodeShape, type ChromePaintSettings, type ChromeShapePaint, type ClickDetector, type ClientBox, type ClientProjectedPage, type ClipboardSelectionSource, type CommandShortcutOptions, type CommentPageLayout, type CommentThreadPage, type CreationDraftAnchorShape, type CssFont, type DefaultActionsUiAdapterOptions, EPDF_VARIABLES, type EditorDocumentFactory, type EditorElement, type EditorNode, type EditorPosition, type EditorRoot, type EditorStyle, type EpdfCssOnlyVariable, type EpdfFollowedVariable, type EpdfSettingVariable, type EpdfTheme, type EpdfThemeVariables, type EpdfTranslucentVariable, type EpdfVariable, type EpdfVariableDefinition, FORM_CONTROL_FILL, type FieldLook, type FieldTextStyle, type FilePickerPort, type FocusTrapOptions, type FormColorSettings, type FormColors, type FormControlFill, type FormFocusRingStyle, type FrameBox, type FrameFraction, type FramePixels, type IndexedDbByteStoreOptions, type LineModel, type LinkActionDispatcher, type LinkActionSource, type LinkAnchor, type LinkAnchorEvent, type LinkAnchorShape, type LinkEventShape, type LinkHoverPump, type ListBoxControlStyle, type ListBoxStyle, type LookRendererEntry, type LookState, type MenuKeysOptions, type MountableFontProgram, type ObjectUrl, type ObjectUrlImageSource, type OptimisticSelection, type Orientation, type PageBoundsAnchor, type PageClientSpace, type PageContext, type PageContextTransform, type PageFrameShape, type PageLayerTransform, type PageLayers, type PagePart, type PagePoint, type PagePointerHub, type PagePointerPage, type PagePointerSample, type PageQuad, type PageRef, type PageSurfaceLayout, type PageToPixels, type PageViewEnv, type PageViewPage, type PageViewTransformInput, type PaintedImageCallbacks, type PaintedParts, type PartRights, type PickFileOptions, type PictureBytes, type PictureLayerOptions, type PictureOrPainting, type PicturePartProps, type PixelBox, type PixelRect, type ProjectedTransform, type RendererBehaviorRegistry, type RendererEntry, type RendererInteractiveContext, type RichTextEditorAlign, type RichTextEditorBinding, type RichTextEditorCommand, type RichTextEditorDecoration, type RichTextEditorDocument, type RichTextEditorHost, type RichTextEditorParagraph, type RichTextEditorProps, type RichTextEditorRange, type RichTextEditorRun, type RichTextEditorScript, type RichTextEditorStyle, type RotationAnchorShape, type RovingFocus, type RovingFocusOptions, type RovingMove, type ScenePaint, type SceneShapeNode, type ScrollbarLayout, type ScrollbarMetrics, type ScrollbarPointerEvent, type ScrollbarPresses, type ScrollbarStage, type ScrollbarTrack, type SearchHighlightOptions, type SearchHighlightPiece, type SearchHitShape, type SelectOptions, type SelectionAnchorShape, type SelectionClipboardOptions, type SelectionEndpointShape, type SelectionEndpointsShape, type SelectionHandleSession, type ShortcutCommands, type ShortcutRefusal, type ShownUrls, type StageDemandSource, type StageGestureHost, type StageGestureOptions, type StageGestureSink, type StagePageDemand, type StagePointerKind, type StageProjection, type StageSurfaceHost, type StageSurfaceHub, type StageSurfaceOptions, type StageSurfaceSample, type StageWheelSample, type StandardCommandsBrowser, type StyleRecord, type SurfaceBox, type SurfaceFocusFollower, type SurfaceFocusOptions, type SurfaceTransform, type SvgCursorOptions, type SvgShape, type SvgShapeTag, type SvgShapesOptions, TOOLBAR_ITEM_ATTRIBUTE, type TextBoxCss, type TextBoxEditor, type TextBoxEditorAnnotation, type TextBoxEditorFollower, type TextBoxEditorItem, type TextBoxStyle, type TextEditorLayout, type TextFieldDrafts, type TextFieldEditor, type TextFieldEditorState, type TextFieldEditorStyle, type TextFieldStyle, type TextPlatePixels, type ToggleForm, type ToolCursorImage, type ToolCursorSpec, type ToolbarFitMetrics, type ToolbarLengths, type TurnedBox, type ViewProjector, type WebClock, type WebFontMetrics, type WebPlatformFeedback, type WheelSample, type WidgetBoxStyle, type WidgetEventKind, anchoredViewOf, annotationChromePaint, annotationDrawingOf, applyFirstLineShift, attachFocusTrap, attachMenuKeys, attachPagePointer, attachRichTextEditor, attachRovingFocus, attachSelectionHandle, attachTextBoxEditor, attachToolbarFocus, bakedAppearanceOf, bindCommandShortcuts, bindPaintedImage, bindWidgetEvents, browserClock, canTakeFocus, chromeInPixels, clientPageProjector, computeReleaseVelocity, containsFocus, copySelection, createClickCounter, createClickDetector, createDefaultActionsUiAdapter, createFontMounts, createOptimisticSelection, createScrollbarPresses, createShownUrls, createStageGestureController, createStageSurface, createSurfaceFocusFollower, createTextBoxEditorFollower, createTextFieldEditor, createToolbarLengths, cssFontOf, cssText, deepActiveElementOf, directionOf, editingTextKeyOf, enrichCommentThreads, epdfThemeVariables, firstLineShiftFor, fitAnchoredRect, focusablesIn, fontProgramsOf, formColorsOf, formFocusRingStyleOf, frameInPixels, ghostOpacity, hoverLink, indexedDbByteStore, installFilePickerProvider, isMacPlatform, isModifiedClick, isTabbable, isUnavailable, isUprightQuad, isolatePointerDown, isolateWheel, layerTextBoxesOf, lineModelFor, linkActivateContextOf, linkAnchorOf, linkHrefOf, listBoxControlStyleOf, listBoxStyleOf, livePageContext, loadAppearanceUrls, loadObjectUrl, lookFrameOf, lookRendererFor, makePageContext, menuItemLabelOf, mixAccent, mountFontProgram, mountWebFont, moveFocusInto, navigableLinksOf, objectUrlOf, observeAnchoredFit, observeClientGeometry, observeContentHeight, observeContentLength, observeContentWidth, observeHeight, observeLength, observeOutsidePress, observeWidth, offsetOfPosition, openExternalUri, pageClientSpace, pageLayersOf, pageSurfaceLayout, pageViewTransformInput, paint, paintDefault, partsDrawnTwice, pickFile, pickImageFile, pickRequestedFile, pictureLayerOptionsOf, pictureOrPainting, positionAnchoredRect, positionOfOffset, pressToggle, projectAnchoredTarget, quadInPixels, rasterInFrame, rectInPixels, registerRendererBehaviors, renderRichText, rendererBehaviorId, rovingMoveOf, rovingTargetOf, sameAnchoredFit, sameAnnotationAnchor, sameCreationDraftAnchor, samePageBounds, sameRotationAnchor, sameSelectionAnchor, sameSelectionEndpoints, sanitizeExternalUri, saveFile, sceneViewBox, scrollbarLayout, searchHighlightsOf, sendLinkEvent, serializeRichText, showSelectedOptions, shownAppearance, stagePageDemand, stageViewProjector, standardCommandsBrowser, styleDeltaOf, svgCursor, svgPoints, svgShapesOf, tabbablesIn, textBoxEditorScaleOf, textBoxStyleOf, textFieldEditorStyleOf, textFieldStyleOf, textPlateInPixels, toolCursorsOf, toolbarMeasureKey, toolbarStopsOf, typeaheadMatchOf, usesKey, vibrationFeedback, webFontMetrics, wheelZoomFactor, widgetBoxStyleOf, wireSelectionClipboard, wkFeedback };
|
|
852
3527
|
//# sourceMappingURL=index.d.ts.map
|