@embedpdf/plugin-selection 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/contract/host.cjs +16 -2
- package/dist/contract/host.cjs.map +1 -0
- package/dist/contract/host.d.cts +3 -2
- package/dist/contract/host.d.ts +3 -2
- package/dist/contract/host.js +16 -2
- package/dist/contract/host.js.map +1 -0
- package/dist/contract-BUiw1d8F.cjs +36 -0
- package/dist/contract-BUiw1d8F.cjs.map +1 -0
- package/dist/contract-DBXA64ep.js +26 -0
- package/dist/contract-DBXA64ep.js.map +1 -0
- package/dist/contract-DLs4vXVt.d.cts +252 -0
- package/dist/contract-DLs4vXVt.d.ts +252 -0
- package/dist/contract.cjs +3 -6
- package/dist/contract.d.cts +2 -7
- package/dist/contract.d.ts +2 -7
- package/dist/contract.js +2 -7
- package/dist/host-contract-DO2aLU2e.d.ts +34 -0
- package/dist/host-contract-Ddo4PcJJ.d.cts +34 -0
- package/dist/index.cjs +777 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -29
- package/dist/index.d.ts +97 -29
- package/dist/index.js +772 -51
- package/dist/index.js.map +1 -1
- package/package.json +5 -9
- package/dist/contract.cjs.map +0 -1
- package/dist/contract.js.map +0 -1
- package/dist/internal.cjs +0 -13
- package/dist/internal.d.cts +0 -63
- package/dist/internal.d.ts +0 -63
- package/dist/internal.js +0 -4
- package/dist/reducer-BAOQ2CJ8.cjs +0 -732
- package/dist/reducer-BAOQ2CJ8.cjs.map +0 -1
- package/dist/reducer-DbKtk9Xl.js +0 -685
- package/dist/reducer-DbKtk9Xl.js.map +0 -1
- package/dist/types-BVUcOsCh.js +0 -14
- package/dist/types-BVUcOsCh.js.map +0 -1
- package/dist/types-CUrUVl6K.d.cts +0 -292
- package/dist/types-CUrUVl6K.d.ts +0 -292
- package/dist/types-D9kEBMFj.cjs +0 -18
- package/dist/types-D9kEBMFj.cjs.map +0 -1
package/dist/contract/host.cjs
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
|
|
2
|
+
const require_contract = require("../contract-BUiw1d8F.cjs");
|
|
3
|
+
//#region src/host-contract.ts
|
|
4
|
+
/**
|
|
5
|
+
* @embedpdf/plugin-selection/contract/host — the host lens.
|
|
6
|
+
*
|
|
7
|
+
* What render layers, the interaction hub and sibling plugins need on top
|
|
8
|
+
* of the public contract: gesture bracketing, geometry warming and the
|
|
9
|
+
* highlight-visibility handshake. Same runtime token as the public one,
|
|
10
|
+
* typed wider. Never use this from application code.
|
|
11
|
+
*/
|
|
12
|
+
const SelectionToken = (0, require("@embedpdf/core").createHostToken)(require_contract.SelectionToken);
|
|
13
|
+
//#endregion
|
|
14
|
+
exports.SELECTION_DEFAULTS = require_contract.SELECTION_DEFAULTS;
|
|
15
|
+
exports.SelectionToken = SelectionToken;
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=host.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.cjs","names":["PublicSelectionToken"],"sources":["../../src/host-contract.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-selection/contract/host — the host lens.\n *\n * What render layers, the interaction hub and sibling plugins need on top\n * of the public contract: gesture bracketing, geometry warming and the\n * highlight-visibility handshake. Same runtime token as the public one,\n * typed wider. Never use this from application code.\n */\nimport { createHostToken, type PageRef } from '@embedpdf/core';\nimport type { Point } from '@embedpdf/core-geometry';\nimport { SelectionToken as PublicSelectionToken, type SelectionCapability } from './contract';\n\nexport * from './contract';\n\nexport interface SelectionHostCapability extends SelectionCapability {\n /** Warm a page's text geometry. Resolves once loaded; resolves immediately\n * (nothing requested) without `doc.text.select` or for an unknown page. A\n * failed read resolves too — the layer simply has nothing to paint. */\n ensureLoaded(page: PageRef): Promise<void>;\n /** Whether the page's text geometry is loaded and current. */\n isLoaded(page: PageRef): boolean;\n /** Is a page-space point on (or near) text? Drives the I-beam cursor. */\n isOverText(page: PageRef, point: Point): boolean;\n /**\n * A pointer gesture that drives the selection opened (pointer-down). From\n * here until {@link endGesture}, `isSelecting()` is true and\n * selection-scoped UI hides. Programmatic writes never open a gesture.\n */\n beginGesture(): void;\n /** Open a caret selection at a page point (the first drag step). Returns\n * false when the point has no text — the caller lets the gesture go. */\n beginGestureAt(page: PageRef, point: Point): boolean;\n /** The gesture ended (pointer-up). Settles first, then emits `onCommitted`\n * when a selection is in place. */\n endGesture(): void;\n /** Suppress / restore the default highlight visual (a consumer drawing its\n * own preview — the markup ghost). */\n setHighlightVisible(visible: boolean): void;\n isHighlightVisible(): boolean;\n}\n\nexport const SelectionToken = createHostToken<SelectionHostCapability>(PublicSelectionToken);\n"],"mappings":";;;;;;;;;;;AAyCA,MAAa,kBAAA,2BAAA,CAAA,CAAA,gBAAA,CAA0DA,iBAAAA,cAAoB"}
|
package/dist/contract/host.d.cts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
|
|
1
|
+
import { a as SelectionClearedEvent, c as SelectionEndpoint, d as SelectionSnapshot, f as TextPosition, h as SelectionSegment, i as SelectionChangedEvent, l as SelectionRangeInput, n as SelectionAnchor, o as SelectionCommittedEvent, p as TextRange, r as SelectionCapability, s as SelectionConfig, t as SELECTION_DEFAULTS, u as SelectionSettings } from "../contract-DLs4vXVt.cjs";
|
|
2
|
+
import { n as SelectionToken, t as SelectionHostCapability } from "../host-contract-Ddo4PcJJ.cjs";
|
|
3
|
+
export { SELECTION_DEFAULTS, SelectionAnchor, SelectionCapability, SelectionChangedEvent, SelectionClearedEvent, SelectionCommittedEvent, SelectionConfig, SelectionEndpoint, SelectionHostCapability, SelectionRangeInput, type SelectionSegment, SelectionSettings, SelectionSnapshot, SelectionToken, TextPosition, TextRange };
|
package/dist/contract/host.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
|
|
1
|
+
import { a as SelectionClearedEvent, c as SelectionEndpoint, d as SelectionSnapshot, f as TextPosition, h as SelectionSegment, i as SelectionChangedEvent, l as SelectionRangeInput, n as SelectionAnchor, o as SelectionCommittedEvent, p as TextRange, r as SelectionCapability, s as SelectionConfig, t as SELECTION_DEFAULTS, u as SelectionSettings } from "../contract-DLs4vXVt.js";
|
|
2
|
+
import { n as SelectionToken, t as SelectionHostCapability } from "../host-contract-DO2aLU2e.js";
|
|
3
|
+
export { SELECTION_DEFAULTS, SelectionAnchor, SelectionCapability, SelectionChangedEvent, SelectionClearedEvent, SelectionCommittedEvent, SelectionConfig, SelectionEndpoint, SelectionHostCapability, SelectionRangeInput, type SelectionSegment, SelectionSettings, SelectionSnapshot, SelectionToken, TextPosition, TextRange };
|
package/dist/contract/host.js
CHANGED
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { n as SelectionToken$1, t as SELECTION_DEFAULTS } from "../contract-DBXA64ep.js";
|
|
2
|
+
import { createHostToken } from "@embedpdf/core";
|
|
3
|
+
//#region src/host-contract.ts
|
|
4
|
+
/**
|
|
5
|
+
* @embedpdf/plugin-selection/contract/host — the host lens.
|
|
6
|
+
*
|
|
7
|
+
* What render layers, the interaction hub and sibling plugins need on top
|
|
8
|
+
* of the public contract: gesture bracketing, geometry warming and the
|
|
9
|
+
* highlight-visibility handshake. Same runtime token as the public one,
|
|
10
|
+
* typed wider. Never use this from application code.
|
|
11
|
+
*/
|
|
12
|
+
const SelectionToken = createHostToken(SelectionToken$1);
|
|
13
|
+
//#endregion
|
|
14
|
+
export { SELECTION_DEFAULTS, SelectionToken };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","names":["PublicSelectionToken"],"sources":["../../src/host-contract.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-selection/contract/host — the host lens.\n *\n * What render layers, the interaction hub and sibling plugins need on top\n * of the public contract: gesture bracketing, geometry warming and the\n * highlight-visibility handshake. Same runtime token as the public one,\n * typed wider. Never use this from application code.\n */\nimport { createHostToken, type PageRef } from '@embedpdf/core';\nimport type { Point } from '@embedpdf/core-geometry';\nimport { SelectionToken as PublicSelectionToken, type SelectionCapability } from './contract';\n\nexport * from './contract';\n\nexport interface SelectionHostCapability extends SelectionCapability {\n /** Warm a page's text geometry. Resolves once loaded; resolves immediately\n * (nothing requested) without `doc.text.select` or for an unknown page. A\n * failed read resolves too — the layer simply has nothing to paint. */\n ensureLoaded(page: PageRef): Promise<void>;\n /** Whether the page's text geometry is loaded and current. */\n isLoaded(page: PageRef): boolean;\n /** Is a page-space point on (or near) text? Drives the I-beam cursor. */\n isOverText(page: PageRef, point: Point): boolean;\n /**\n * A pointer gesture that drives the selection opened (pointer-down). From\n * here until {@link endGesture}, `isSelecting()` is true and\n * selection-scoped UI hides. Programmatic writes never open a gesture.\n */\n beginGesture(): void;\n /** Open a caret selection at a page point (the first drag step). Returns\n * false when the point has no text — the caller lets the gesture go. */\n beginGestureAt(page: PageRef, point: Point): boolean;\n /** The gesture ended (pointer-up). Settles first, then emits `onCommitted`\n * when a selection is in place. */\n endGesture(): void;\n /** Suppress / restore the default highlight visual (a consumer drawing its\n * own preview — the markup ghost). */\n setHighlightVisible(visible: boolean): void;\n isHighlightVisible(): boolean;\n}\n\nexport const SelectionToken = createHostToken<SelectionHostCapability>(PublicSelectionToken);\n"],"mappings":";;;;;;;;;;;AAyCA,MAAa,iBAAiB,gBAAyCA,gBAAoB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/token.ts
|
|
2
|
+
/** The package token — created once here; `contract.ts` re-exports it and
|
|
3
|
+
* `host-contract.ts` widens it. */
|
|
4
|
+
const SelectionToken = (0, require("@embedpdf/core").createCapabilityToken)("selection", {
|
|
5
|
+
hint: `add selectionPlugin() from '@embedpdf/plugin-selection' to your plugins list`,
|
|
6
|
+
promises: {
|
|
7
|
+
readText: true,
|
|
8
|
+
readTextInRange: true
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/contract.ts
|
|
13
|
+
/** What the selection settings are when the app registers none. */
|
|
14
|
+
const SELECTION_DEFAULTS = {
|
|
15
|
+
dragThreshold: 4,
|
|
16
|
+
color: null,
|
|
17
|
+
handles: {
|
|
18
|
+
color: null,
|
|
19
|
+
shadow: "0 1px 4px rgb(0 0 0 / 0.35)"
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
Object.defineProperty(exports, "SELECTION_DEFAULTS", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function() {
|
|
26
|
+
return SELECTION_DEFAULTS;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
Object.defineProperty(exports, "SelectionToken", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
get: function() {
|
|
32
|
+
return SelectionToken;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=contract-BUiw1d8F.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-BUiw1d8F.cjs","names":[],"sources":["../src/token.ts","../src/contract.ts"],"sourcesContent":["/** The package token — created once here; `contract.ts` re-exports it and\n * `host-contract.ts` widens it. */\nimport { createCapabilityToken } from '@embedpdf/core';\n\nimport type { SelectionCapability } from './contract';\n\nexport const SelectionToken = createCapabilityToken<SelectionCapability>('selection', {\n hint: `add selectionPlugin() from '@embedpdf/plugin-selection' to your plugins list`,\n // Without a document, an adapter's stand-in rejects these with `not-ready`, as the\n // capability would; the type asks for every member that returns a promise.\n promises: {\n readText: true,\n readTextInRange: true,\n },\n});\n","/**\n * @embedpdf/plugin-selection/contract — the public selection vocabulary.\n *\n * Selection ranges live in character space (half-open `TextRange`, the same\n * space search hits address). Geometry needs `doc.text.select`, text\n * extraction needs `doc.text.copy`, and neither permission implies the other.\n * Segments, endpoints and anchors are in page space (page space: y-down,\n * PDF units, crop-relative), the space every layer paints in.\n */\nimport type {\n DeepPartial,\n EventHook,\n OperationOptions,\n PageRef,\n SettingsApi,\n} from '@embedpdf/core';\nimport type { Point, Rect, Quad } from '@embedpdf/core-geometry';\nimport type { SelectionSegment } from './geometry';\n\nexport type { SelectionSegment } from './geometry';\n\n// ── settings ────────────────────────────────────────────────────────────────\n\n/**\n * The selection plugin's settings. `selectionPlugin(config)` registers them\n * over {@link SELECTION_DEFAULTS}, and `updateSettings()` changes them for\n * every document while the app runs. The colors and the shadow can also come\n * from CSS (`--epdf-text-selection`, `--epdf-text-selection-handle`,\n * `--epdf-text-selection-handle-shadow`), which wins over the setting.\n */\nexport interface SelectionSettings {\n /** How far, in viewport pixels, the pointer travels before a press becomes a drag that selects. */\n readonly dragThreshold: number;\n /** The color of selected text: a CSS color, or `null` for the viewer's accent at 35%. */\n readonly color: string | null;\n /** The grips at the selection's ends, on touch screens. */\n readonly handles: {\n /** A CSS color, or `null` for the viewer's accent. */\n readonly color: string | null;\n /** A CSS `box-shadow`. */\n readonly shadow: string;\n };\n}\n\n/** What the selection settings are when the app registers none. */\nexport const SELECTION_DEFAULTS: SelectionSettings = {\n dragThreshold: 4,\n color: null,\n handles: { color: null, shadow: '0 1px 4px rgb(0 0 0 / 0.35)' },\n};\n\n/** What `selectionPlugin(config)` takes: any of the settings, merged over the defaults. */\nexport type SelectionConfig = DeepPartial<SelectionSettings>;\n\n// ── the range vocabulary ────────────────────────────────────────────────────\n\n/**\n * A position in a page's character space — the space the engine's geometry\n * runs tile (`PageGeometryRun.charStart`) and search hits address\n * (`SearchMatch.charStart`). Not a string offset into extracted text; the\n * two spaces are joined by the engine's `charMap` (see engine-core\n * `text/charmap.ts`), which `readText()` applies for you.\n */\nexport interface TextPosition {\n page: PageRef;\n /** Character index, 0-based. */\n index: number;\n}\n\n/**\n * A half-open range in character space: `start` inclusive, `end` exclusive,\n * in document order (`start` at or before `end`). `end.index` may be 0 to\n * end a range exactly at a page boundary.\n */\nexport interface TextRange {\n start: TextPosition;\n end: TextPosition;\n}\n\n/**\n * What {@link SelectionCapability.select} accepts: a cross-page\n * {@link TextRange}, or a single-page span — the shape of a search hit, so\n * `select({ page: hit.page, start: hit.charStart, count: hit.charCount })`\n * needs no conversion.\n */\nexport type SelectionRangeInput = TextRange | { page: PageRef; start: number; count: number };\n\n// ── the read model ──────────────────────────────────────────────────────────\n\n/**\n * A selection boundary, anchored to the boundary glyph's own oriented cell.\n * `advance` is the reading direction of the segment it belongs to (+1 = the\n * frame's +x), so caret consumers place at the trailing edge without\n * re-deriving bidi from geometry. `rect` is the AABB (scroll targets).\n */\nexport interface SelectionEndpoint {\n page: PageRef;\n glyphQuad: Quad;\n advance: 1 | -1;\n rect: Rect;\n}\n\n/** Where selection-scoped floating UI attaches: a page + the selection's\n * union box on it, in page space. See {@link SelectionCapability.getAnchor}. */\nexport interface SelectionAnchor {\n page: PageRef;\n bounds: Rect;\n}\n\nexport interface SelectionSnapshot {\n /** Per-page canonical segments — the one geometry consumers act on.\n * Boxes are derived views (`segment.rect`, or `listRects()`). */\n readonly pages: readonly { page: PageRef; segments: readonly SelectionSegment[] }[];\n readonly start: SelectionEndpoint | null;\n readonly end: SelectionEndpoint | null;\n readonly direction: 'forward' | 'backward';\n /**\n * The selection as a half-open character range in document order — a\n * valid {@link SelectionCapability.select} input (persist and restore).\n * Null when nothing is selected. Until a boundary page's text geometry\n * has loaded, its index may still exceed the page's character count\n * (`selectAll` settles as geometry arrives); consumers of the range\n * (`select`, `readTextInRange`) clamp, so round-tripping is always safe.\n */\n readonly range: TextRange | null;\n}\n\n// ── events ──────────────────────────────────────────────────────────────────\n\n/**\n * The selection's range or segments changed: a gesture step, a programmatic\n * select, a boundary page's text geometry arriving, or a clear. Selection is\n * session state, so the event carries no document origin.\n */\nexport interface SelectionChangedEvent {\n readonly range: TextRange | null;\n /** The pages that carry a segment right now. */\n readonly pages: readonly PageRef[];\n}\n\n/** A selection gesture ended (pointer-up, handle release) with a selection in\n * place — the commit point markup creation and clipboard prefetch act on.\n * Never fires for programmatic selection. */\nexport interface SelectionCommittedEvent {\n readonly range: TextRange;\n}\n\n/** The selection went from a range to nothing. */\nexport type SelectionClearedEvent = Record<string, never>;\n\n// ── the public capability ───────────────────────────────────────────────────\n\n/**\n * The public selection API — the documented, stable surface for application\n * code (toolbars, context menus, automation).\n *\n * The permission model: geometry enables selection (`doc.text.select`),\n * text enables extraction (`doc.text.copy`) — neither implies the other.\n * Everything here except the `readText` pair works with the select scope\n * alone, so a deployment can allow selecting and highlighting while denying\n * copy. Writes without the scope throw `PluginError('permission-denied')`;\n * gate UI with {@link canSelect} / {@link canCopy}.\n *\n * Every gesture has a programmatic twin: drag = {@link select} (or\n * `beginGestureAt` + {@link extendTo} for point-driven code on the host\n * lens), double-click = {@link selectWordAt}, triple-click =\n * {@link selectLineAt}, handle drag = {@link extendTo}, click on empty space\n * = {@link clear}, select-all = {@link selectAll}.\n *\n * A page argument is a `PageRef` or a zero-based index. A verb given a page\n * that isn't in the document throws `not-found`; a read returns empty.\n *\n * The settings (`getSettings`, `updateSettings`, `resetSettings`,\n * `onSettingsChanged`) belong to the plugin, not to a document: a change\n * reaches every open document.\n *\n * Framework-only plumbing (gesture bracketing, geometry warming, the\n * highlight-visibility handshake) lives on `SelectionHostCapability`,\n * reachable through `@embedpdf/plugin-selection/contract/host`. Both are the\n * same runtime object — two typed lenses on one token.\n */\nexport interface SelectionCapability extends SettingsApi<SelectionSettings> {\n // ── authorization (mirrors the engine's own enforcement) ──\n /** Whether this caller may create selections at all (`doc.text.select`). */\n canSelect(): boolean;\n /** Whether this caller may extract literal text (`doc.text.copy`). */\n canCopy(): boolean;\n\n // ── writes (character space, half-open) ──\n /**\n * Select a range — the same path gestures use, so the highlight, events\n * and markup bridges behave identically. An empty range clears. Throws\n * `permission-denied` without `doc.text.select`, `not-found` for a page\n * that is not in this document. Fires `onChanged`, or `onCleared`.\n */\n select(range: SelectionRangeInput): void;\n /** Select every character of the document. Throws `permission-denied` without `doc.text.select`. */\n selectAll(): void;\n /**\n * Select every character on one page. Throws `permission-denied` without\n * `doc.text.select`, `not-found` for a page that is not in this document.\n */\n selectPage(page: PageRef | number): void;\n /**\n * Select the word around a page point. Returns false when the point has no\n * selectable text (geometry not loaded yet, or no glyph there). Throws\n * `permission-denied` without `doc.text.select`, `not-found` for a page that\n * is not in this document.\n */\n selectWordAt(page: PageRef | number, point: Point): boolean;\n /** Select the visual line around a page point. Same result and errors as {@link selectWordAt}. */\n selectLineAt(page: PageRef | number, point: Point): boolean;\n /**\n * Extend the current selection to a page point (a drag step). No selection\n * → no-op; a page whose geometry has not loaded is warmed and the extension\n * lands when it arrives. Errors as {@link selectPage}.\n */\n extendTo(page: PageRef | number, point: Point): void;\n /** Clear the selection. Always allowed. Fires `onCleared` when something was selected. */\n clear(): void;\n\n // ── reads ──\n /** Whether anything is selected. */\n hasSelection(): boolean;\n /**\n * Whether the user is still selecting: from the press of a drag, a\n * double-click or a handle until it lifts. A selection made from code is\n * never in progress.\n */\n isSelecting(): boolean;\n /** Per-page segments, endpoints, direction and the range. Reference-stable\n * until the selection changes. */\n getSnapshot(): SelectionSnapshot;\n /** The selected character range, or null. */\n getRange(): TextRange | null;\n /** The pages the current selection covers (those with at least one\n * segment), in document order — so a cross-page action can fan out per page. */\n listSelectedPages(): readonly PageRef[];\n /** Per-line oriented segments for a page, in page space — build your own\n * highlight layer from these. Reference-stable per page. */\n listSegments(page: PageRef | number): readonly SelectionSegment[];\n /** The segments' AABBs — for consumers that genuinely want boxes (scroll,\n * conservative regions). Never a substitute for the oriented quads in\n * geometry that gets drawn or persisted. */\n listRects(page: PageRef | number): readonly Rect[];\n /**\n * Where selection-scoped floating UI should attach: the union box of the\n * selection's segments on its end page (where the gesture finished),\n * falling back to the last page with materialized segments while a\n * boundary page's geometry is still loading. One anchor regardless of\n * cross-page selection. Null when nothing is selected (or nothing has\n * materialized yet).\n */\n getAnchor(): SelectionAnchor | null;\n\n // ── text extraction (requires doc.text.copy) ──\n /**\n * The selected text. Each page's text snapshot is fetched once per content\n * version and sliced through the engine's `charMap`; pages are joined with\n * `\\n`. Resolves `''` when nothing is selected. Rejects `permission-denied`\n * without `doc.text.copy`, and `operation-cancelled` when `options.signal`\n * fires. Clipboard writes are deliberately not here — this package is\n * DOM-free; use `@embedpdf/web`'s clipboard helpers.\n */\n readText(options?: OperationOptions): Promise<string>;\n /**\n * Text for any range, without touching the selection. Rejects as\n * {@link readText} does, and `not-found` for a page that is not in this\n * document.\n */\n readTextInRange(range: TextRange, options?: OperationOptions): Promise<string>;\n\n // ── events ──\n /** The range or its segments changed, whoever changed them. */\n readonly onChanged: EventHook<SelectionChangedEvent>;\n /** A selection gesture ended with a selection in place. */\n readonly onCommitted: EventHook<SelectionCommittedEvent>;\n /** The selection went from a range to nothing: a clear, an empty range, or\n * its pages' content changed or left the document. */\n readonly onCleared: EventHook<SelectionClearedEvent>;\n}\n\nexport { SelectionToken } from './token';\n"],"mappings":";;;AAMA,MAAa,kBAAA,2BAAA,CAAA,CAAA,sBAAA,CAA4D,aAAa;CACpF,MAAM;CAGN,UAAU;EACR,UAAU;EACV,iBAAiB;CACnB;AACF,CAAC;;;;AC+BD,MAAa,qBAAwC;CACnD,eAAe;CACf,OAAO;CACP,SAAS;EAAE,OAAO;EAAM,QAAQ;CAA8B;AAChE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createCapabilityToken } from "@embedpdf/core";
|
|
2
|
+
//#region src/token.ts
|
|
3
|
+
/** The package token — created once here; `contract.ts` re-exports it and
|
|
4
|
+
* `host-contract.ts` widens it. */
|
|
5
|
+
const SelectionToken = createCapabilityToken("selection", {
|
|
6
|
+
hint: `add selectionPlugin() from '@embedpdf/plugin-selection' to your plugins list`,
|
|
7
|
+
promises: {
|
|
8
|
+
readText: true,
|
|
9
|
+
readTextInRange: true
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/contract.ts
|
|
14
|
+
/** What the selection settings are when the app registers none. */
|
|
15
|
+
const SELECTION_DEFAULTS = {
|
|
16
|
+
dragThreshold: 4,
|
|
17
|
+
color: null,
|
|
18
|
+
handles: {
|
|
19
|
+
color: null,
|
|
20
|
+
shadow: "0 1px 4px rgb(0 0 0 / 0.35)"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { SelectionToken as n, SELECTION_DEFAULTS as t };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=contract-DBXA64ep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-DBXA64ep.js","names":[],"sources":["../src/token.ts","../src/contract.ts"],"sourcesContent":["/** The package token — created once here; `contract.ts` re-exports it and\n * `host-contract.ts` widens it. */\nimport { createCapabilityToken } from '@embedpdf/core';\n\nimport type { SelectionCapability } from './contract';\n\nexport const SelectionToken = createCapabilityToken<SelectionCapability>('selection', {\n hint: `add selectionPlugin() from '@embedpdf/plugin-selection' to your plugins list`,\n // Without a document, an adapter's stand-in rejects these with `not-ready`, as the\n // capability would; the type asks for every member that returns a promise.\n promises: {\n readText: true,\n readTextInRange: true,\n },\n});\n","/**\n * @embedpdf/plugin-selection/contract — the public selection vocabulary.\n *\n * Selection ranges live in character space (half-open `TextRange`, the same\n * space search hits address). Geometry needs `doc.text.select`, text\n * extraction needs `doc.text.copy`, and neither permission implies the other.\n * Segments, endpoints and anchors are in page space (page space: y-down,\n * PDF units, crop-relative), the space every layer paints in.\n */\nimport type {\n DeepPartial,\n EventHook,\n OperationOptions,\n PageRef,\n SettingsApi,\n} from '@embedpdf/core';\nimport type { Point, Rect, Quad } from '@embedpdf/core-geometry';\nimport type { SelectionSegment } from './geometry';\n\nexport type { SelectionSegment } from './geometry';\n\n// ── settings ────────────────────────────────────────────────────────────────\n\n/**\n * The selection plugin's settings. `selectionPlugin(config)` registers them\n * over {@link SELECTION_DEFAULTS}, and `updateSettings()` changes them for\n * every document while the app runs. The colors and the shadow can also come\n * from CSS (`--epdf-text-selection`, `--epdf-text-selection-handle`,\n * `--epdf-text-selection-handle-shadow`), which wins over the setting.\n */\nexport interface SelectionSettings {\n /** How far, in viewport pixels, the pointer travels before a press becomes a drag that selects. */\n readonly dragThreshold: number;\n /** The color of selected text: a CSS color, or `null` for the viewer's accent at 35%. */\n readonly color: string | null;\n /** The grips at the selection's ends, on touch screens. */\n readonly handles: {\n /** A CSS color, or `null` for the viewer's accent. */\n readonly color: string | null;\n /** A CSS `box-shadow`. */\n readonly shadow: string;\n };\n}\n\n/** What the selection settings are when the app registers none. */\nexport const SELECTION_DEFAULTS: SelectionSettings = {\n dragThreshold: 4,\n color: null,\n handles: { color: null, shadow: '0 1px 4px rgb(0 0 0 / 0.35)' },\n};\n\n/** What `selectionPlugin(config)` takes: any of the settings, merged over the defaults. */\nexport type SelectionConfig = DeepPartial<SelectionSettings>;\n\n// ── the range vocabulary ────────────────────────────────────────────────────\n\n/**\n * A position in a page's character space — the space the engine's geometry\n * runs tile (`PageGeometryRun.charStart`) and search hits address\n * (`SearchMatch.charStart`). Not a string offset into extracted text; the\n * two spaces are joined by the engine's `charMap` (see engine-core\n * `text/charmap.ts`), which `readText()` applies for you.\n */\nexport interface TextPosition {\n page: PageRef;\n /** Character index, 0-based. */\n index: number;\n}\n\n/**\n * A half-open range in character space: `start` inclusive, `end` exclusive,\n * in document order (`start` at or before `end`). `end.index` may be 0 to\n * end a range exactly at a page boundary.\n */\nexport interface TextRange {\n start: TextPosition;\n end: TextPosition;\n}\n\n/**\n * What {@link SelectionCapability.select} accepts: a cross-page\n * {@link TextRange}, or a single-page span — the shape of a search hit, so\n * `select({ page: hit.page, start: hit.charStart, count: hit.charCount })`\n * needs no conversion.\n */\nexport type SelectionRangeInput = TextRange | { page: PageRef; start: number; count: number };\n\n// ── the read model ──────────────────────────────────────────────────────────\n\n/**\n * A selection boundary, anchored to the boundary glyph's own oriented cell.\n * `advance` is the reading direction of the segment it belongs to (+1 = the\n * frame's +x), so caret consumers place at the trailing edge without\n * re-deriving bidi from geometry. `rect` is the AABB (scroll targets).\n */\nexport interface SelectionEndpoint {\n page: PageRef;\n glyphQuad: Quad;\n advance: 1 | -1;\n rect: Rect;\n}\n\n/** Where selection-scoped floating UI attaches: a page + the selection's\n * union box on it, in page space. See {@link SelectionCapability.getAnchor}. */\nexport interface SelectionAnchor {\n page: PageRef;\n bounds: Rect;\n}\n\nexport interface SelectionSnapshot {\n /** Per-page canonical segments — the one geometry consumers act on.\n * Boxes are derived views (`segment.rect`, or `listRects()`). */\n readonly pages: readonly { page: PageRef; segments: readonly SelectionSegment[] }[];\n readonly start: SelectionEndpoint | null;\n readonly end: SelectionEndpoint | null;\n readonly direction: 'forward' | 'backward';\n /**\n * The selection as a half-open character range in document order — a\n * valid {@link SelectionCapability.select} input (persist and restore).\n * Null when nothing is selected. Until a boundary page's text geometry\n * has loaded, its index may still exceed the page's character count\n * (`selectAll` settles as geometry arrives); consumers of the range\n * (`select`, `readTextInRange`) clamp, so round-tripping is always safe.\n */\n readonly range: TextRange | null;\n}\n\n// ── events ──────────────────────────────────────────────────────────────────\n\n/**\n * The selection's range or segments changed: a gesture step, a programmatic\n * select, a boundary page's text geometry arriving, or a clear. Selection is\n * session state, so the event carries no document origin.\n */\nexport interface SelectionChangedEvent {\n readonly range: TextRange | null;\n /** The pages that carry a segment right now. */\n readonly pages: readonly PageRef[];\n}\n\n/** A selection gesture ended (pointer-up, handle release) with a selection in\n * place — the commit point markup creation and clipboard prefetch act on.\n * Never fires for programmatic selection. */\nexport interface SelectionCommittedEvent {\n readonly range: TextRange;\n}\n\n/** The selection went from a range to nothing. */\nexport type SelectionClearedEvent = Record<string, never>;\n\n// ── the public capability ───────────────────────────────────────────────────\n\n/**\n * The public selection API — the documented, stable surface for application\n * code (toolbars, context menus, automation).\n *\n * The permission model: geometry enables selection (`doc.text.select`),\n * text enables extraction (`doc.text.copy`) — neither implies the other.\n * Everything here except the `readText` pair works with the select scope\n * alone, so a deployment can allow selecting and highlighting while denying\n * copy. Writes without the scope throw `PluginError('permission-denied')`;\n * gate UI with {@link canSelect} / {@link canCopy}.\n *\n * Every gesture has a programmatic twin: drag = {@link select} (or\n * `beginGestureAt` + {@link extendTo} for point-driven code on the host\n * lens), double-click = {@link selectWordAt}, triple-click =\n * {@link selectLineAt}, handle drag = {@link extendTo}, click on empty space\n * = {@link clear}, select-all = {@link selectAll}.\n *\n * A page argument is a `PageRef` or a zero-based index. A verb given a page\n * that isn't in the document throws `not-found`; a read returns empty.\n *\n * The settings (`getSettings`, `updateSettings`, `resetSettings`,\n * `onSettingsChanged`) belong to the plugin, not to a document: a change\n * reaches every open document.\n *\n * Framework-only plumbing (gesture bracketing, geometry warming, the\n * highlight-visibility handshake) lives on `SelectionHostCapability`,\n * reachable through `@embedpdf/plugin-selection/contract/host`. Both are the\n * same runtime object — two typed lenses on one token.\n */\nexport interface SelectionCapability extends SettingsApi<SelectionSettings> {\n // ── authorization (mirrors the engine's own enforcement) ──\n /** Whether this caller may create selections at all (`doc.text.select`). */\n canSelect(): boolean;\n /** Whether this caller may extract literal text (`doc.text.copy`). */\n canCopy(): boolean;\n\n // ── writes (character space, half-open) ──\n /**\n * Select a range — the same path gestures use, so the highlight, events\n * and markup bridges behave identically. An empty range clears. Throws\n * `permission-denied` without `doc.text.select`, `not-found` for a page\n * that is not in this document. Fires `onChanged`, or `onCleared`.\n */\n select(range: SelectionRangeInput): void;\n /** Select every character of the document. Throws `permission-denied` without `doc.text.select`. */\n selectAll(): void;\n /**\n * Select every character on one page. Throws `permission-denied` without\n * `doc.text.select`, `not-found` for a page that is not in this document.\n */\n selectPage(page: PageRef | number): void;\n /**\n * Select the word around a page point. Returns false when the point has no\n * selectable text (geometry not loaded yet, or no glyph there). Throws\n * `permission-denied` without `doc.text.select`, `not-found` for a page that\n * is not in this document.\n */\n selectWordAt(page: PageRef | number, point: Point): boolean;\n /** Select the visual line around a page point. Same result and errors as {@link selectWordAt}. */\n selectLineAt(page: PageRef | number, point: Point): boolean;\n /**\n * Extend the current selection to a page point (a drag step). No selection\n * → no-op; a page whose geometry has not loaded is warmed and the extension\n * lands when it arrives. Errors as {@link selectPage}.\n */\n extendTo(page: PageRef | number, point: Point): void;\n /** Clear the selection. Always allowed. Fires `onCleared` when something was selected. */\n clear(): void;\n\n // ── reads ──\n /** Whether anything is selected. */\n hasSelection(): boolean;\n /**\n * Whether the user is still selecting: from the press of a drag, a\n * double-click or a handle until it lifts. A selection made from code is\n * never in progress.\n */\n isSelecting(): boolean;\n /** Per-page segments, endpoints, direction and the range. Reference-stable\n * until the selection changes. */\n getSnapshot(): SelectionSnapshot;\n /** The selected character range, or null. */\n getRange(): TextRange | null;\n /** The pages the current selection covers (those with at least one\n * segment), in document order — so a cross-page action can fan out per page. */\n listSelectedPages(): readonly PageRef[];\n /** Per-line oriented segments for a page, in page space — build your own\n * highlight layer from these. Reference-stable per page. */\n listSegments(page: PageRef | number): readonly SelectionSegment[];\n /** The segments' AABBs — for consumers that genuinely want boxes (scroll,\n * conservative regions). Never a substitute for the oriented quads in\n * geometry that gets drawn or persisted. */\n listRects(page: PageRef | number): readonly Rect[];\n /**\n * Where selection-scoped floating UI should attach: the union box of the\n * selection's segments on its end page (where the gesture finished),\n * falling back to the last page with materialized segments while a\n * boundary page's geometry is still loading. One anchor regardless of\n * cross-page selection. Null when nothing is selected (or nothing has\n * materialized yet).\n */\n getAnchor(): SelectionAnchor | null;\n\n // ── text extraction (requires doc.text.copy) ──\n /**\n * The selected text. Each page's text snapshot is fetched once per content\n * version and sliced through the engine's `charMap`; pages are joined with\n * `\\n`. Resolves `''` when nothing is selected. Rejects `permission-denied`\n * without `doc.text.copy`, and `operation-cancelled` when `options.signal`\n * fires. Clipboard writes are deliberately not here — this package is\n * DOM-free; use `@embedpdf/web`'s clipboard helpers.\n */\n readText(options?: OperationOptions): Promise<string>;\n /**\n * Text for any range, without touching the selection. Rejects as\n * {@link readText} does, and `not-found` for a page that is not in this\n * document.\n */\n readTextInRange(range: TextRange, options?: OperationOptions): Promise<string>;\n\n // ── events ──\n /** The range or its segments changed, whoever changed them. */\n readonly onChanged: EventHook<SelectionChangedEvent>;\n /** A selection gesture ended with a selection in place. */\n readonly onCommitted: EventHook<SelectionCommittedEvent>;\n /** The selection went from a range to nothing: a clear, an empty range, or\n * its pages' content changed or left the document. */\n readonly onCleared: EventHook<SelectionClearedEvent>;\n}\n\nexport { SelectionToken } from './token';\n"],"mappings":";;;;AAMA,MAAa,iBAAiB,sBAA2C,aAAa;CACpF,MAAM;CAGN,UAAU;EACR,UAAU;EACV,iBAAiB;CACnB;AACF,CAAC;;;;AC+BD,MAAa,qBAAwC;CACnD,eAAe;CACf,OAAO;CACP,SAAS;EAAE,OAAO;EAAM,QAAQ;CAA8B;AAChE"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { DeepPartial, EventHook, OperationOptions, PageRef, SettingsApi } from "@embedpdf/core";
|
|
2
|
+
import { Point, Quad, Rect } from "@embedpdf/core-geometry";
|
|
3
|
+
import { PdfTextSegment } from "@embedpdf/engine-core/runtime";
|
|
4
|
+
//#region src/geometry.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* One merged visual line of a selection, as the engine's layout gives it.
|
|
7
|
+
* `quad` carries the corners, named in the line's own frame; `advance` is the
|
|
8
|
+
* reading direction along the baseline (+1 = toward the right end), derived
|
|
9
|
+
* from the glyph sequence, so geometry and bidi stay separate concerns.
|
|
10
|
+
* `rect` is its bounding box.
|
|
11
|
+
*/
|
|
12
|
+
type SelectionSegment = PdfTextSegment;
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/token.d.ts
|
|
15
|
+
declare const SelectionToken: import("@embedpdf/core").CapabilityToken<SelectionCapability>;
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/contract.d.ts
|
|
18
|
+
/**
|
|
19
|
+
* The selection plugin's settings. `selectionPlugin(config)` registers them
|
|
20
|
+
* over {@link SELECTION_DEFAULTS}, and `updateSettings()` changes them for
|
|
21
|
+
* every document while the app runs. The colors and the shadow can also come
|
|
22
|
+
* from CSS (`--epdf-text-selection`, `--epdf-text-selection-handle`,
|
|
23
|
+
* `--epdf-text-selection-handle-shadow`), which wins over the setting.
|
|
24
|
+
*/
|
|
25
|
+
interface SelectionSettings {
|
|
26
|
+
/** How far, in viewport pixels, the pointer travels before a press becomes a drag that selects. */
|
|
27
|
+
readonly dragThreshold: number;
|
|
28
|
+
/** The color of selected text: a CSS color, or `null` for the viewer's accent at 35%. */
|
|
29
|
+
readonly color: string | null;
|
|
30
|
+
/** The grips at the selection's ends, on touch screens. */
|
|
31
|
+
readonly handles: {
|
|
32
|
+
/** A CSS color, or `null` for the viewer's accent. */
|
|
33
|
+
readonly color: string | null;
|
|
34
|
+
/** A CSS `box-shadow`. */
|
|
35
|
+
readonly shadow: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** What the selection settings are when the app registers none. */
|
|
39
|
+
declare const SELECTION_DEFAULTS: SelectionSettings;
|
|
40
|
+
/** What `selectionPlugin(config)` takes: any of the settings, merged over the defaults. */
|
|
41
|
+
type SelectionConfig = DeepPartial<SelectionSettings>;
|
|
42
|
+
/**
|
|
43
|
+
* A position in a page's character space — the space the engine's geometry
|
|
44
|
+
* runs tile (`PageGeometryRun.charStart`) and search hits address
|
|
45
|
+
* (`SearchMatch.charStart`). Not a string offset into extracted text; the
|
|
46
|
+
* two spaces are joined by the engine's `charMap` (see engine-core
|
|
47
|
+
* `text/charmap.ts`), which `readText()` applies for you.
|
|
48
|
+
*/
|
|
49
|
+
interface TextPosition {
|
|
50
|
+
page: PageRef;
|
|
51
|
+
/** Character index, 0-based. */
|
|
52
|
+
index: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A half-open range in character space: `start` inclusive, `end` exclusive,
|
|
56
|
+
* in document order (`start` at or before `end`). `end.index` may be 0 to
|
|
57
|
+
* end a range exactly at a page boundary.
|
|
58
|
+
*/
|
|
59
|
+
interface TextRange {
|
|
60
|
+
start: TextPosition;
|
|
61
|
+
end: TextPosition;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* What {@link SelectionCapability.select} accepts: a cross-page
|
|
65
|
+
* {@link TextRange}, or a single-page span — the shape of a search hit, so
|
|
66
|
+
* `select({ page: hit.page, start: hit.charStart, count: hit.charCount })`
|
|
67
|
+
* needs no conversion.
|
|
68
|
+
*/
|
|
69
|
+
type SelectionRangeInput = TextRange | {
|
|
70
|
+
page: PageRef;
|
|
71
|
+
start: number;
|
|
72
|
+
count: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A selection boundary, anchored to the boundary glyph's own oriented cell.
|
|
76
|
+
* `advance` is the reading direction of the segment it belongs to (+1 = the
|
|
77
|
+
* frame's +x), so caret consumers place at the trailing edge without
|
|
78
|
+
* re-deriving bidi from geometry. `rect` is the AABB (scroll targets).
|
|
79
|
+
*/
|
|
80
|
+
interface SelectionEndpoint {
|
|
81
|
+
page: PageRef;
|
|
82
|
+
glyphQuad: Quad;
|
|
83
|
+
advance: 1 | -1;
|
|
84
|
+
rect: Rect;
|
|
85
|
+
}
|
|
86
|
+
/** Where selection-scoped floating UI attaches: a page + the selection's
|
|
87
|
+
* union box on it, in page space. See {@link SelectionCapability.getAnchor}. */
|
|
88
|
+
interface SelectionAnchor {
|
|
89
|
+
page: PageRef;
|
|
90
|
+
bounds: Rect;
|
|
91
|
+
}
|
|
92
|
+
interface SelectionSnapshot {
|
|
93
|
+
/** Per-page canonical segments — the one geometry consumers act on.
|
|
94
|
+
* Boxes are derived views (`segment.rect`, or `listRects()`). */
|
|
95
|
+
readonly pages: readonly {
|
|
96
|
+
page: PageRef;
|
|
97
|
+
segments: readonly SelectionSegment[];
|
|
98
|
+
}[];
|
|
99
|
+
readonly start: SelectionEndpoint | null;
|
|
100
|
+
readonly end: SelectionEndpoint | null;
|
|
101
|
+
readonly direction: 'forward' | 'backward';
|
|
102
|
+
/**
|
|
103
|
+
* The selection as a half-open character range in document order — a
|
|
104
|
+
* valid {@link SelectionCapability.select} input (persist and restore).
|
|
105
|
+
* Null when nothing is selected. Until a boundary page's text geometry
|
|
106
|
+
* has loaded, its index may still exceed the page's character count
|
|
107
|
+
* (`selectAll` settles as geometry arrives); consumers of the range
|
|
108
|
+
* (`select`, `readTextInRange`) clamp, so round-tripping is always safe.
|
|
109
|
+
*/
|
|
110
|
+
readonly range: TextRange | null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The selection's range or segments changed: a gesture step, a programmatic
|
|
114
|
+
* select, a boundary page's text geometry arriving, or a clear. Selection is
|
|
115
|
+
* session state, so the event carries no document origin.
|
|
116
|
+
*/
|
|
117
|
+
interface SelectionChangedEvent {
|
|
118
|
+
readonly range: TextRange | null;
|
|
119
|
+
/** The pages that carry a segment right now. */
|
|
120
|
+
readonly pages: readonly PageRef[];
|
|
121
|
+
}
|
|
122
|
+
/** A selection gesture ended (pointer-up, handle release) with a selection in
|
|
123
|
+
* place — the commit point markup creation and clipboard prefetch act on.
|
|
124
|
+
* Never fires for programmatic selection. */
|
|
125
|
+
interface SelectionCommittedEvent {
|
|
126
|
+
readonly range: TextRange;
|
|
127
|
+
}
|
|
128
|
+
/** The selection went from a range to nothing. */
|
|
129
|
+
type SelectionClearedEvent = Record<string, never>;
|
|
130
|
+
/**
|
|
131
|
+
* The public selection API — the documented, stable surface for application
|
|
132
|
+
* code (toolbars, context menus, automation).
|
|
133
|
+
*
|
|
134
|
+
* The permission model: geometry enables selection (`doc.text.select`),
|
|
135
|
+
* text enables extraction (`doc.text.copy`) — neither implies the other.
|
|
136
|
+
* Everything here except the `readText` pair works with the select scope
|
|
137
|
+
* alone, so a deployment can allow selecting and highlighting while denying
|
|
138
|
+
* copy. Writes without the scope throw `PluginError('permission-denied')`;
|
|
139
|
+
* gate UI with {@link canSelect} / {@link canCopy}.
|
|
140
|
+
*
|
|
141
|
+
* Every gesture has a programmatic twin: drag = {@link select} (or
|
|
142
|
+
* `beginGestureAt` + {@link extendTo} for point-driven code on the host
|
|
143
|
+
* lens), double-click = {@link selectWordAt}, triple-click =
|
|
144
|
+
* {@link selectLineAt}, handle drag = {@link extendTo}, click on empty space
|
|
145
|
+
* = {@link clear}, select-all = {@link selectAll}.
|
|
146
|
+
*
|
|
147
|
+
* A page argument is a `PageRef` or a zero-based index. A verb given a page
|
|
148
|
+
* that isn't in the document throws `not-found`; a read returns empty.
|
|
149
|
+
*
|
|
150
|
+
* The settings (`getSettings`, `updateSettings`, `resetSettings`,
|
|
151
|
+
* `onSettingsChanged`) belong to the plugin, not to a document: a change
|
|
152
|
+
* reaches every open document.
|
|
153
|
+
*
|
|
154
|
+
* Framework-only plumbing (gesture bracketing, geometry warming, the
|
|
155
|
+
* highlight-visibility handshake) lives on `SelectionHostCapability`,
|
|
156
|
+
* reachable through `@embedpdf/plugin-selection/contract/host`. Both are the
|
|
157
|
+
* same runtime object — two typed lenses on one token.
|
|
158
|
+
*/
|
|
159
|
+
interface SelectionCapability extends SettingsApi<SelectionSettings> {
|
|
160
|
+
/** Whether this caller may create selections at all (`doc.text.select`). */
|
|
161
|
+
canSelect(): boolean;
|
|
162
|
+
/** Whether this caller may extract literal text (`doc.text.copy`). */
|
|
163
|
+
canCopy(): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Select a range — the same path gestures use, so the highlight, events
|
|
166
|
+
* and markup bridges behave identically. An empty range clears. Throws
|
|
167
|
+
* `permission-denied` without `doc.text.select`, `not-found` for a page
|
|
168
|
+
* that is not in this document. Fires `onChanged`, or `onCleared`.
|
|
169
|
+
*/
|
|
170
|
+
select(range: SelectionRangeInput): void;
|
|
171
|
+
/** Select every character of the document. Throws `permission-denied` without `doc.text.select`. */
|
|
172
|
+
selectAll(): void;
|
|
173
|
+
/**
|
|
174
|
+
* Select every character on one page. Throws `permission-denied` without
|
|
175
|
+
* `doc.text.select`, `not-found` for a page that is not in this document.
|
|
176
|
+
*/
|
|
177
|
+
selectPage(page: PageRef | number): void;
|
|
178
|
+
/**
|
|
179
|
+
* Select the word around a page point. Returns false when the point has no
|
|
180
|
+
* selectable text (geometry not loaded yet, or no glyph there). Throws
|
|
181
|
+
* `permission-denied` without `doc.text.select`, `not-found` for a page that
|
|
182
|
+
* is not in this document.
|
|
183
|
+
*/
|
|
184
|
+
selectWordAt(page: PageRef | number, point: Point): boolean;
|
|
185
|
+
/** Select the visual line around a page point. Same result and errors as {@link selectWordAt}. */
|
|
186
|
+
selectLineAt(page: PageRef | number, point: Point): boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Extend the current selection to a page point (a drag step). No selection
|
|
189
|
+
* → no-op; a page whose geometry has not loaded is warmed and the extension
|
|
190
|
+
* lands when it arrives. Errors as {@link selectPage}.
|
|
191
|
+
*/
|
|
192
|
+
extendTo(page: PageRef | number, point: Point): void;
|
|
193
|
+
/** Clear the selection. Always allowed. Fires `onCleared` when something was selected. */
|
|
194
|
+
clear(): void;
|
|
195
|
+
/** Whether anything is selected. */
|
|
196
|
+
hasSelection(): boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Whether the user is still selecting: from the press of a drag, a
|
|
199
|
+
* double-click or a handle until it lifts. A selection made from code is
|
|
200
|
+
* never in progress.
|
|
201
|
+
*/
|
|
202
|
+
isSelecting(): boolean;
|
|
203
|
+
/** Per-page segments, endpoints, direction and the range. Reference-stable
|
|
204
|
+
* until the selection changes. */
|
|
205
|
+
getSnapshot(): SelectionSnapshot;
|
|
206
|
+
/** The selected character range, or null. */
|
|
207
|
+
getRange(): TextRange | null;
|
|
208
|
+
/** The pages the current selection covers (those with at least one
|
|
209
|
+
* segment), in document order — so a cross-page action can fan out per page. */
|
|
210
|
+
listSelectedPages(): readonly PageRef[];
|
|
211
|
+
/** Per-line oriented segments for a page, in page space — build your own
|
|
212
|
+
* highlight layer from these. Reference-stable per page. */
|
|
213
|
+
listSegments(page: PageRef | number): readonly SelectionSegment[];
|
|
214
|
+
/** The segments' AABBs — for consumers that genuinely want boxes (scroll,
|
|
215
|
+
* conservative regions). Never a substitute for the oriented quads in
|
|
216
|
+
* geometry that gets drawn or persisted. */
|
|
217
|
+
listRects(page: PageRef | number): readonly Rect[];
|
|
218
|
+
/**
|
|
219
|
+
* Where selection-scoped floating UI should attach: the union box of the
|
|
220
|
+
* selection's segments on its end page (where the gesture finished),
|
|
221
|
+
* falling back to the last page with materialized segments while a
|
|
222
|
+
* boundary page's geometry is still loading. One anchor regardless of
|
|
223
|
+
* cross-page selection. Null when nothing is selected (or nothing has
|
|
224
|
+
* materialized yet).
|
|
225
|
+
*/
|
|
226
|
+
getAnchor(): SelectionAnchor | null;
|
|
227
|
+
/**
|
|
228
|
+
* The selected text. Each page's text snapshot is fetched once per content
|
|
229
|
+
* version and sliced through the engine's `charMap`; pages are joined with
|
|
230
|
+
* `\n`. Resolves `''` when nothing is selected. Rejects `permission-denied`
|
|
231
|
+
* without `doc.text.copy`, and `operation-cancelled` when `options.signal`
|
|
232
|
+
* fires. Clipboard writes are deliberately not here — this package is
|
|
233
|
+
* DOM-free; use `@embedpdf/web`'s clipboard helpers.
|
|
234
|
+
*/
|
|
235
|
+
readText(options?: OperationOptions): Promise<string>;
|
|
236
|
+
/**
|
|
237
|
+
* Text for any range, without touching the selection. Rejects as
|
|
238
|
+
* {@link readText} does, and `not-found` for a page that is not in this
|
|
239
|
+
* document.
|
|
240
|
+
*/
|
|
241
|
+
readTextInRange(range: TextRange, options?: OperationOptions): Promise<string>;
|
|
242
|
+
/** The range or its segments changed, whoever changed them. */
|
|
243
|
+
readonly onChanged: EventHook<SelectionChangedEvent>;
|
|
244
|
+
/** A selection gesture ended with a selection in place. */
|
|
245
|
+
readonly onCommitted: EventHook<SelectionCommittedEvent>;
|
|
246
|
+
/** The selection went from a range to nothing: a clear, an empty range, or
|
|
247
|
+
* its pages' content changed or left the document. */
|
|
248
|
+
readonly onCleared: EventHook<SelectionClearedEvent>;
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
export { SelectionClearedEvent as a, SelectionEndpoint as c, SelectionSnapshot as d, TextPosition as f, SelectionSegment as h, SelectionChangedEvent as i, SelectionRangeInput as l, SelectionToken as m, SelectionAnchor as n, SelectionCommittedEvent as o, TextRange as p, SelectionCapability as r, SelectionConfig as s, SELECTION_DEFAULTS as t, SelectionSettings as u };
|
|
252
|
+
//# sourceMappingURL=contract-DLs4vXVt.d.cts.map
|