@embedpdf/web 3.0.0-next.6 → 3.0.0-next.8

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.d.ts CHANGED
@@ -239,5 +239,323 @@ interface PaintedImageCallbacks {
239
239
  */
240
240
  declare function bindPaintedImage(image: HTMLImageElement, source: ObjectUrlImageSource, callbacks: PaintedImageCallbacks): () => void;
241
241
  //#endregion
242
- export { type AnchorTarget, type AnchoredPlacement, type AnchoredPoint, type AnchoredPosition, type AnchoredRect, type ClipboardSelectionSource, type ObjectUrlImageSource, type PaintedImageCallbacks, type PickFileOptions, type SelectionClipboardOptions, type SvgCursorOptions, type ViewProjector, bindPaintedImage, copySelection, observeClientGeometry, pickFile, pickImageFile, positionAnchoredRect, projectAnchoredTarget, sanitizeExternalUri, saveFile, svgCursor, wireSelectionClipboard };
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 };
243
561
  //# sourceMappingURL=index.d.ts.map