@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
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reducer-BAOQ2CJ8.cjs","names":["PermissionDenied"],"sources":["../src/geometry.ts","../src/capability.ts","../src/handler.ts","../src/reducer.ts"],"sourcesContent":["/**\n * The selection plugin's COORDINATE SEAM — and nothing else.\n *\n * Segmentation, hit-testing, and word/line expansion live in the canonical\n * engine-core text layout (`@embedpdf/engine-core` `text/layout`): a text\n * range has exactly one segmentation whether it came from a drag or a\n * search. This module only converts between the viewer's content space\n * (y-down, crop-relative) and the engine's PDF space (y-up) — pointer\n * points inward, canonical segments outward. The PDF↔content y-flip is the\n * geometry package's `pageGeometry` (the one place that math lives), never\n * hand-rolled here.\n */\nimport {\n applyPoint,\n invert,\n pageGeometry,\n textQuadBounds,\n type Mat2D,\n type Point,\n type PointIn,\n type Rect,\n type TextQuad,\n} from '@embedpdf/core-geometry';\nimport {\n buildPageTextLayout,\n type PageGeometrySnapshot,\n type PageTextLayout,\n type PdfPoint,\n type PdfQuad,\n type PdfRect,\n type PdfTextSegment,\n} from '@embedpdf/engine-core/runtime';\n\n/**\n * One merged visual line of a selection, in content space — the structural\n * twin of the engine's `PdfTextSegment`. `quad` carries frame-geometric\n * corner semantics (upper = ascent side, start = the frame's −x); `advance`\n * is the READING direction along the baseline (+1 = toward `end`), derived\n * from the glyph sequence — geometry and bidi stay separate concerns.\n * `rect` is the content-space AABB.\n */\nexport interface SelectionSegment {\n quad: TextQuad;\n rect: Rect;\n advance: 1 | -1;\n}\n\n/** A page's cached selection geometry: the canonical layout + the seam. */\nexport interface SelectionPageGeometry {\n layout: PageTextLayout;\n toContent: Mat2D<'pdf', 'content'>;\n fromContent: Mat2D<'content', 'pdf'>;\n}\n\n/**\n * Build a page's selection geometry. Page display rotation does NOT enter\n * here — the overlay rides the page's CSS rotation, so content space stays\n * un-rotated (the crop-relative y-flip is the only conversion; zoom = 1,\n * the viewer's zoom is applied later by `PageTransform.toPixels`).\n */\nexport function buildSelectionPageGeometry(\n snapshot: PageGeometrySnapshot,\n crop: PdfRect,\n rotation: 0 | 90 | 180 | 270,\n userUnit: number,\n): SelectionPageGeometry {\n const { pdfToContent } = pageGeometry({ crop, rotation, userUnit }, 1);\n return {\n layout: buildPageTextLayout(snapshot),\n toContent: pdfToContent,\n fromContent: invert(pdfToContent),\n };\n}\n\n/** A content-space pointer point in the layout's PDF space. */\nexport function contentPointToPdf(geom: SelectionPageGeometry, p: Point): PdfPoint {\n return applyPoint(geom.fromContent, p as PointIn<'content'>);\n}\n\n/**\n * A canonical PDF quad in content space. Engine quads carry frame-geometric\n * slot semantics (`p1..p4` = upper-start, upper-end, lower-start,\n * lower-end) — a trusted producer, so the y-flip maps corners straight onto\n * their names; imported-annotation normalization does NOT apply here.\n */\nexport function toContentTextQuad(geom: SelectionPageGeometry, quad: PdfQuad): TextQuad {\n const pt = (p: PdfPoint): Point => applyPoint(geom.toContent, p as PointIn<'pdf'>);\n return {\n upperStart: pt(quad.p1),\n upperEnd: pt(quad.p2),\n lowerStart: pt(quad.p3),\n lowerEnd: pt(quad.p4),\n };\n}\n\n/** A canonical segment in content space (`rect` recomputed from the mapped\n * quad so the pair can never drift). */\nexport function toContentSegment(\n geom: SelectionPageGeometry,\n segment: PdfTextSegment,\n): SelectionSegment {\n const quad = toContentTextQuad(geom, segment.quad);\n return { quad, rect: textQuadBounds(quad), advance: segment.advance };\n}\n","import type { PageObjectNumber, PluginContext } from '@embedpdf/core';\nimport { textQuadBounds, type Point, type Rect } from '@embedpdf/core-geometry';\nimport {\n expandTextRangeToLine,\n expandTextRangeToWord,\n PermissionDenied,\n sliceTextByChars,\n textGlyphAt,\n textGlyphQuad,\n textSegmentsForRange,\n type PageGeometrySnapshot,\n type PageTextSnapshot,\n} from '@embedpdf/engine-core/runtime';\nimport {\n buildSelectionPageGeometry,\n contentPointToPdf,\n toContentSegment,\n toContentTextQuad,\n type SelectionPageGeometry,\n type SelectionSegment,\n} from './geometry';\nimport type {\n GlyphPointer,\n SelectionAction,\n SelectionEndpoint,\n SelectionHostCapability,\n SelectionMenuAnchor,\n SelectionRange,\n SelectionRangeInput,\n SelectionSnapshot,\n SelectionState,\n TextRange,\n} from './types';\n\nconst EMPTY_SEGMENTS: SelectionSegment[] = [];\n\n/** How many page-text reads `readText()` keeps in flight at once. */\nconst TEXT_READ_CONCURRENCY = 8;\n\n/**\n * The selection capability — ONE closure returning the host lens (the\n * public lens is the same object, narrowed at the package root).\n *\n * State model: the reducer holds the selection range and the derived\n * content-space segments; the large, non-serializable per-page caches live\n * HERE in the closure, split by what invalidates them:\n *\n * - `rawGeometry` — PDF-space geometry snapshots, rotation-independent\n * (pages load normalized; see `PageRotateResult`). Dropped only when a\n * page leaves the registry or page CONTENT changes (redaction apply /\n * flatten).\n * - `derived` — the content-space transform + layout, keyed by the\n * layout params (crop/rotation/userUnit) so a view-rotate re-derives\n * from the cached raw snapshot with NO refetch.\n * - `textSnapshots` — per-page text (for `readText`), same content-only\n * invalidation as `rawGeometry`.\n *\n * Permission model: `doc.text.select` gates geometry (selection exists),\n * `doc.text.copy` gates text (extraction) — neither implies the other.\n * Host gesture functions are INERT when select is denied (`ensurePage`\n * no-ops, so nothing warms and nothing hit-tests: the pointer handler\n * needs no special-casing); the public `select()` THROWS `PermissionDenied`\n * so programmatic misuse is loud; `clear()` is always allowed. The engine\n * independently enforces both scopes — these gates exist so the plugin\n * never issues a request that is guaranteed to fail.\n *\n * Selection is cross-page: glyphs are ordered globally by (pageIndex,\n * glyph), so a drag from page 2 into page 4 selects the tail of 2, all of\n * 3, and the head of 4. `recompute` rebuilds the merged line segments for\n * every loaded page in the span, re-runs whenever a mid-span page finishes\n * loading, and CLAMPS stored endpoints once their page's geometry is known\n * (so `selectAll`'s open-ended focus settles to the real last character).\n */\nexport function createSelectionCapability(\n ctx: PluginContext<SelectionState, SelectionAction>,\n): SelectionHostCapability {\n const rawGeometry = new Map<PageObjectNumber, PageGeometrySnapshot>();\n const derived = new Map<PageObjectNumber, { key: string; geom: SelectionPageGeometry }>();\n const pending = new Set<PageObjectNumber>();\n const textSnapshots = new Map<PageObjectNumber, Promise<PageTextSnapshot>>();\n /** Bumped on content invalidation; in-flight reads from before are discarded. */\n let epoch = 0;\n // Consumers (e.g. text-markup) observe the selection without selection knowing\n // about them: `change` fires whenever the segments change, `commit` when a\n // gesture ends (pointer-up). One typed callback each — not an event bus.\n const changeCbs = new Set<() => void>();\n const commitCbs = new Set<() => void>();\n const fireChange = (): void => changeCbs.forEach((cb) => cb());\n\n const canSelect = (): boolean => ctx.doc?.security.allows('doc.text.select') ?? false;\n const canCopy = (): boolean => ctx.doc?.security.allows('doc.text.copy') ?? false;\n\n const layoutOf = (pon: PageObjectNumber) =>\n ctx.document()?.pages.find((p) => p.pageObjectNumber === pon);\n const pageIndexOf = (pon: PageObjectNumber): number =>\n ctx.document()?.pages.findIndex((p) => p.pageObjectNumber === pon) ?? -1;\n const ponAtIndex = (i: number): PageObjectNumber | undefined =>\n ctx.document()?.pages[i]?.pageObjectNumber;\n\n /**\n * The content-space geometry for a page, derived on demand from the raw\n * snapshot + the CURRENT layout params. A view-rotate (or crop change)\n * changes the key and re-derives — raw caches and the engine are never\n * touched (rotation is presentation metadata).\n */\n function geometryFor(pon: PageObjectNumber): SelectionPageGeometry | null {\n const raw = rawGeometry.get(pon);\n const layout = layoutOf(pon);\n if (!raw || !layout) return null;\n const crop = layout.boxes.crop;\n const key = `${layout.rotation}|${layout.userUnit}|${crop.left},${crop.bottom},${crop.right},${crop.top}`;\n const hit = derived.get(pon);\n if (hit && hit.key === key) return hit.geom;\n const geom = buildSelectionPageGeometry(raw, crop, layout.rotation, layout.userUnit);\n derived.set(pon, { key, geom });\n return geom;\n }\n\n const glyphAt = (geom: SelectionPageGeometry, point: Point): number | null =>\n textGlyphAt(geom.layout, contentPointToPdf(geom, point));\n\n // Order the two ends of a selection by document position (page, then glyph).\n function orderedEnds(sel: SelectionRange): {\n start: GlyphPointer;\n end: GlyphPointer;\n direction: 'forward' | 'backward';\n } {\n const ai = pageIndexOf(sel.anchor.pon);\n const fi = pageIndexOf(sel.focus.pon);\n const anchorFirst = ai < fi || (ai === fi && sel.anchor.glyph <= sel.focus.glyph);\n return anchorFirst\n ? { start: sel.anchor, end: sel.focus, direction: 'forward' }\n : { start: sel.focus, end: sel.anchor, direction: 'backward' };\n }\n\n function endpointFor(ptr: GlyphPointer, which: 'start' | 'end'): SelectionEndpoint | null {\n const segments = ctx.getState().segments[ptr.pon] ?? EMPTY_SEGMENTS;\n if (!segments.length) return null;\n const segment = which === 'start' ? segments[0] : segments[segments.length - 1];\n\n // Anchor the endpoint to the boundary GLYPH's own oriented cell so caret\n // placement lands on the exact character edge; fall back to the segment\n // when the glyph is degenerate (e.g. a generated space).\n const geom = geometryFor(ptr.pon);\n const cell = geom ? textGlyphQuad(geom.layout, ptr.glyph) : null;\n if (geom && cell) {\n const glyphQuad = toContentTextQuad(geom, cell);\n return {\n pon: ptr.pon,\n glyphQuad,\n advance: segment.advance,\n rect: textQuadBounds(glyphQuad),\n };\n }\n return { pon: ptr.pon, glyphQuad: segment.quad, advance: segment.advance, rect: segment.rect };\n }\n\n /** Union box of a page's segments, or null when none have materialized. */\n function pageBounds(pon: PageObjectNumber): Rect | null {\n const segs = ctx.getState().segments[pon];\n if (!segs || segs.length === 0) return null;\n let x1 = Infinity;\n let y1 = Infinity;\n let x2 = -Infinity;\n let y2 = -Infinity;\n for (const s of segs) {\n x1 = Math.min(x1, s.rect.x);\n y1 = Math.min(y1, s.rect.y);\n x2 = Math.max(x2, s.rect.x + s.rect.width);\n y2 = Math.max(y2, s.rect.y + s.rect.height);\n }\n return { x: x1, y: y1, width: x2 - x1, height: y2 - y1 };\n }\n\n function menuAnchor(): SelectionMenuAnchor | null {\n const sel = ctx.getState().selection;\n if (!sel) return null;\n const { end } = orderedEnds(sel);\n // Prefer the gesture's end page; while its geometry is still loading,\n // fall back to the LAST page (document order) with materialized segments\n // so the anchor never teleports backwards mid-drag.\n let bounds = pageBounds(end.pon);\n if (bounds) return { pon: end.pon, bounds };\n const pages = ctx.document()?.pages ?? [];\n for (let i = pages.length - 1; i >= 0; i--) {\n const pon = pages[i].pageObjectNumber;\n bounds = pageBounds(pon);\n if (bounds) return { pon, bounds };\n }\n return null;\n }\n\n function snapshot(): SelectionSnapshot {\n const { selection, segments } = ctx.getState();\n const pages = Object.keys(segments)\n .map(Number)\n .filter((pon) => (segments[pon]?.length ?? 0) > 0)\n .map((pon) => ({ pon: pon as PageObjectNumber, segments: segments[pon] }));\n if (!selection) return { pages, start: null, end: null, direction: 'forward', range: null };\n const { start, end, direction } = orderedEnds(selection);\n return {\n pages,\n start: endpointFor(start, 'start'),\n end: endpointFor(end, 'end'),\n direction,\n range: {\n start: { pon: start.pon, index: start.glyph },\n end: { pon: end.pon, index: end.glyph + 1 },\n },\n };\n }\n\n function ensurePage(pon: PageObjectNumber): void {\n if (rawGeometry.has(pon) || pending.has(pon)) return;\n // Authorized-only warming: without doc.text.select the read is\n // guaranteed to be rejected — don't issue it. The engine guard stays\n // the security boundary either way.\n if (!canSelect()) return;\n const doc = ctx.doc;\n if (!doc || !layoutOf(pon)) return;\n pending.add(pon);\n const at = epoch;\n doc\n .page(pon)\n .geometry.read()\n .then(\n (snapshot) => {\n pending.delete(pon);\n if (at !== epoch) return; // content changed while in flight — stale\n rawGeometry.set(pon, snapshot);\n ctx.dispatch({ type: 'PAGE_LOADED', pon });\n if (ctx.getState().selection) recompute(); // a mid-span page arrived → fill its segments\n },\n () => {\n pending.delete(pon); // doc closed / read aborted / denied — ignore\n },\n );\n }\n\n /** Clamp a pointer into its page's real character range once geometry is\n * known — how `selectAll`'s open-ended focus settles. */\n function clampPointer(ptr: GlyphPointer): GlyphPointer {\n const geom = geometryFor(ptr.pon);\n if (!geom) return ptr;\n const max = Math.max(geom.layout.glyphs.length - 1, 0);\n const glyph = Math.max(0, Math.min(ptr.glyph, max));\n return glyph === ptr.glyph ? ptr : { pon: ptr.pon, glyph };\n }\n\n // Rebuild merged line segments for every loaded page in the span; warm the\n // rest (they recompute on arrival). Clears when an endpoint's page has left\n // the registry — a range across a structural edit is meaningless.\n function recompute(sel: SelectionRange | null = ctx.getState().selection): void {\n if (!sel) return;\n const clamped: SelectionRange = {\n anchor: clampPointer(sel.anchor),\n focus: clampPointer(sel.focus),\n };\n const { start, end } = orderedEnds(clamped);\n const si = pageIndexOf(start.pon);\n const ei = pageIndexOf(end.pon);\n if (si < 0 || ei < 0) {\n clearSelection();\n return;\n }\n const segments: Record<number, SelectionSegment[]> = {};\n for (let i = si; i <= ei; i++) {\n const pon = ponAtIndex(i);\n if (pon == null) continue;\n const geom = geometryFor(pon);\n if (!geom) {\n ensurePage(pon); // not loaded yet — it'll recompute when ready\n continue;\n }\n const from = i === si ? start.glyph : 0;\n const to = i === ei ? end.glyph : geom.layout.glyphs.length - 1;\n segments[pon] = textSegmentsForRange(geom.layout, from, to - from + 1).map((s) =>\n toContentSegment(geom, s),\n );\n }\n ctx.dispatch({ type: 'SET', selection: clamped, segments });\n fireChange();\n }\n\n /** Flip the gesture-in-flight FACT (see `SelectionState.selecting`). Set\n * BEFORE the recompute that fires `onChange`, so change listeners always\n * observe a coherent (selecting, segments) pair. */\n function setSelecting(selecting: boolean): void {\n ctx.dispatch({ type: 'SET_SELECTING', selecting });\n }\n\n function clearSelection(): void {\n setSelecting(false);\n ctx.dispatch({ type: 'CLEAR' });\n fireChange();\n }\n\n // Set the selection to a flat [from,to] glyph span on one page (word/line).\n // These are GESTURE vocabulary (double-/triple-click) — the commit arrives\n // at the pointer-up that follows, so the span counts as in-flight until then.\n // Returns whether a span actually engaged (geometry present AND a glyph\n // under the point) — the fact haptics and other success-gated feedback key\n // on, so nothing ever buzzes over blank space.\n function selectSpanAt(pon: PageObjectNumber, point: Point, expand: 'word' | 'line'): boolean {\n const geom = geometryFor(pon);\n if (!geom) return false;\n const i = glyphAt(geom, point);\n if (i == null) return false;\n const [from, to] =\n expand === 'word'\n ? expandTextRangeToWord(geom.layout, i)\n : expandTextRangeToLine(geom.layout, i);\n setSelecting(true);\n recompute({ anchor: { pon, glyph: from }, focus: { pon, glyph: to } });\n return true;\n }\n\n function assertCanSelect(context: string): void {\n if (!canSelect()) throw new PermissionDenied('doc.text.select', context);\n }\n\n /** The public programmatic entry: a half-open character range in. */\n function select(input: SelectionRangeInput): void {\n assertCanSelect('selection.select');\n const range: TextRange =\n 'pon' in input\n ? {\n start: { pon: input.pon, index: input.start },\n end: { pon: input.pon, index: input.start + input.count },\n }\n : input;\n const si = pageIndexOf(range.start.pon);\n let ei = pageIndexOf(range.end.pon);\n if (si < 0 || ei < 0) {\n throw new Error(\n `select: unknown page object ${si < 0 ? range.start.pon : range.end.pon}`,\n );\n }\n let endIndex = range.end.index;\n if (ei < si || (ei === si && endIndex <= range.start.index)) {\n clearSelection(); // empty range = no selection\n return;\n }\n if (endIndex === 0) {\n // Half-open end exactly at a page boundary: the last included\n // character is the previous page's last one. Its index settles via\n // clamping once that page's geometry loads.\n ei -= 1;\n if (ei < si) {\n clearSelection();\n return;\n }\n endIndex = Number.MAX_SAFE_INTEGER;\n }\n const focusPon = ponAtIndex(ei);\n if (focusPon == null) throw new Error(`select: unknown page at index ${ei}`);\n setSelecting(false); // programmatic selections are born settled\n recompute({\n anchor: { pon: range.start.pon, glyph: Math.max(0, range.start.index) },\n focus: { pon: focusPon, glyph: endIndex - 1 },\n });\n }\n\n function selectAll(): void {\n assertCanSelect('selection.selectAll');\n const pages = ctx.document()?.pages ?? [];\n if (pages.length === 0) return;\n setSelecting(false); // programmatic selections are born settled\n recompute({\n anchor: { pon: pages[0].pageObjectNumber, glyph: 0 },\n focus: {\n pon: pages[pages.length - 1].pageObjectNumber,\n glyph: Number.MAX_SAFE_INTEGER, // settles to the real last character on load\n },\n });\n }\n\n /** Per-page text snapshot, cached as a PROMISE so concurrent readers\n * share one fetch. Rejections are evicted (a denied or failed read must\n * not poison the cache for a later authorized call). */\n function pageTextSnapshot(pon: PageObjectNumber): Promise<PageTextSnapshot> {\n let p = textSnapshots.get(pon);\n if (!p) {\n const doc = ctx.doc;\n if (!doc) return Promise.reject(new Error('readText: document is not open'));\n p = Promise.resolve(doc.page(pon).text.read());\n p.catch(() => textSnapshots.delete(pon));\n textSnapshots.set(pon, p);\n }\n return p;\n }\n\n async function readText(): Promise<string> {\n const sel = ctx.getState().selection;\n if (!sel) return '';\n if (!canCopy()) throw new PermissionDenied('doc.text.copy', 'selection.readText');\n const { start, end } = orderedEnds(sel);\n const si = pageIndexOf(start.pon);\n const ei = pageIndexOf(end.pon);\n if (si < 0 || ei < 0) return '';\n // Per-page half-open character spans. Geometry is NOT needed here —\n // boundary offsets come from the range, interior pages span their whole\n // charCount (known from the text snapshot itself).\n const spans: Array<{ pon: PageObjectNumber; from: number; to: number }> = [];\n for (let i = si; i <= ei; i++) {\n const pon = ponAtIndex(i);\n if (pon == null) continue;\n spans.push({\n pon,\n from: i === si ? start.glyph : 0,\n to: i === ei ? end.glyph + 1 : Number.MAX_SAFE_INTEGER, // slice clamps to charCount\n });\n }\n const parts: string[] = new Array(spans.length);\n for (let base = 0; base < spans.length; base += TEXT_READ_CONCURRENCY) {\n const batch = spans.slice(base, base + TEXT_READ_CONCURRENCY);\n const snapshots = await Promise.all(batch.map((s) => pageTextSnapshot(s.pon)));\n snapshots.forEach((snap, j) => {\n parts[base + j] = sliceTextByChars(snap, batch[j].from, batch[j].to);\n });\n }\n return parts.join('\\n');\n }\n\n /** Structural registry change (rotate/move/delete/insert — `revision`\n * bumped): drop caches for pages that left, then recompute. Rotation\n * re-derives transforms via the layout key; a deleted endpoint page\n * clears via recompute's registry check. Raw snapshots are NEVER\n * refetched here — they are rotation-independent. */\n function onPagesUpdated(): void {\n const alive = new Set((ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber));\n for (const pon of [...rawGeometry.keys()]) {\n if (!alive.has(pon)) {\n rawGeometry.delete(pon);\n derived.delete(pon);\n textSnapshots.delete(pon);\n }\n }\n if (ctx.getState().selection) recompute();\n }\n\n /** Page CONTENT changed (redaction apply / flatten): every cached\n * snapshot — geometry AND text — is stale, and any live range points\n * into a character space that no longer exists. Drop everything, clear. */\n function invalidateContent(): void {\n epoch++;\n rawGeometry.clear();\n derived.clear();\n pending.clear();\n textSnapshots.clear();\n if (ctx.getState().selection) clearSelection();\n }\n\n // ── lifecycle wiring (registry + content invalidation) ──\n let lastRevision = ctx.document()?.revision ?? -1;\n const offStore = ctx.subscribe(() => {\n const revision = ctx.document()?.revision;\n if (revision === undefined || revision === lastRevision) return;\n lastRevision = revision;\n onPagesUpdated();\n });\n ctx.cleanup(offStore);\n const offEvents = ctx.doc?.events.subscribe((event) => {\n if (event.type === 'redaction.applied' || event.type === 'pages.flattened') {\n invalidateContent();\n }\n });\n if (offEvents) ctx.cleanup(offEvents);\n\n return {\n // ── public lens ──\n canSelect,\n canCopy,\n select,\n selectAll,\n clear: clearSelection,\n snapshot,\n menuAnchor,\n isSelecting: () => ctx.getState().selecting,\n hasSelection: () => ctx.getState().selection != null,\n selectedPages: () => {\n const { segments } = ctx.getState();\n return Object.keys(segments)\n .map(Number)\n .filter((pon) => (segments[pon]?.length ?? 0) > 0) as PageObjectNumber[];\n },\n segmentsForPage: (pon) => ctx.getState().segments[pon] ?? EMPTY_SEGMENTS,\n rectsForPage: (pon) =>\n (ctx.getState().segments[pon] ?? EMPTY_SEGMENTS).map((s) => s.rect),\n readText,\n onChange: (cb) => {\n changeCbs.add(cb);\n return () => changeCbs.delete(cb);\n },\n onCommit: (cb) => {\n commitCbs.add(cb);\n return () => commitCbs.delete(cb);\n },\n\n // ── host lens ──\n ensurePage,\n isLoaded: (pon) => !!ctx.getState().loaded[pon],\n isOverText: (pon, point: Point) => {\n const geom = geometryFor(pon);\n return geom ? glyphAt(geom, point) != null : false;\n },\n beginAt: (pon, point: Point) => {\n const geom = geometryFor(pon);\n if (!geom) return false;\n const i = glyphAt(geom, point);\n if (i == null) return false; // not near text — caller deselects, doesn't capture\n setSelecting(true); // the gesture opened\n recompute({ anchor: { pon, glyph: i }, focus: { pon, glyph: i } });\n return true;\n },\n selectWordAt: (pon, point: Point) => selectSpanAt(pon, point, 'word'),\n selectLineAt: (pon, point: Point) => selectSpanAt(pon, point, 'line'),\n extendTo: (pon, point: Point) => {\n const cur = ctx.getState().selection;\n if (!cur) return;\n const geom = geometryFor(pon);\n if (!geom) {\n ensurePage(pon); // dragged onto a not-yet-loaded page — warm it, recompute on load\n return;\n }\n const i = glyphAt(geom, point);\n if (i == null) return; // off-text — keep the last focus\n recompute({ anchor: cur.anchor, focus: { pon, glyph: i } });\n },\n end: () => {\n // The gesture ended (pointer-up): settle FIRST, so commit listeners\n // (menus, clipboard prefetch) observe isSelecting() === false.\n setSelecting(false);\n commitCbs.forEach((cb) => cb());\n },\n setHighlightVisible: (visible) =>\n ctx.dispatch({ type: 'SET_HIGHLIGHT_HIDDEN', hidden: !visible }),\n highlightVisible: () => !ctx.getState().highlightHidden,\n };\n}\n","import type {\n InteractionCapability,\n InteractionHandler,\n PlatformFeedback,\n} from '@embedpdf/plugin-interaction/contract';\nimport type { SelectionHostCapability } from './types';\n\nconst CURSOR_TOKEN = 'selection-text';\nconst DRAG_THRESHOLD_PX = 4; // viewport px the pointer must move before a drag-select begins\n\n/**\n * The text-selection pointer handler. It is live only under tools that enable the\n * `'text-select'` tag (the built-in `pointer` tool does; `pan` does not — so\n * switching to pan disables text selection with zero special-casing here).\n *\n * - single click → deselect; records an anchor but selects NOTHING until\n * the pointer moves past the drag threshold (Chrome/Acrobat feel)\n * - single-click + drag → caret selection from the anchor (extends across pages)\n * - double-click → select the word\n * - triple-click → select the visual line\n * - down off-text → deselect, and DON'T capture (so it can't block)\n * - hover → I-beam only when over text, else the pointer cursor\n */\nexport function createTextSelectHandler(\n selection: SelectionHostCapability,\n interaction: InteractionCapability,\n feedback?: PlatformFeedback,\n): InteractionHandler {\n // Per-gesture drag-threshold state (one active gesture at a time — the hub owner).\n let anchor: { pon: number; point: { x: number; y: number }; vx: number; vy: number } | null =\n null;\n let dragging = false;\n\n return {\n id: 'text-select',\n priority: 60,\n enabledFor: (tool) => tool.enables.has('text-select'),\n onDown: (s) => {\n anchor = null;\n dragging = false;\n if (!s.page) return false; // over a gap — let a lower handler (e.g. scroll) try\n const { pon, point } = s.page;\n const clicks = s.clickCount ?? 1;\n if (clicks >= 3) {\n selection.selectLineAt(pon, point);\n return true;\n }\n if (clicks === 2) {\n const selected = selection.selectWordAt(pon, point);\n // The platform's \"selection changed\" tick — ONLY when a touch\n // long-press actually engaged a word (never on blank space, never for\n // a mouse double-click). The gesture marker is the honest signal; a\n // raw double-click sample never carries it.\n if (selected && s.gesture === 'long-press') feedback?.selection();\n return true;\n }\n // Single click: clear immediately (clicking deselects), then record an anchor\n // ONLY if over text — but begin no selection until the drag threshold is met.\n selection.clear();\n if (!selection.isOverText(pon, point)) return false; // empty space → don't capture\n anchor = { pon, point, vx: s.viewport.x, vy: s.viewport.y };\n return true;\n },\n onMove: (s) => {\n if (!s.page || !anchor) return;\n if (!dragging) {\n if (Math.hypot(s.viewport.x - anchor.vx, s.viewport.y - anchor.vy) < DRAG_THRESHOLD_PX) {\n return; // still a click, not a drag — select nothing yet\n }\n dragging = true;\n selection.beginAt(anchor.pon, anchor.point); // open the selection at the anchor\n }\n selection.extendTo(s.page.pon, s.page.point);\n },\n onUp: () => {\n anchor = null;\n dragging = false;\n selection.end();\n },\n onCancel: () => {\n // Aborted (second finger → pinch, or a system cancel): drop the\n // in-flight selection instead of committing a sliver of it. end() after\n // clear() settles the `selecting` flag without anything to commit.\n anchor = null;\n dragging = false;\n selection.clear();\n selection.end();\n },\n onHover: (s) => {\n if (!s.page) {\n interaction.setCursor(CURSOR_TOKEN, null); // off the page → pointer\n return;\n }\n // Warm geometry on first hover; show the I-beam ONLY when actually over text.\n selection.ensurePage(s.page.pon);\n const overText = selection.isOverText(s.page.pon, s.page.point);\n interaction.setCursor(CURSOR_TOKEN, overText ? 'text' : null, 10);\n },\n };\n}\n","import type { SelectionAction, SelectionState } from './types';\n\nexport const initialSelectionState: SelectionState = {\n selection: null,\n segments: {},\n loaded: {},\n highlightHidden: false,\n selecting: false,\n};\n\nexport const selectionReducer = (\n state: SelectionState,\n action: SelectionAction,\n): SelectionState => {\n switch (action.type) {\n case 'PAGE_LOADED':\n return state.loaded[action.pon]\n ? state\n : { ...state, loaded: { ...state.loaded, [action.pon]: true } };\n case 'SET':\n return { ...state, selection: action.selection, segments: action.segments };\n case 'CLEAR':\n return state.selection === null && Object.keys(state.segments).length === 0\n ? state\n : { ...state, selection: null, segments: {} };\n case 'SET_HIGHLIGHT_HIDDEN':\n return state.highlightHidden === action.hidden\n ? state\n : { ...state, highlightHidden: action.hidden };\n case 'SET_SELECTING':\n return state.selecting === action.selecting\n ? state\n : { ...state, selecting: action.selecting };\n default:\n return state;\n }\n};\n"],"mappings":"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"}
|