@embedpdf/web 3.0.0-next.1 → 3.0.0-next.10
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 +978 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +499 -1
- package/dist/index.d.ts +499 -1
- package/dist/index.js +966 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -16,6 +16,163 @@ declare const pickFile: (options?: PickFileOptions) => Promise<File | null>;
|
|
|
16
16
|
*/
|
|
17
17
|
declare function saveFile(bytes: Uint8Array | Blob, name: string, mimeType?: string): void;
|
|
18
18
|
//#endregion
|
|
19
|
+
//#region src/clipboard.d.ts
|
|
20
|
+
/**
|
|
21
|
+
* Clipboard wiring for text selection — the environmental half of copy.
|
|
22
|
+
*
|
|
23
|
+
* The selection plugin is deliberately DOM-free: its public capability ends
|
|
24
|
+
* at `readText()` (data). Everything that touches `navigator.clipboard` or
|
|
25
|
+
* the native `copy` event lives HERE, structurally typed so this module
|
|
26
|
+
* stays a pure DOM utility with no EmbedPDF dependencies (the selection
|
|
27
|
+
* capability satisfies {@link ClipboardSelectionSource} as-is).
|
|
28
|
+
*/
|
|
29
|
+
/** The slice of the selection capability clipboard wiring needs. */
|
|
30
|
+
interface ClipboardSelectionSource {
|
|
31
|
+
hasSelection(): boolean;
|
|
32
|
+
canCopy(): boolean;
|
|
33
|
+
readText(): Promise<string>;
|
|
34
|
+
onChange(cb: () => void): () => void;
|
|
35
|
+
onCommit(cb: () => void): () => void;
|
|
36
|
+
}
|
|
37
|
+
interface SelectionClipboardOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Prefetch the selected text when the selection settles (default true).
|
|
40
|
+
* This is what makes the NATIVE copy path work: a `copy` event handler
|
|
41
|
+
* must call `clipboardData.setData` synchronously — awaiting a page-text
|
|
42
|
+
* read inside it is too late — and it also keeps the async path instant.
|
|
43
|
+
* The fetch is one versioned, cached, permission-gated read per page;
|
|
44
|
+
* pass false to make copying strictly on-demand.
|
|
45
|
+
*/
|
|
46
|
+
prefetch?: boolean;
|
|
47
|
+
/** Event target to listen on. Defaults to `document`. */
|
|
48
|
+
target?: Document;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Wire clipboard copy for a selection. Two delivery paths, both fed by the
|
|
52
|
+
* prefetched text:
|
|
53
|
+
*
|
|
54
|
+
* - the native `copy` event (menu Edit→Copy, or ctrl/cmd+C while the page
|
|
55
|
+
* has a DOM selection or focused editable — e.g. the viewer shell's
|
|
56
|
+
* focus sink): answered SYNCHRONOUSLY from the cache;
|
|
57
|
+
* - ctrl/cmd+C with no DOM selection (canvas-rendered viewers usually
|
|
58
|
+
* have none, and browsers don't dispatch `copy` then): a keydown
|
|
59
|
+
* fallback writes via the async Clipboard API inside the keystroke's
|
|
60
|
+
* user-activation window.
|
|
61
|
+
*
|
|
62
|
+
* Returns the unwire function. Mount once per document view (not per page).
|
|
63
|
+
*/
|
|
64
|
+
declare function wireSelectionClipboard(selection: ClipboardSelectionSource, options?: SelectionClipboardOptions): () => void;
|
|
65
|
+
/**
|
|
66
|
+
* Toolbar/menu path: read the selected text and write it to the clipboard
|
|
67
|
+
* via the async Clipboard API. Call from a user-gesture handler (browsers
|
|
68
|
+
* require a secure context + user activation for clipboard writes). Resolves
|
|
69
|
+
* with what was copied ('' when nothing was — nothing is written then, so an
|
|
70
|
+
* empty selection never clobbers the user's clipboard).
|
|
71
|
+
*/
|
|
72
|
+
declare function copySelection(selection: ClipboardSelectionSource): Promise<string>;
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/anchored-position.d.ts
|
|
75
|
+
/**
|
|
76
|
+
* Anchored-overlay geometry for UI floating over page content (selection
|
|
77
|
+
* menus, draft menus, popovers): the projector SNAPSHOT contract, the
|
|
78
|
+
* anchor shape, and the placement math. Pure values and pure functions over
|
|
79
|
+
* structural rect/point shapes — no EmbedPDF types, no framework, no
|
|
80
|
+
* reactive lifecycle — so every framework adapter (React, Vue, Svelte,
|
|
81
|
+
* Angular) shares ONE implementation and binds it with its NATIVE
|
|
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}).
|
|
94
|
+
*/
|
|
95
|
+
interface AnchoredRect {
|
|
96
|
+
x: number;
|
|
97
|
+
y: number;
|
|
98
|
+
width: number;
|
|
99
|
+
height: number;
|
|
100
|
+
}
|
|
101
|
+
interface AnchoredPoint {
|
|
102
|
+
x: number;
|
|
103
|
+
y: number;
|
|
104
|
+
}
|
|
105
|
+
type AnchoredPlacement = 'top' | 'right' | 'bottom' | 'left';
|
|
106
|
+
/** CSS-ready output: absolute/fixed `left`/`top` plus a centering transform. */
|
|
107
|
+
interface AnchoredPosition {
|
|
108
|
+
left: number;
|
|
109
|
+
top: number;
|
|
110
|
+
transform: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Place an upright element around `box` (screen px). `avoid` is a screen
|
|
114
|
+
* point the element must clear (e.g. the rotate knob): the element extends
|
|
115
|
+
* ONLY the edge it sits on, and ONLY when the point protrudes past that
|
|
116
|
+
* edge — so it clears the obstacle without ever shifting off-centre on the
|
|
117
|
+
* other axis. When the point is on another side (e.g. a 90° shape, knob at
|
|
118
|
+
* mid-height for a `top` placement) the edge is untouched and the element
|
|
119
|
+
* stays centred on `box`.
|
|
120
|
+
*/
|
|
121
|
+
/** What anchored UI attaches to: a content-space rect on a page, plus
|
|
122
|
+
* optional content-space points the UI must clear (e.g. a rotate knob).
|
|
123
|
+
* Structural — plugin anchor reads satisfy it without importing this
|
|
124
|
+
* package. */
|
|
125
|
+
interface AnchorTarget {
|
|
126
|
+
pon: number;
|
|
127
|
+
bounds: AnchoredRect;
|
|
128
|
+
avoid?: AnchoredPoint[];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* A page surface's PROJECTION SNAPSHOT: how a content-space rect on a page
|
|
132
|
+
* becomes screen coordinates, right now. Provided by `<Stage>`
|
|
133
|
+
* (camera-driven, pure state, no DOM reads) and `<PageView>` (DOM-measured).
|
|
134
|
+
* Deliberately NO subscribe here — when projection changes is a framework
|
|
135
|
+
* binding concern (see the module doc), not part of the snapshot.
|
|
136
|
+
*/
|
|
137
|
+
interface ViewProjector {
|
|
138
|
+
/**
|
|
139
|
+
* Which coordinate space `toScreen` speaks, and therefore how anchored
|
|
140
|
+
* content mounts:
|
|
141
|
+
* - 'overlay': coords are relative to the surface's own positioned
|
|
142
|
+
* container → rendered in place, position:absolute. (Stage)
|
|
143
|
+
* - 'client': coords are viewport px → portalled to the document body,
|
|
144
|
+
* position:fixed, so no ancestor overflow can clip. (PageView)
|
|
145
|
+
*/
|
|
146
|
+
space: 'overlay' | 'client';
|
|
147
|
+
/** Content-space rect on a page → coords in `space`. Null: not projectable
|
|
148
|
+
* right now (page not shown / not measurable yet). */
|
|
149
|
+
toScreen(pon: number, rect: AnchoredRect): AnchoredRect | null;
|
|
150
|
+
toScreenPoint(pon: number, at: AnchoredPoint): AnchoredPoint | null;
|
|
151
|
+
/** The page's live view facts (for anchor reads that need them — e.g. the
|
|
152
|
+
* screen-constant rotate-knob stalk), or null when the page isn't shown. */
|
|
153
|
+
viewEnv(pon: number): {
|
|
154
|
+
scale: number;
|
|
155
|
+
rotation: 0 | 90 | 180 | 270;
|
|
156
|
+
zoom: number;
|
|
157
|
+
} | null;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* THE anchored projection: anchor → screen position, in one pure call —
|
|
161
|
+
* projection, avoid-point transform, and the shared placement policy.
|
|
162
|
+
* Frameworks recompute this inside their native reactive primitive
|
|
163
|
+
* (a React render, a Vue `computed`, an Angular signal, a Svelte
|
|
164
|
+
* `$derived`); nothing here schedules anything.
|
|
165
|
+
*/
|
|
166
|
+
declare function projectAnchoredTarget(projector: ViewProjector, anchor: AnchorTarget, placement: AnchoredPlacement, gap: number): AnchoredPosition | null;
|
|
167
|
+
/**
|
|
168
|
+
* The one genuinely BROWSER-driven invalidation: an element in normal
|
|
169
|
+
* document flow moves when the document scrolls or the window resizes —
|
|
170
|
+
* no state change announces it. `<PageView>`'s binding registers this;
|
|
171
|
+
* the Stage never does (its camera is state, delivered through render).
|
|
172
|
+
*/
|
|
173
|
+
declare function observeClientGeometry(callback: () => void): () => void;
|
|
174
|
+
declare function positionAnchoredRect(box: AnchoredRect, placement: AnchoredPlacement, gap: number, avoid?: AnchoredPoint | null): AnchoredPosition;
|
|
175
|
+
//#endregion
|
|
19
176
|
//#region src/cursor.d.ts
|
|
20
177
|
/**
|
|
21
178
|
* SVG → CSS cursor string. The armed-tool indicator is the CURSOR itself (the
|
|
@@ -59,5 +216,346 @@ declare function svgCursor({ svg, hotspot, fallback }: SvgCursorOptions): string
|
|
|
59
216
|
*/
|
|
60
217
|
declare function sanitizeExternalUri(uri: string, allowedSchemes?: Iterable<string>): string | null;
|
|
61
218
|
//#endregion
|
|
62
|
-
|
|
219
|
+
//#region src/painted-image.d.ts
|
|
220
|
+
/** A browser image source whose object URL has an explicit lifetime. */
|
|
221
|
+
interface ObjectUrlImageSource {
|
|
222
|
+
objectUrl(signal?: AbortSignal): Promise<{
|
|
223
|
+
url: string;
|
|
224
|
+
revoke(): void;
|
|
225
|
+
}>;
|
|
226
|
+
}
|
|
227
|
+
interface PaintedImageCallbacks {
|
|
228
|
+
onPainted(): void;
|
|
229
|
+
onUnpainted(): void;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Bind a raster source to an <img> without ever painting its incomplete-image
|
|
233
|
+
* placeholder. The source becomes visible on load; retained coverage is
|
|
234
|
+
* released only after the browser has had one full frame to present it.
|
|
235
|
+
*
|
|
236
|
+
* Call this from the framework's pre-paint mount hook and invoke the returned
|
|
237
|
+
* cleanup on unmount. Keeping this DOM lifecycle here lets every framework
|
|
238
|
+
* adapter remain a ref plus one bind/unbind hook.
|
|
239
|
+
*/
|
|
240
|
+
declare function bindPaintedImage(image: HTMLImageElement, source: ObjectUrlImageSource, callbacks: PaintedImageCallbacks): () => void;
|
|
241
|
+
//#endregion
|
|
242
|
+
//#region src/feedback.d.ts
|
|
243
|
+
/**
|
|
244
|
+
* Platform-feedback providers — the browser implementations of the interaction
|
|
245
|
+
* hub's haptic port (structurally `PlatformFeedback` from
|
|
246
|
+
* `@embedpdf/plugin-interaction`; declared structurally here so this package
|
|
247
|
+
* stays plugin-free, per the layering law).
|
|
248
|
+
*
|
|
249
|
+
* Honesty about reach: `navigator.vibrate` works on Android browsers and is
|
|
250
|
+
* NOT implemented in iOS Safari — there the default provider is a silent
|
|
251
|
+
* no-op until Apple ships a haptics API. (The community switch-control hacks
|
|
252
|
+
* were evaluated and deliberately NOT shipped: Apple patched programmatic
|
|
253
|
+
* triggering in iOS 26.5, leaving only tap-on-control tricks that don't fit a
|
|
254
|
+
* viewer's gesture moments.) The real iPhone haptic today comes through a
|
|
255
|
+
* native shell: a WKWebView embedder installs a script message handler and
|
|
256
|
+
* passes {@link wkFeedback} (or their own provider) instead.
|
|
257
|
+
*/
|
|
258
|
+
/** Structural twin of plugin-interaction's `PlatformFeedback`. */
|
|
259
|
+
interface WebPlatformFeedback {
|
|
260
|
+
selection(): void;
|
|
261
|
+
impact(weight?: 'light' | 'medium' | 'heavy'): void;
|
|
262
|
+
notify(kind: 'success' | 'warning' | 'error'): void;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* The default web provider: the Vibration API, mapped onto the three haptic
|
|
266
|
+
* families (selection = the shortest tick; impact scales with weight; notify
|
|
267
|
+
* uses patterns). A no-op wherever vibration is unsupported — notably iOS
|
|
268
|
+
* Safari — so it is always safe to install.
|
|
269
|
+
*/
|
|
270
|
+
declare const vibrationFeedback: WebPlatformFeedback;
|
|
271
|
+
/**
|
|
272
|
+
* A provider for native iOS shells: forwards each call to a WKWebView script
|
|
273
|
+
* message handler the HOST APP installed under `handlerName` — an explicit
|
|
274
|
+
* contract between the embedder and their own app, never a global this library
|
|
275
|
+
* sniffs on its own. The message shape is
|
|
276
|
+
* `{ family: 'selection' } | { family: 'impact', weight } | { family: 'notify', kind }`;
|
|
277
|
+
* the native side maps families onto the matching `UIFeedbackGenerator`.
|
|
278
|
+
* Calls fall back to `fallback` (default: {@link vibrationFeedback}) when the
|
|
279
|
+
* handler is absent, so one provider serves a hybrid web/app deployment.
|
|
280
|
+
*/
|
|
281
|
+
declare const wkFeedback: (handlerName: string, fallback?: WebPlatformFeedback) => WebPlatformFeedback;
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/stage-gestures.d.ts
|
|
284
|
+
/**
|
|
285
|
+
* Stage gesture controller — the ONE DOM input binding for a Stage surface,
|
|
286
|
+
* shared by every framework adapter (React, Angular, …) so the feel can never
|
|
287
|
+
* drift between them.
|
|
288
|
+
*
|
|
289
|
+
* The premise (see the stage plugin's camera doctrine): desktop inputs arrive
|
|
290
|
+
* with physics already applied by the OS — momentum lives in the wheel stream,
|
|
291
|
+
* a trackpad pinch is one pre-arbitrated gesture stream. Touch arrives RAW:
|
|
292
|
+
* with `touch-action: none` the platform scroller is out of the loop, so the
|
|
293
|
+
* ballistics (velocity → fling) and the arbitration (is this contact a scroll,
|
|
294
|
+
* a pinch, a tap, or a tool gesture?) must be synthesized here.
|
|
295
|
+
*
|
|
296
|
+
* Arbitration is MODALITY-AWARE:
|
|
297
|
+
* - touch — navigation-first: one finger pans (whatever tool is armed), two
|
|
298
|
+
* fingers pinch-zoom around their centroid, release velocity flings, a tap
|
|
299
|
+
* forwards as a click, a double-tap zoom-toggles, a long-press hands the
|
|
300
|
+
* gesture to the interaction hub (text selection), and a second finger
|
|
301
|
+
* landing mid-tool-gesture CANCELS it into a pinch (the Notes/Procreate
|
|
302
|
+
* convention).
|
|
303
|
+
* - mouse/pen — tool-first, exactly the pre-existing behavior: with a hub,
|
|
304
|
+
* every down/move/up forwards (pan is the pan tool's job); without one,
|
|
305
|
+
* dragging pans. Wheel and Safari-trackpad gesture events are unchanged.
|
|
306
|
+
*
|
|
307
|
+
* Camera writes are rAF-COALESCED: pointer events only update gesture state;
|
|
308
|
+
* one animation-frame tick applies at most one pan and one zoom per frame,
|
|
309
|
+
* inside the host's begin/endGesture transaction. Events may arrive at 120 Hz;
|
|
310
|
+
* the camera moves at display rate.
|
|
311
|
+
*
|
|
312
|
+
* Dependency note: this module speaks to the stage through the STRUCTURAL
|
|
313
|
+
* {@link StageGestureHost} interface (satisfied by `StageCapability`) and to
|
|
314
|
+
* the interaction hub through {@link StageGestureSink} (a closure the adapter
|
|
315
|
+
* builds) — @embedpdf/web stays free of plugin imports, per the layering law.
|
|
316
|
+
*/
|
|
317
|
+
type StagePointerKind = 'mouse' | 'pen' | 'touch';
|
|
318
|
+
/** What the controller needs from the camera — `StageCapability` satisfies it. */
|
|
319
|
+
interface StageGestureHost {
|
|
320
|
+
panBy(dxScreen: number, dyScreen: number): void;
|
|
321
|
+
zoomAround(screenPt: {
|
|
322
|
+
x: number;
|
|
323
|
+
y: number;
|
|
324
|
+
}, factor: number): void;
|
|
325
|
+
beginGesture(options?: {
|
|
326
|
+
elastic?: boolean;
|
|
327
|
+
}): void;
|
|
328
|
+
endGesture(): void;
|
|
329
|
+
/** Momentum pan from a release velocity in screen px/s. */
|
|
330
|
+
fling(velocityX: number, velocityY: number): void;
|
|
331
|
+
/** True while a tween/fling runs — a touch-down then is a "catch", not a tap. */
|
|
332
|
+
cameraInMotion(): boolean;
|
|
333
|
+
doubleTapZoom(screenPt: {
|
|
334
|
+
x: number;
|
|
335
|
+
y: number;
|
|
336
|
+
}): void;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Where non-navigation gestures go — the adapter's bridge to the interaction
|
|
340
|
+
* hub. Every callback receives the ORIGINAL PointerEvent so the adapter can
|
|
341
|
+
* resolve pages/points exactly as it always has. Omit the sink entirely for a
|
|
342
|
+
* hub-less (built-in pan) stage.
|
|
343
|
+
*/
|
|
344
|
+
interface StageGestureSink {
|
|
345
|
+
down(e: PointerEvent, clickCount: number): void;
|
|
346
|
+
move(e: PointerEvent): void;
|
|
347
|
+
up(e: PointerEvent): void;
|
|
348
|
+
/** The gesture was taken over by navigation (second finger → pinch) or
|
|
349
|
+
* cancelled by the system — abort, don't commit. */
|
|
350
|
+
cancel(e: PointerEvent): void;
|
|
351
|
+
/** Pointer travel with no gesture in flight — cursor feedback. */
|
|
352
|
+
hover(e: PointerEvent): void;
|
|
353
|
+
/** A touch press held still: hand the gesture to the hub (the adapter
|
|
354
|
+
* typically forwards it as a word-select down). Subsequent move/up arrive
|
|
355
|
+
* via {@link move}/{@link up}. */
|
|
356
|
+
longPress(e: PointerEvent): void;
|
|
357
|
+
/**
|
|
358
|
+
* Touch-consent pre-flight, asked at touch-down BEFORE the contact is
|
|
359
|
+
* classified: does a tool have standing to own this contact? True when the
|
|
360
|
+
* armed tool takes fingers wholesale (a drawing tool) or something under
|
|
361
|
+
* the point claims its drags (a selected annotation's body or handles).
|
|
362
|
+
* True routes the whole contact to {@link down}/{@link move}/{@link up} —
|
|
363
|
+
* where a second finger still cancels it into a pinch. Must be a pure
|
|
364
|
+
* read. Absent = never; the contact navigates.
|
|
365
|
+
*/
|
|
366
|
+
claimsPoint?(e: PointerEvent): boolean;
|
|
367
|
+
}
|
|
368
|
+
/** The wheel fields the zoom classifier reads (see `./wheel`'s `WheelSample`). */
|
|
369
|
+
interface StageWheelSample {
|
|
370
|
+
deltaY: number;
|
|
371
|
+
deltaMode: number;
|
|
372
|
+
ctrlKey: boolean;
|
|
373
|
+
metaKey: boolean;
|
|
374
|
+
}
|
|
375
|
+
interface StageGestureOptions {
|
|
376
|
+
/** Ambient zoom (wheel-zoom, pinch-zoom, double-tap zoom). Off: zoom wheels
|
|
377
|
+
* fall through to pan and pinches pan without zooming — but are still
|
|
378
|
+
* swallowed, never page-zooming the browser. Default true. */
|
|
379
|
+
zoomGestures?: boolean;
|
|
380
|
+
/** The wheel → zoom-factor classifier. Defaults to this package's
|
|
381
|
+
* `wheelZoomFactor` (browser wheel classification lives HERE, with the rest
|
|
382
|
+
* of the browser input handling); inject to override or to fake in tests. */
|
|
383
|
+
wheelZoomFactor?: (sample: StageWheelSample) => number;
|
|
384
|
+
/** Tool routing for non-navigation gestures; omit for built-in-pan stages. */
|
|
385
|
+
sink?: StageGestureSink | null;
|
|
386
|
+
/** Touch press duration that becomes a long-press (ms). Default 450. */
|
|
387
|
+
longPressMs?: number;
|
|
388
|
+
/** Finger travel below which a touch stays a tap/press (px). Default 10. */
|
|
389
|
+
tapSlopPx?: number;
|
|
390
|
+
/** Max gap between taps for a double-tap (ms). Default 300. */
|
|
391
|
+
doubleTapMs?: number;
|
|
392
|
+
/** Release speed below which no fling starts (px/s). Default 50. */
|
|
393
|
+
flingMinVelocity?: number;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Release velocity from a trail of pointer samples: the mean velocity over the
|
|
397
|
+
* trailing `windowMs` (first-to-last inside the window). Null when the trail is
|
|
398
|
+
* too thin or too stale to trust — the standard "held still, then let go"
|
|
399
|
+
* case, which must NOT fling. Pure; exported for tests.
|
|
400
|
+
*/
|
|
401
|
+
declare function computeReleaseVelocity(samples: ReadonlyArray<{
|
|
402
|
+
t: number;
|
|
403
|
+
x: number;
|
|
404
|
+
y: number;
|
|
405
|
+
}>, now: number, windowMs?: number): {
|
|
406
|
+
vx: number;
|
|
407
|
+
vy: number;
|
|
408
|
+
} | null;
|
|
409
|
+
/** Attach the gesture controller to a Stage container. Returns the detach fn. */
|
|
410
|
+
declare function createStageGestureController(el: HTMLElement, host: StageGestureHost, options: StageGestureOptions): () => void;
|
|
411
|
+
//#endregion
|
|
412
|
+
//#region src/selection-handles.d.ts
|
|
413
|
+
/**
|
|
414
|
+
* Selection-handle DOM binding — the listener mechanics of dragging one
|
|
415
|
+
* handle element, shared by every framework adapter (the policy — geometry
|
|
416
|
+
* and the drag session — lives in `@embedpdf/plugin-selection`'s pure
|
|
417
|
+
* `handles` module; this file never imports it, per the layering law:
|
|
418
|
+
* structural interfaces only).
|
|
419
|
+
*
|
|
420
|
+
* The load-bearing subtlety this module owns: the pointer-DOWN shield must be
|
|
421
|
+
* a NATIVE listener. The stage's gesture controller listens natively on the
|
|
422
|
+
* container, so a framework-synthetic stopPropagation (React runs its
|
|
423
|
+
* handlers at the root, AFTER the container's native ones) would be too late
|
|
424
|
+
* — the stage would already be panning underneath the handle drag. Once the
|
|
425
|
+
* down is captured here, movement tracks by CLIENT DELTAS from the handle's
|
|
426
|
+
* own base point: no DOM geometry reads, and the client↔overlay conversion
|
|
427
|
+
* cancels out.
|
|
428
|
+
*/
|
|
429
|
+
interface SurfacePoint$1 {
|
|
430
|
+
x: number;
|
|
431
|
+
y: number;
|
|
432
|
+
}
|
|
433
|
+
/** The armed drag the adapter hands back — plugin-selection's
|
|
434
|
+
* `SelectionHandleDragSession` satisfies it. */
|
|
435
|
+
interface SelectionHandleSession {
|
|
436
|
+
move(overlay: SurfacePoint$1): void;
|
|
437
|
+
end(): void;
|
|
438
|
+
}
|
|
439
|
+
interface AttachSelectionHandleOptions {
|
|
440
|
+
/**
|
|
441
|
+
* Called at pointer-down to arm a drag: return the drag session plus the
|
|
442
|
+
* handle's current BASE point in overlay space (the bar's midpoint — the
|
|
443
|
+
* point the user grabbed). Return null to decline (endpoint vanished, page
|
|
444
|
+
* not laid out) — the press then does nothing and nothing is captured.
|
|
445
|
+
*/
|
|
446
|
+
arm(): {
|
|
447
|
+
base: SurfacePoint$1;
|
|
448
|
+
session: SelectionHandleSession;
|
|
449
|
+
} | null;
|
|
450
|
+
}
|
|
451
|
+
/** Bind one handle element. Returns the detach fn. */
|
|
452
|
+
declare function attachSelectionHandle(el: HTMLElement, options: AttachSelectionHandleOptions): () => void;
|
|
453
|
+
//#endregion
|
|
454
|
+
//#region src/stage-surface.d.ts
|
|
455
|
+
interface SurfacePoint {
|
|
456
|
+
x: number;
|
|
457
|
+
y: number;
|
|
458
|
+
}
|
|
459
|
+
/** What the binding needs from the stage — `StageCapability` satisfies it. */
|
|
460
|
+
interface StageSurfaceHost extends StageGestureHost {
|
|
461
|
+
setViewport(size: {
|
|
462
|
+
width: number;
|
|
463
|
+
height: number;
|
|
464
|
+
}): void;
|
|
465
|
+
setDevicePixelRatio(ratio: number): void;
|
|
466
|
+
/** Viewport point → the page under it (with per-page display context), or null over a gap. */
|
|
467
|
+
pageAt(screen: SurfacePoint): {
|
|
468
|
+
pon: number;
|
|
469
|
+
point: SurfacePoint;
|
|
470
|
+
scale?: number;
|
|
471
|
+
rotation?: 0 | 90 | 180 | 270;
|
|
472
|
+
zoom?: number;
|
|
473
|
+
} | null;
|
|
474
|
+
/** Viewport point → a SPECIFIC page's content space, unclamped (frame-stable projection). */
|
|
475
|
+
pointOnPage(pon: number, screen: SurfacePoint): SurfacePoint | null;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* The page-resolved sample the binding hands the hub — structurally a
|
|
479
|
+
* `PointerSample` (plugin-interaction). `source` carries the lens identity so
|
|
480
|
+
* the hub can route lens-scoped handlers; with several stages on one document,
|
|
481
|
+
* a drag on one lens must never be captured by another lens's handler.
|
|
482
|
+
*/
|
|
483
|
+
interface StageSurfaceSample {
|
|
484
|
+
phase: 'down' | 'move' | 'up' | 'cancel';
|
|
485
|
+
viewport: SurfacePoint;
|
|
486
|
+
page?: {
|
|
487
|
+
pon: number;
|
|
488
|
+
point: SurfacePoint;
|
|
489
|
+
scale?: number;
|
|
490
|
+
rotation?: 0 | 90 | 180 | 270;
|
|
491
|
+
zoom?: number;
|
|
492
|
+
};
|
|
493
|
+
project: (pon: number) => SurfacePoint | null;
|
|
494
|
+
modifiers: {
|
|
495
|
+
shift: boolean;
|
|
496
|
+
alt: boolean;
|
|
497
|
+
ctrl: boolean;
|
|
498
|
+
meta: boolean;
|
|
499
|
+
};
|
|
500
|
+
clickCount: number;
|
|
501
|
+
pointerType: 'mouse' | 'pen' | 'touch';
|
|
502
|
+
gesture?: 'long-press';
|
|
503
|
+
source?: string;
|
|
504
|
+
}
|
|
505
|
+
/** What the binding needs from the interaction hub — `InteractionCapability` satisfies it. */
|
|
506
|
+
interface StageSurfaceHub {
|
|
507
|
+
dispatch(sample: StageSurfaceSample): void;
|
|
508
|
+
activeTool(): {
|
|
509
|
+
touchDirect?: boolean;
|
|
510
|
+
};
|
|
511
|
+
wouldClaimTouch(sample: StageSurfaceSample): boolean;
|
|
512
|
+
}
|
|
513
|
+
interface StageSurfaceOptions {
|
|
514
|
+
/** Route pointer input to the interaction hub (page-resolved samples) instead
|
|
515
|
+
* of built-in drag-to-pan. Omit/null for a hub-less stage. */
|
|
516
|
+
hub?: StageSurfaceHub | null;
|
|
517
|
+
/** The lens identity stamped on every sample (`StageCapability.lensId()`),
|
|
518
|
+
* so lens-scoped handlers only see their own stage's input. */
|
|
519
|
+
source?: string;
|
|
520
|
+
/** Ambient zoom gestures (see {@link StageGestureOptions}). Default true. */
|
|
521
|
+
zoomGestures?: boolean;
|
|
522
|
+
/** Override the wheel → zoom-factor classifier (defaults to `./wheel`). */
|
|
523
|
+
wheelZoomFactor?: (sample: StageWheelSample) => number;
|
|
524
|
+
}
|
|
525
|
+
/** Attach the full surface binding. Returns the detach fn. */
|
|
526
|
+
declare function createStageSurface(el: HTMLElement, stage: StageSurfaceHost, options?: StageSurfaceOptions): () => void;
|
|
527
|
+
//#endregion
|
|
528
|
+
//#region src/wheel.d.ts
|
|
529
|
+
/**
|
|
530
|
+
* Wheel-input classification for ambient zoom — pure, so every framework
|
|
531
|
+
* adapter shares one feel and the mapping is unit-testable.
|
|
532
|
+
*
|
|
533
|
+
* A ctrl/cmd wheel event is one of three physically different inputs that
|
|
534
|
+
* happen to share an event type, each with its own unit system:
|
|
535
|
+
*
|
|
536
|
+
* • trackpad PINCH — browsers (Chrome/Edge/Firefox) synthesize ctrl+wheel
|
|
537
|
+
* px-deltas scaled to the de-facto convention that `exp(-Δ/100)` tracks
|
|
538
|
+
* the physical finger scale 1:1. Anything weaker feels dead (the content
|
|
539
|
+
* must track the fingers — the Figma/maps feel).
|
|
540
|
+
* • mouse NOTCHES — coarse steps: ±100/±120 px in Chrome, lines/pages mode
|
|
541
|
+
* in Firefox. The pinch mapping would triple per click; a notch instead
|
|
542
|
+
* steps by 1.2, the same ratio as the zoom buttons.
|
|
543
|
+
* • cmd + continuous SCROLL — real scroll px, big and streaming (with
|
|
544
|
+
* momentum): a gentle scrub coefficient. A cmd+mouse notch (±120 px)
|
|
545
|
+
* lands within 0.3% of the 1.2 button step, so it needs no special case.
|
|
546
|
+
*
|
|
547
|
+
* (Safari never synthesizes ctrl+wheel for pinch — it fires proprietary
|
|
548
|
+
* gesture events with an absolute scale; that wiring lives in the adapters.)
|
|
549
|
+
*/
|
|
550
|
+
interface WheelSample {
|
|
551
|
+
deltaY: number;
|
|
552
|
+
/** WheelEvent.deltaMode: 0 = pixels, 1 = lines, 2 = pages. */
|
|
553
|
+
deltaMode: number;
|
|
554
|
+
ctrlKey: boolean;
|
|
555
|
+
metaKey: boolean;
|
|
556
|
+
}
|
|
557
|
+
/** Zoom factor for a ctrl/cmd wheel event (the caller decides zoom vs pan). */
|
|
558
|
+
declare function wheelZoomFactor(e: WheelSample): number;
|
|
559
|
+
//#endregion
|
|
560
|
+
export { type AnchorTarget, type AnchoredPlacement, type AnchoredPoint, type AnchoredPosition, type AnchoredRect, type AttachSelectionHandleOptions, type ClipboardSelectionSource, type ObjectUrlImageSource, type PaintedImageCallbacks, type PickFileOptions, type SelectionClipboardOptions, type SelectionHandleSession, type StageGestureHost, type StageGestureOptions, type StageGestureSink, type StagePointerKind, type StageSurfaceHost, type StageSurfaceHub, type StageSurfaceOptions, type StageSurfaceSample, type StageWheelSample, type SvgCursorOptions, type ViewProjector, type WebPlatformFeedback, type WheelSample, attachSelectionHandle, bindPaintedImage, computeReleaseVelocity, copySelection, createStageGestureController, createStageSurface, observeClientGeometry, pickFile, pickImageFile, positionAnchoredRect, projectAnchoredTarget, sanitizeExternalUri, saveFile, svgCursor, vibrationFeedback, wheelZoomFactor, wireSelectionClipboard, wkFeedback };
|
|
63
561
|
//# sourceMappingURL=index.d.cts.map
|