@embedpdf/react 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/AnnotationList-CkijRHet-HEFNUIZe.d.cts +877 -0
- package/dist/AnnotationList-CkijRHet-HEFNUIZe.d.ts +877 -0
- package/dist/actions.cjs +25 -5
- package/dist/actions.cjs.map +1 -1
- package/dist/actions.d.cts +18 -5
- package/dist/actions.d.ts +18 -5
- package/dist/actions.js +22 -6
- package/dist/actions.js.map +1 -1
- package/dist/anchored-DeX95xSd.d.ts +85 -0
- package/dist/anchored-DzN3JywS.d.cts +85 -0
- package/dist/anchored.cjs +71 -28
- package/dist/anchored.cjs.map +1 -1
- package/dist/anchored.d.cts +2 -45
- package/dist/anchored.d.ts +2 -45
- package/dist/anchored.js +56 -19
- package/dist/anchored.js.map +1 -1
- package/dist/annotation-B48UT2ln.d.ts +302 -0
- package/dist/annotation-C1ttM8Wj.js +708 -0
- package/dist/annotation-C1ttM8Wj.js.map +1 -0
- package/dist/annotation-C9dVwo9b.d.cts +302 -0
- package/dist/annotation-Dex5EBda.cjs +830 -0
- package/dist/annotation-Dex5EBda.cjs.map +1 -0
- package/dist/annotation.cjs +20 -783
- package/dist/annotation.d.cts +2 -2
- package/dist/annotation.d.ts +2 -2
- package/dist/annotation.js +2 -768
- package/dist/commands.cjs +68 -28
- package/dist/commands.cjs.map +1 -1
- package/dist/commands.d.cts +37 -10
- package/dist/commands.d.ts +37 -10
- package/dist/commands.js +68 -31
- package/dist/commands.js.map +1 -1
- package/dist/form-55izw0jS.js +511 -0
- package/dist/form-55izw0jS.js.map +1 -0
- package/dist/form-BNqQfGGH.cjs +548 -0
- package/dist/form-BNqQfGGH.cjs.map +1 -0
- package/dist/form.cjs +5 -5
- package/dist/form.d.cts +32 -25
- package/dist/form.d.ts +32 -25
- package/dist/form.js +2 -3
- package/dist/history.cjs +38 -0
- package/dist/history.cjs.map +1 -0
- package/dist/history.d.cts +27 -0
- package/dist/history.d.ts +27 -0
- package/dist/history.js +27 -0
- package/dist/history.js.map +1 -0
- package/dist/i18n.cjs +26 -30
- package/dist/i18n.cjs.map +1 -1
- package/dist/i18n.d.cts +24 -21
- package/dist/i18n.d.ts +24 -21
- package/dist/i18n.js +24 -31
- package/dist/i18n.js.map +1 -1
- package/dist/index.cjs +213 -57
- package/dist/index.d.cts +32 -31
- package/dist/index.d.ts +32 -31
- package/dist/index.js +33 -29
- package/dist/inert-CmBEbKCn.cjs +19 -0
- package/dist/inert-CmBEbKCn.cjs.map +1 -0
- package/dist/inert-D8fkennb.js +14 -0
- package/dist/inert-D8fkennb.js.map +1 -0
- package/dist/interaction.cjs +48 -102
- package/dist/interaction.cjs.map +1 -1
- package/dist/interaction.d.cts +23 -32
- package/dist/interaction.d.ts +23 -32
- package/dist/interaction.js +33 -102
- package/dist/interaction.js.map +1 -1
- package/dist/link.cjs +65 -104
- package/dist/link.cjs.map +1 -1
- package/dist/link.d.cts +21 -16
- package/dist/link.d.ts +22 -17
- package/dist/link.js +67 -107
- package/dist/link.js.map +1 -1
- package/dist/measurement.cjs +56 -0
- package/dist/measurement.cjs.map +1 -0
- package/dist/measurement.d.cts +38 -0
- package/dist/measurement.d.ts +38 -0
- package/dist/measurement.js +42 -0
- package/dist/measurement.js.map +1 -0
- package/dist/metadata.cjs +20 -7
- package/dist/metadata.cjs.map +1 -1
- package/dist/metadata.d.cts +22 -7
- package/dist/metadata.d.ts +22 -7
- package/dist/metadata.js +20 -10
- package/dist/metadata.js.map +1 -1
- package/dist/page-edit.cjs +7 -3
- package/dist/page-edit.cjs.map +1 -1
- package/dist/page-edit.d.cts +6 -2
- package/dist/page-edit.d.ts +6 -2
- package/dist/page-edit.js +7 -4
- package/dist/page-edit.js.map +1 -1
- package/dist/page-layers-Bkaaz8Zf.js +26 -0
- package/dist/page-layers-Bkaaz8Zf.js.map +1 -0
- package/dist/page-layers-BloZDoOV.cjs +37 -0
- package/dist/page-layers-BloZDoOV.cjs.map +1 -0
- package/dist/page-view.cjs +89 -82
- package/dist/page-view.cjs.map +1 -1
- package/dist/page-view.d.cts +14 -7
- package/dist/page-view.d.ts +18 -11
- package/dist/page-view.js +86 -81
- package/dist/page-view.js.map +1 -1
- package/dist/redaction.cjs +30 -15
- package/dist/redaction.cjs.map +1 -1
- package/dist/redaction.d.cts +27 -9
- package/dist/redaction.d.ts +27 -9
- package/dist/redaction.js +29 -18
- package/dist/redaction.js.map +1 -1
- package/dist/render.cjs +71 -46
- package/dist/render.cjs.map +1 -1
- package/dist/render.d.cts +17 -5
- package/dist/render.d.ts +17 -5
- package/dist/render.js +70 -49
- package/dist/render.js.map +1 -1
- package/dist/runtime-B6xcPsEb.js +398 -0
- package/dist/runtime-B6xcPsEb.js.map +1 -0
- package/dist/runtime-DBEBlpQV.d.cts +237 -0
- package/dist/runtime-V3MVMb91.d.ts +237 -0
- package/dist/runtime-fzpGv78v.cjs +555 -0
- package/dist/runtime-fzpGv78v.cjs.map +1 -0
- package/dist/runtime.cjs +45 -324
- package/dist/runtime.d.cts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +2 -306
- package/dist/search.cjs +81 -50
- package/dist/search.cjs.map +1 -1
- package/dist/search.d.cts +36 -24
- package/dist/search.d.ts +36 -24
- package/dist/search.js +81 -53
- package/dist/search.js.map +1 -1
- package/dist/selection.cjs +105 -108
- package/dist/selection.cjs.map +1 -1
- package/dist/selection.d.cts +54 -26
- package/dist/selection.d.ts +56 -28
- package/dist/selection.js +103 -110
- package/dist/selection.js.map +1 -1
- package/dist/shell.cjs +36 -21
- package/dist/shell.cjs.map +1 -1
- package/dist/shell.d.cts +32 -17
- package/dist/shell.d.ts +32 -17
- package/dist/shell.js +36 -24
- package/dist/shell.js.map +1 -1
- package/dist/signature.cjs +29 -48
- package/dist/signature.cjs.map +1 -1
- package/dist/signature.d.cts +26 -26
- package/dist/signature.d.ts +26 -26
- package/dist/signature.js +30 -48
- package/dist/signature.js.map +1 -1
- package/dist/stage-BIG6aeVd.cjs +369 -0
- package/dist/stage-BIG6aeVd.cjs.map +1 -0
- package/dist/stage-ByFPD-Fv.d.cts +117 -0
- package/dist/stage-DaboaheR.d.ts +117 -0
- package/dist/stage-DoVekb83.js +302 -0
- package/dist/stage-DoVekb83.js.map +1 -0
- package/dist/stage-scope-CQgCuf1w.cjs +46 -0
- package/dist/stage-scope-CQgCuf1w.cjs.map +1 -0
- package/dist/stage-scope-D7ZeNduT.js +23 -0
- package/dist/stage-scope-D7ZeNduT.js.map +1 -0
- package/dist/stage.cjs +12 -235
- package/dist/stage.d.cts +2 -116
- package/dist/stage.d.ts +2 -116
- package/dist/stage.js +3 -228
- package/dist/stamp.cjs +41 -35
- package/dist/stamp.cjs.map +1 -1
- package/dist/stamp.d.cts +25 -18
- package/dist/stamp.d.ts +25 -18
- package/dist/stamp.js +40 -37
- package/dist/stamp.js.map +1 -1
- package/dist/state-0K1I5cM4.d.cts +29 -0
- package/dist/state-0K1I5cM4.d.ts +29 -0
- package/dist/state-CbgxhwLA.js +62 -0
- package/dist/state-CbgxhwLA.js.map +1 -0
- package/dist/state-CsfZy_Eq.cjs +73 -0
- package/dist/state-CsfZy_Eq.cjs.map +1 -0
- package/dist/svg-shapes-Dm1yTR1b.js +40 -0
- package/dist/svg-shapes-Dm1yTR1b.js.map +1 -0
- package/dist/svg-shapes-zo0GNkc9.cjs +53 -0
- package/dist/svg-shapes-zo0GNkc9.cjs.map +1 -0
- package/dist/toolbar.cjs +297 -295
- package/dist/toolbar.cjs.map +1 -1
- package/dist/toolbar.d.cts +58 -68
- package/dist/toolbar.d.ts +67 -77
- package/dist/toolbar.js +271 -293
- package/dist/toolbar.js.map +1 -1
- package/dist/view-manager.cjs +34 -0
- package/dist/view-manager.cjs.map +1 -0
- package/dist/view-manager.d.cts +21 -0
- package/dist/view-manager.d.ts +21 -0
- package/dist/view-manager.js +23 -0
- package/dist/view-manager.js.map +1 -0
- package/package.json +41 -38
- package/dist/AnnotationListSnapshot-D3mFut1e-C_GMpK25.d.cts +0 -546
- package/dist/AnnotationListSnapshot-D3mFut1e-C_GMpK25.d.ts +0 -546
- package/dist/annotation-BCED_p9H.d.cts +0 -160
- package/dist/annotation-anchors-CetwM1g7.js +0 -15
- package/dist/annotation-anchors-CetwM1g7.js.map +0 -1
- package/dist/annotation-anchors-DuYRBJLl.cjs +0 -26
- package/dist/annotation-anchors-DuYRBJLl.cjs.map +0 -1
- package/dist/annotation-hooks-BB5ZhPpf.cjs +0 -16
- package/dist/annotation-hooks-BB5ZhPpf.cjs.map +0 -1
- package/dist/annotation-hooks-Df8EmzDO.js +0 -11
- package/dist/annotation-hooks-Df8EmzDO.js.map +0 -1
- package/dist/annotation-k38KDlIZ.d.ts +0 -160
- package/dist/annotation-menu.cjs +0 -64
- package/dist/annotation-menu.cjs.map +0 -1
- package/dist/annotation-menu.d.cts +0 -33
- package/dist/annotation-menu.d.ts +0 -33
- package/dist/annotation-menu.js +0 -48
- package/dist/annotation-menu.js.map +0 -1
- package/dist/annotation.cjs.map +0 -1
- package/dist/annotation.js.map +0 -1
- package/dist/form-BVumS7up.cjs +0 -926
- package/dist/form-BVumS7up.cjs.map +0 -1
- package/dist/form-CK3mp99m.js +0 -895
- package/dist/form-CK3mp99m.js.map +0 -1
- package/dist/rolldown-runtime-BBjsoOtd.js +0 -27
- package/dist/runtime-DE76hlnl.d.ts +0 -216
- package/dist/runtime-umHA_xHt.d.cts +0 -216
- package/dist/runtime.cjs.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/scrollbar.cjs +0 -241
- package/dist/scrollbar.cjs.map +0 -1
- package/dist/scrollbar.d.cts +0 -42
- package/dist/scrollbar.d.ts +0 -42
- package/dist/scrollbar.js +0 -213
- package/dist/scrollbar.js.map +0 -1
- package/dist/stage.cjs.map +0 -1
- package/dist/stage.js.map +0 -1
- package/dist/views.cjs +0 -35
- package/dist/views.cjs.map +0 -1
- package/dist/views.d.cts +0 -21
- package/dist/views.d.ts +0 -21
- package/dist/views.js +0 -27
- package/dist/views.js.map +0 -1
package/dist/search.d.ts
CHANGED
|
@@ -1,35 +1,47 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import
|
|
1
|
+
import { n as StateHook, t as SettingsHook } from "./state-0K1I5cM4.js";
|
|
2
|
+
import { o as SearchQuery } from "./AnnotationList-CkijRHet-HEFNUIZe.js";
|
|
3
|
+
import { EventHook, PageRef } from "@embedpdf/core";
|
|
4
|
+
import { SearchCapability, SearchHit } from "@embedpdf/plugin-search";
|
|
3
5
|
export * from "@embedpdf/plugin-search";
|
|
4
6
|
//#region src/search.d.ts
|
|
5
7
|
interface SearchLayerProps {
|
|
6
|
-
/** Highlight colour for hits — SOLID (default: highlighter yellow). */
|
|
7
|
-
color?: string;
|
|
8
|
-
/** Highlight colour for the ACTIVE hit — SOLID (default: orange). */
|
|
9
|
-
activeColor?: string;
|
|
10
8
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
9
|
+
* Make matches clickable: called with the match someone clicks, for example
|
|
10
|
+
* to make it the active one with `search.goToHit(hit)`. The press still
|
|
11
|
+
* reaches the page, so a drag that starts on a match selects text, and only
|
|
12
|
+
* a click calls this. Without it, matches are only paint and the pointer
|
|
13
|
+
* goes straight through.
|
|
15
14
|
*/
|
|
16
|
-
|
|
15
|
+
onHitClick?: (hit: SearchHit) => void;
|
|
17
16
|
}
|
|
18
|
-
declare function SearchLayer({
|
|
19
|
-
/** The search capability (search/clear/
|
|
20
|
-
declare function useSearch():
|
|
21
|
-
/**
|
|
22
|
-
declare function
|
|
17
|
+
declare function SearchLayer({ onHitClick }: SearchLayerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
18
|
+
/** The search capability (search / clear / nextHit / previousHit / …) for app chrome. */
|
|
19
|
+
declare function useSearch(): SearchCapability;
|
|
20
|
+
/** Subscribe to one search event for the mounted lifetime: `useSearchEvent((search) => search.onCompleted, handler)`. */
|
|
21
|
+
declare function useSearchEvent<T>(select: (search: SearchCapability) => EventHook<T>, handler: (event: T) => void): void;
|
|
22
|
+
/**
|
|
23
|
+
* The search's state: the query, status, count, active match, progress and
|
|
24
|
+
* error (the page's State table, declared once in `searchState`). Takes a
|
|
25
|
+
* selector, and re-renders only when what it returns changes.
|
|
26
|
+
*/
|
|
27
|
+
declare const useSearchState: StateHook<{
|
|
23
28
|
query: SearchQuery | null;
|
|
24
29
|
status: import("@embedpdf/plugin-search").SearchStatus;
|
|
25
30
|
hitCount: number;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
activeHitIndex: number;
|
|
32
|
+
activeHit: SearchHit | null;
|
|
33
|
+
progress: import("@embedpdf/plugin-search").SearchProgress;
|
|
34
|
+
error: import("@embedpdf/core").PluginErrorInfo | null;
|
|
35
|
+
}>;
|
|
36
|
+
/** The search settings (`reveal`, `highlight`), with or without a document. Takes a selector. */
|
|
37
|
+
declare const useSearchSettings: SettingsHook<import("@embedpdf/plugin-search").SearchSettings>;
|
|
38
|
+
/**
|
|
39
|
+
* Every match found so far, or one page's (its ref or index), for a results
|
|
40
|
+
* list or a count per thumbnail. The arrays are reference-stable, so a
|
|
41
|
+
* component re-renders only when matches land on what it shows. Empty without
|
|
42
|
+
* a document, and for a page that has just left the document.
|
|
43
|
+
*/
|
|
44
|
+
declare function useSearchHits(page?: PageRef | number): readonly SearchHit[];
|
|
33
45
|
//#endregion
|
|
34
|
-
export { SearchLayer, SearchLayerProps, useSearch, useSearchState };
|
|
46
|
+
export { SearchLayer, SearchLayerProps, useSearch, useSearchEvent, useSearchHits, useSearchSettings, useSearchState };
|
|
35
47
|
//# sourceMappingURL=search.d.ts.map
|
package/dist/search.js
CHANGED
|
@@ -1,75 +1,103 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { f as useCapability, g as useDocumentScope, p as useCapabilityEvent, w as usePage, x as useKernelValue } from "./runtime-B6xcPsEb.js";
|
|
2
|
+
import { n as stateHook, t as settingsHook } from "./state-CbgxhwLA.js";
|
|
2
3
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import "
|
|
4
|
-
import {
|
|
4
|
+
import { createClickDetector, paint, searchHighlightsOf } from "@embedpdf/web";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { SearchToken, searchState } from "@embedpdf/plugin-search";
|
|
5
7
|
export * from "@embedpdf/plugin-search";
|
|
6
8
|
//#region src/search.tsx
|
|
7
|
-
function SearchLayer({
|
|
9
|
+
function SearchLayer({ onHitClick }) {
|
|
8
10
|
const page = usePage();
|
|
9
|
-
const hits =
|
|
10
|
-
const active =
|
|
11
|
+
const hits = useSearchHits(page.ref);
|
|
12
|
+
const active = useSearchState((state) => state.activeHit);
|
|
13
|
+
const highlight = useSearchSettings((settings) => settings.highlight);
|
|
14
|
+
const [clicks] = useState(createClickDetector);
|
|
11
15
|
if (hits.length === 0) return null;
|
|
16
|
+
const color = paint("search-highlight", highlight.color);
|
|
17
|
+
const activeColor = paint("search-highlight-active", highlight.activeColor);
|
|
18
|
+
const blendMode = paint("search-blend-mode", highlight.blendMode);
|
|
19
|
+
const clickable = onHitClick ? {
|
|
20
|
+
pointerEvents: "auto",
|
|
21
|
+
cursor: "pointer"
|
|
22
|
+
} : null;
|
|
23
|
+
const pointerHandlers = (hit) => onHitClick && {
|
|
24
|
+
onPointerDown: (event) => clicks.press(event),
|
|
25
|
+
onClick: (event) => {
|
|
26
|
+
if (clicks.isClick(event)) onHitClick(hit);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
12
29
|
return /* @__PURE__ */ jsx("div", {
|
|
13
30
|
style: {
|
|
14
31
|
position: "absolute",
|
|
15
32
|
inset: 0,
|
|
16
33
|
pointerEvents: "none"
|
|
17
34
|
},
|
|
18
|
-
children: hits
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
children: searchHighlightsOf(hits, {
|
|
36
|
+
active,
|
|
37
|
+
page: page.transform,
|
|
38
|
+
color,
|
|
39
|
+
activeColor
|
|
40
|
+
}).map((piece) => piece.box ? /* @__PURE__ */ jsx("div", {
|
|
41
|
+
...pointerHandlers(piece.hit),
|
|
42
|
+
style: {
|
|
43
|
+
position: "absolute",
|
|
44
|
+
left: piece.box.left,
|
|
45
|
+
top: piece.box.top,
|
|
46
|
+
width: piece.box.width,
|
|
47
|
+
height: piece.box.height,
|
|
48
|
+
backgroundColor: piece.fill,
|
|
49
|
+
mixBlendMode: blendMode,
|
|
50
|
+
borderRadius: 2,
|
|
51
|
+
...clickable
|
|
33
52
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
}, piece.key) : /* @__PURE__ */ jsx("svg", {
|
|
54
|
+
style: {
|
|
55
|
+
position: "absolute",
|
|
56
|
+
inset: 0,
|
|
57
|
+
width: "100%",
|
|
58
|
+
height: "100%",
|
|
59
|
+
overflow: "visible",
|
|
60
|
+
mixBlendMode: blendMode
|
|
61
|
+
},
|
|
62
|
+
children: /* @__PURE__ */ jsx("polygon", {
|
|
63
|
+
points: piece.points ?? void 0,
|
|
64
|
+
...pointerHandlers(piece.hit),
|
|
41
65
|
style: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
mixBlendMode: blendMode
|
|
48
|
-
},
|
|
49
|
-
children: /* @__PURE__ */ jsx("polygon", {
|
|
50
|
-
points: ring.map((p) => `${p.x},${p.y}`).join(" "),
|
|
51
|
-
fill
|
|
52
|
-
})
|
|
53
|
-
}, `${hit.charStart}:${i}`);
|
|
54
|
-
}))
|
|
66
|
+
fill: piece.fill,
|
|
67
|
+
...clickable
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}, piece.key))
|
|
55
71
|
});
|
|
56
72
|
}
|
|
57
|
-
/** The search capability (search/clear/
|
|
73
|
+
/** The search capability (search / clear / nextHit / previousHit / …) for app chrome. */
|
|
58
74
|
function useSearch() {
|
|
59
75
|
return useCapability(SearchToken);
|
|
60
76
|
}
|
|
61
|
-
/**
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
/** Subscribe to one search event for the mounted lifetime: `useSearchEvent((search) => search.onCompleted, handler)`. */
|
|
78
|
+
function useSearchEvent(select, handler) {
|
|
79
|
+
useCapabilityEvent(SearchToken, select, handler);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The search's state: the query, status, count, active match, progress and
|
|
83
|
+
* error (the page's State table, declared once in `searchState`). Takes a
|
|
84
|
+
* selector, and re-renders only when what it returns changes.
|
|
85
|
+
*/
|
|
86
|
+
const useSearchState = stateHook(searchState);
|
|
87
|
+
/** The search settings (`reveal`, `highlight`), with or without a document. Takes a selector. */
|
|
88
|
+
const useSearchSettings = settingsHook(SearchToken);
|
|
89
|
+
const NO_HITS = Object.freeze([]);
|
|
90
|
+
/**
|
|
91
|
+
* Every match found so far, or one page's (its ref or index), for a results
|
|
92
|
+
* list or a count per thumbnail. The arrays are reference-stable, so a
|
|
93
|
+
* component re-renders only when matches land on what it shows. Empty without
|
|
94
|
+
* a document, and for a page that has just left the document.
|
|
95
|
+
*/
|
|
96
|
+
function useSearchHits(page) {
|
|
97
|
+
const scoped = useDocumentScope();
|
|
98
|
+
return useKernelValue((kernel) => kernel.tryCapability(SearchToken, scoped ?? void 0)?.listHits(page === void 0 ? void 0 : { page }) ?? NO_HITS);
|
|
71
99
|
}
|
|
72
100
|
//#endregion
|
|
73
|
-
export { SearchLayer, useSearch, useSearchState };
|
|
101
|
+
export { SearchLayer, useSearch, useSearchEvent, useSearchHits, useSearchSettings, useSearchState };
|
|
74
102
|
|
|
75
103
|
//# sourceMappingURL=search.js.map
|
package/dist/search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","names":[],"sources":["../src/search.tsx"],"sourcesContent":["/**\n * The React surface for @embedpdf/plugin-search.\n *\n * <SearchLayer> is
|
|
1
|
+
{"version":3,"file":"search.js","names":[],"sources":["../src/search.tsx"],"sourcesContent":["/**\n * The React surface for @embedpdf/plugin-search.\n *\n * <SearchLayer> is the SelectionLayer's twin: it reads the page's page-space\n * hit rects from the capability and paints them through PageContext.toPixels,\n * in the colors of the plugin's `highlight` setting, which the `--epdf-search-*`\n * CSS variables override. No engine calls: search is driven from app chrome\n * via useSearch().\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-search';\nimport * as React from 'react';\nimport { useState } from 'react';\nimport { SearchToken, searchState } from '@embedpdf/plugin-search';\nimport type { SearchCapability, SearchHit } from '@embedpdf/plugin-search';\nimport type { EventHook, PageRef } from '@embedpdf/core';\nimport { createClickDetector, paint, searchHighlightsOf } from '@embedpdf/web';\nimport {\n useCapability,\n useCapabilityEvent,\n useDocumentScope,\n useKernelValue,\n usePage,\n} from './runtime';\nimport { settingsHook, stateHook } from './state';\n\nexport interface SearchLayerProps {\n /**\n * Make matches clickable: called with the match someone clicks, for example\n * to make it the active one with `search.goToHit(hit)`. The press still\n * reaches the page, so a drag that starts on a match selects text, and only\n * a click calls this. Without it, matches are only paint and the pointer\n * goes straight through.\n */\n onHitClick?: (hit: SearchHit) => void;\n}\n\nexport function SearchLayer({ onHitClick }: SearchLayerProps) {\n const page = usePage();\n // Per-page hit arrays are reference-stable in the plugin, so this re-renders\n // only when matches land on this page.\n const hits = useSearchHits(page.ref);\n const active = useSearchState((state) => state.activeHit);\n const highlight = useSearchSettings((settings) => settings.highlight);\n // Tells a click on a match from a drag that starts there (and selects text).\n const [clicks] = useState(createClickDetector);\n\n if (hits.length === 0) return null;\n\n // Each color is its CSS variable first, then the setting: CSS wins.\n const color = paint('search-highlight', highlight.color);\n const activeColor = paint('search-highlight-active', highlight.activeColor);\n const blendMode = paint(\n 'search-blend-mode',\n highlight.blendMode,\n ) as React.CSSProperties['mixBlendMode'];\n\n // Only a clickable match takes the pointer; a plain highlight stays inert.\n // Nothing here stops the press, so it reaches the page as well.\n const clickable = onHitClick ? { pointerEvents: 'auto' as const, cursor: 'pointer' } : null;\n const pointerHandlers = (hit: SearchHit) =>\n onHitClick && {\n onPointerDown: (event: React.PointerEvent) => clicks.press(event),\n onClick: (event: React.MouseEvent) => {\n if (clicks.isClick(event)) onHitClick(hit);\n },\n };\n\n // Upright lines are a rounded box; turned lines draw their true quad.\n const pieces = searchHighlightsOf(hits, {\n active,\n page: page.transform,\n color,\n activeColor,\n });\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {pieces.map((piece) =>\n piece.box ? (\n <div\n key={piece.key}\n {...pointerHandlers(piece.hit)}\n style={{\n position: 'absolute',\n left: piece.box.left,\n top: piece.box.top,\n width: piece.box.width,\n height: piece.box.height,\n backgroundColor: piece.fill,\n mixBlendMode: blendMode,\n borderRadius: 2,\n ...clickable,\n }}\n />\n ) : (\n <svg\n key={piece.key}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n overflow: 'visible',\n mixBlendMode: blendMode,\n }}\n >\n {/* The fill goes in `style`: an SVG attribute doesn't read var(). */}\n <polygon\n points={piece.points ?? undefined}\n {...pointerHandlers(piece.hit)}\n style={{ fill: piece.fill, ...clickable }}\n />\n </svg>\n ),\n )}\n </div>\n );\n}\n\n/** The search capability (search / clear / nextHit / previousHit / …) for app chrome. */\nexport function useSearch(): SearchCapability {\n return useCapability(SearchToken);\n}\n\n/** Subscribe to one search event for the mounted lifetime: `useSearchEvent((search) => search.onCompleted, handler)`. */\nexport function useSearchEvent<T>(\n select: (search: SearchCapability) => EventHook<T>,\n handler: (event: T) => void,\n): void {\n useCapabilityEvent(SearchToken, select, handler);\n}\n\n/**\n * The search's state: the query, status, count, active match, progress and\n * error (the page's State table, declared once in `searchState`). Takes a\n * selector, and re-renders only when what it returns changes.\n */\nexport const useSearchState = stateHook(searchState);\n\n/** The search settings (`reveal`, `highlight`), with or without a document. Takes a selector. */\nexport const useSearchSettings = settingsHook(SearchToken);\n\nconst NO_HITS: readonly SearchHit[] = Object.freeze([]);\n\n/**\n * Every match found so far, or one page's (its ref or index), for a results\n * list or a count per thumbnail. The arrays are reference-stable, so a\n * component re-renders only when matches land on what it shows. Empty without\n * a document, and for a page that has just left the document.\n */\nexport function useSearchHits(page?: PageRef | number): readonly SearchHit[] {\n const scoped = useDocumentScope();\n // Resolved on every read, like the state hook: a document that closes reads as no hits.\n return useKernelValue(\n (kernel) =>\n kernel\n .tryCapability(SearchToken, scoped ?? undefined)\n ?.listHits(page === undefined ? undefined : { page }) ?? NO_HITS,\n );\n}\n"],"mappings":";;;;;;;;AAsCA,SAAgB,YAAY,EAAE,cAAgC;CAC5D,MAAM,OAAO,QAAQ;CAGrB,MAAM,OAAO,cAAc,KAAK,GAAG;CACnC,MAAM,SAAS,gBAAgB,UAAU,MAAM,SAAS;CACxD,MAAM,YAAY,mBAAmB,aAAa,SAAS,SAAS;CAEpE,MAAM,CAAC,UAAU,SAAS,mBAAmB;CAE7C,IAAI,KAAK,WAAW,GAAG,OAAO;CAG9B,MAAM,QAAQ,MAAM,oBAAoB,UAAU,KAAK;CACvD,MAAM,cAAc,MAAM,2BAA2B,UAAU,WAAW;CAC1E,MAAM,YAAY,MAChB,qBACA,UAAU,SACZ;CAIA,MAAM,YAAY,aAAa;EAAE,eAAe;EAAiB,QAAQ;CAAU,IAAI;CACvF,MAAM,mBAAmB,QACvB,cAAc;EACZ,gBAAgB,UAA8B,OAAO,MAAM,KAAK;EAChE,UAAU,UAA4B;GACpC,IAAI,OAAO,QAAQ,KAAK,GAAG,WAAW,GAAG;EAC3C;CACF;CAUF,OACE,oBAAC,OAAD;EAAK,OAAO;GAAE,UAAU;GAAY,OAAO;GAAG,eAAe;EAAO;EARvD,UAAA,mBAAmB,MAAM;GACtC;GACA,MAAM,KAAK;GACX;GACA;EACF,CAIU,CAAC,CAAC,KAAK,UACX,MAAM,MACJ,oBAAC,OAAD;GAEE,GAAI,gBAAgB,MAAM,GAAG;GAC7B,OAAO;IACL,UAAU;IACV,MAAM,MAAM,IAAI;IAChB,KAAK,MAAM,IAAI;IACf,OAAO,MAAM,IAAI;IACjB,QAAQ,MAAM,IAAI;IAClB,iBAAiB,MAAM;IACvB,cAAc;IACd,cAAc;IACd,GAAG;GACL;EACD,GAbM,MAAM,GAaZ,IAED,oBAAC,OAAD;GAEE,OAAO;IACL,UAAU;IACV,OAAO;IACP,OAAO;IACP,QAAQ;IACR,UAAU;IACV,cAAc;GAChB;GAGA,UAAA,oBAAC,WAAD;IACE,QAAQ,MAAM,UAAU,KAAA;IACxB,GAAI,gBAAgB,MAAM,GAAG;IAC7B,OAAO;KAAE,MAAM,MAAM;KAAM,GAAG;IAAU;GACzC,CAAA;EACE,GAhBE,MAAM,GAgBR,CAET;CACG,CAAA;AAET;;AAGA,SAAgB,YAA8B;CAC5C,OAAO,cAAc,WAAW;AAClC;;AAGA,SAAgB,eACd,QACA,SACM;CACN,mBAAmB,aAAa,QAAQ,OAAO;AACjD;;;;;;AAOA,MAAa,iBAAiB,UAAU,WAAW;;AAGnD,MAAa,oBAAoB,aAAa,WAAW;AAEzD,MAAM,UAAgC,OAAO,OAAO,CAAC,CAAC;;;;;;;AAQtD,SAAgB,cAAc,MAA+C;CAC3E,MAAM,SAAS,iBAAiB;CAEhC,OAAO,gBACJ,WACC,OACG,cAAc,aAAa,UAAU,KAAA,CAAS,CAAC,EAC9C,SAAS,SAAS,KAAA,IAAY,KAAA,IAAY,EAAE,KAAK,CAAC,KAAK,OAC/D;AACF"}
|
package/dist/selection.cjs
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-DDXJien1.cjs");
|
|
3
|
-
const require_runtime = require("./runtime.cjs");
|
|
3
|
+
const require_runtime = require("./runtime-fzpGv78v.cjs");
|
|
4
|
+
const require_state = require("./state-CsfZy_Eq.cjs");
|
|
4
5
|
const require_anchored = require("./anchored.cjs");
|
|
6
|
+
const require_stage_scope = require("./stage-scope-CQgCuf1w.cjs");
|
|
5
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let _embedpdf_web = require("@embedpdf/web");
|
|
6
9
|
let react = require("react");
|
|
7
10
|
react = require_rolldown_runtime.__toESM(react, 1);
|
|
8
|
-
let _embedpdf_web = require("@embedpdf/web");
|
|
9
|
-
let _embedpdf_plugin_stage_contract = require("@embedpdf/plugin-stage/contract");
|
|
10
|
-
let _embedpdf_core_geometry = require("@embedpdf/core-geometry");
|
|
11
11
|
let _embedpdf_plugin_selection = require("@embedpdf/plugin-selection");
|
|
12
|
-
let
|
|
12
|
+
let _embedpdf_plugin_selection_contract_host = require("@embedpdf/plugin-selection/contract/host");
|
|
13
13
|
//#region src/selection.tsx
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The highlight of the selected text on one page, in the selection plugin's
|
|
16
|
+
* `color` setting; the `--epdf-text-selection` CSS variable wins over it.
|
|
17
|
+
*/
|
|
18
|
+
function SelectionLayer() {
|
|
15
19
|
const page = require_runtime.usePage();
|
|
16
|
-
const selection = require_runtime.useCapability(
|
|
17
|
-
const segments = require_runtime.useSelector(
|
|
18
|
-
const visible = require_runtime.useSelector(
|
|
20
|
+
const selection = require_runtime.useCapability(_embedpdf_plugin_selection_contract_host.SelectionToken);
|
|
21
|
+
const segments = require_runtime.useSelector(_embedpdf_plugin_selection_contract_host.SelectionToken, (selection) => selection.listSegments(page.ref), require_runtime.shallowArray);
|
|
22
|
+
const visible = require_runtime.useSelector(_embedpdf_plugin_selection_contract_host.SelectionToken, (selection) => selection.isHighlightVisible());
|
|
23
|
+
const color = useSelectionSettings((settings) => settings.color);
|
|
24
|
+
const accent = require_runtime.useViewerSettings((settings) => settings.accent);
|
|
19
25
|
(0, react.useEffect)(() => {
|
|
20
|
-
selection.
|
|
21
|
-
}, [selection, page.
|
|
26
|
+
selection.ensureLoaded(page.ref);
|
|
27
|
+
}, [selection, page.ref]);
|
|
22
28
|
if (!visible) return null;
|
|
29
|
+
const fill = (0, _embedpdf_web.paint)("text-selection", color ?? (0, _embedpdf_web.mixAccent)("text-selection", accent));
|
|
23
30
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
24
31
|
style: {
|
|
25
32
|
position: "absolute",
|
|
@@ -29,47 +36,45 @@ function SelectionLayer({ color = "rgba(33, 150, 243, 0.35)" }) {
|
|
|
29
36
|
overflow: "visible",
|
|
30
37
|
pointerEvents: "none"
|
|
31
38
|
},
|
|
32
|
-
children: segments.map((
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
s.quad.upperEnd,
|
|
37
|
-
s.quad.lowerEnd,
|
|
38
|
-
s.quad.lowerStart
|
|
39
|
-
].map((p) => page.transform.toPixels(p)).map((p) => `${p.x},${p.y}`).join(" "),
|
|
40
|
-
fill: color
|
|
41
|
-
}, i);
|
|
42
|
-
})
|
|
39
|
+
children: segments.map((segment, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
|
|
40
|
+
points: (0, _embedpdf_web.svgPoints)((0, _embedpdf_web.quadInPixels)(segment.quad, page.transform)),
|
|
41
|
+
style: { fill }
|
|
42
|
+
}, i))
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
/** The
|
|
45
|
+
/** The public selection capability (select(), readText(), canCopy(), …) for
|
|
46
46
|
* app chrome — toolbars, context menus, automation. */
|
|
47
47
|
function useSelection() {
|
|
48
48
|
return require_runtime.useCapability(_embedpdf_plugin_selection.SelectionToken);
|
|
49
49
|
}
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
/** Subscribe to one selection event for the mounted lifetime: `useSelectionEvent((selection) => selection.onCommitted, handler)`. */
|
|
51
|
+
function useSelectionEvent(select, handler) {
|
|
52
|
+
require_runtime.useCapabilityEvent(_embedpdf_plugin_selection.SelectionToken, select, handler);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The selection's state: whether anything is selected, whether the user is
|
|
56
|
+
* still selecting, the character range and the pages it's on (the page's State
|
|
57
|
+
* table, declared once in `selectionState`). Takes a selector, re-renders only
|
|
58
|
+
* when what it returns changes, and returns the empty state without a document.
|
|
59
|
+
*/
|
|
60
|
+
const useSelectionState = require_state.stateHook(_embedpdf_plugin_selection.selectionState);
|
|
61
|
+
/** The selection settings (`dragThreshold`, `color`, `handles`), with or without a document. Takes a selector. */
|
|
62
|
+
const useSelectionSettings = require_state.settingsHook(_embedpdf_plugin_selection.SelectionToken);
|
|
58
63
|
/**
|
|
59
|
-
* Floats over the current
|
|
64
|
+
* Floats over the current text selection (one anchor regardless of
|
|
60
65
|
* cross-page selection; it rides the gesture's end page) — and only once the
|
|
61
|
-
* selection
|
|
66
|
+
* selection settles: hidden while a gesture is active (mid-drag), it appears at
|
|
62
67
|
* pointer-up; programmatic selections show immediately (born settled). Works
|
|
63
68
|
* under `<Stage>` (mount in the overlay slot) and `<PageView>` alike — the
|
|
64
69
|
* surface provides the projection. Compose the contents from hooks:
|
|
65
70
|
* `useSelection()` for copy/clear, `useAnnotation()` for
|
|
66
71
|
* `markupFromSelection('highlight')`, `copySelection` for the clipboard.
|
|
67
72
|
* For live-follow UI during the drag, compose `<Anchored>` with
|
|
68
|
-
* `
|
|
73
|
+
* `getAnchor()` yourself — the primitive carries no policy.
|
|
69
74
|
*/
|
|
70
75
|
function SelectionMenu({ children, gap = 8, placement = "top" }) {
|
|
71
|
-
const selecting =
|
|
72
|
-
const anchor = require_runtime.useSelector(_embedpdf_plugin_selection.SelectionToken, (
|
|
76
|
+
const selecting = useSelectionState((state) => state.isSelecting);
|
|
77
|
+
const anchor = require_runtime.useSelector(_embedpdf_plugin_selection.SelectionToken, (selection) => selection.getAnchor(), _embedpdf_web.samePageBounds);
|
|
73
78
|
if (selecting || !anchor) return null;
|
|
74
79
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_anchored.Anchored, {
|
|
75
80
|
anchor,
|
|
@@ -78,60 +83,37 @@ function SelectionMenu({ children, gap = 8, placement = "top" }) {
|
|
|
78
83
|
children
|
|
79
84
|
});
|
|
80
85
|
}
|
|
81
|
-
const sameEndpoints = (a, b) => {
|
|
82
|
-
if (a === b) return true;
|
|
83
|
-
if (!a || !b) return false;
|
|
84
|
-
return a.start.pon === b.start.pon && a.end.pon === b.end.pon && a.start.advance === b.start.advance && a.end.advance === b.end.advance && (0, _embedpdf_core_geometry.textQuadEquals)(a.start.glyphQuad, b.start.glyphQuad) && (0, _embedpdf_core_geometry.textQuadEquals)(a.end.glyphQuad, b.end.glyphQuad);
|
|
85
|
-
};
|
|
86
|
-
/** The plugin's structural view over this Stage: point-exact projection in,
|
|
87
|
-
* page resolution out. (`pageRectToScreen` is the AABB projector — upright
|
|
88
|
-
* overlays only — and would collapse exactly the orientation handles need.) */
|
|
89
|
-
const handleView = (stage) => ({
|
|
90
|
-
toOverlay: (pon, pt) => {
|
|
91
|
-
const world = stage.pageToWorld(pon, pt);
|
|
92
|
-
return world ? stage.toScreen(world) : null;
|
|
93
|
-
},
|
|
94
|
-
pageAt: (overlay) => stage.pageAt(overlay),
|
|
95
|
-
pointOnPage: (pon, overlay) => stage.pointOnPage(pon, overlay)
|
|
96
|
-
});
|
|
97
86
|
/**
|
|
98
87
|
* iOS-style draggable selection handles. Each is drawn the way the platform
|
|
99
|
-
* draws them: a thin caret
|
|
88
|
+
* draws them: a thin caret bar that forms the selection's own start/end edge
|
|
100
89
|
* — the boundary glyph's oriented edge, so rotated text and rotated pages
|
|
101
90
|
* carry the handle with them — capped by a screen-constant circle, above the
|
|
102
91
|
* first line at the start, below the last line at the end.
|
|
103
92
|
*
|
|
104
|
-
* On touch, where a caret drag isn't available, the handles
|
|
93
|
+
* On touch, where a caret drag isn't available, the handles are the way to
|
|
105
94
|
* grow or shrink a selection: a long-press selects a word, then each handle
|
|
106
|
-
* extends from the
|
|
107
|
-
* exactly like a pointer drag — it rides the same `
|
|
95
|
+
* extends from the opposite endpoint, snapping to glyphs and crossing pages
|
|
96
|
+
* exactly like a pointer drag — it rides the same `beginGestureAt`/`extendTo`
|
|
108
97
|
* gesture path, so highlights, menus, and commit signals all behave
|
|
109
98
|
* identically. Mount in the `<Stage>` overlay slot next to `<SelectionMenu>`;
|
|
110
99
|
* outside a Stage it renders nothing (a `PageView` has no camera to project
|
|
111
100
|
* through). Pointer-isolated, so grabbing a handle never pans the stage.
|
|
101
|
+
* Painted in the plugin's `handles` setting, which the
|
|
102
|
+
* `--epdf-text-selection-handle` and `--epdf-text-selection-handle-shadow` CSS
|
|
103
|
+
* variables override.
|
|
112
104
|
*/
|
|
113
|
-
function SelectionHandles({
|
|
114
|
-
const
|
|
105
|
+
function SelectionHandles({ token: explicitToken } = {}) {
|
|
106
|
+
const token = require_stage_scope.useStageToken(explicitToken);
|
|
107
|
+
const host = require_runtime.useCapability(_embedpdf_plugin_selection_contract_host.SelectionToken);
|
|
115
108
|
const stage = require_runtime.useOptionalCapability(token);
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
glyphQuad: s.start.glyphQuad,
|
|
125
|
-
advance: s.start.advance
|
|
126
|
-
},
|
|
127
|
-
end: {
|
|
128
|
-
pon: s.end.pon,
|
|
129
|
-
glyphQuad: s.end.glyphQuad,
|
|
130
|
-
advance: s.end.advance
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
}, sameEndpoints);
|
|
134
|
-
require_runtime.useKernelValue(() => stage?.visiblePages() ?? null);
|
|
109
|
+
const surface = require_anchored.useOptionalProjectorBinding();
|
|
110
|
+
if (!surface || surface.projector.space !== "overlay") require_runtime.devWarn("selection-handles-outside-stage", "<SelectionHandles> renders nothing here: mount it in the <Stage> overlay slot (a <PageView> has no camera to project the handles through).");
|
|
111
|
+
const selecting = useSelectionState((state) => state.isSelecting);
|
|
112
|
+
const visible = require_runtime.useSelector(_embedpdf_plugin_selection_contract_host.SelectionToken, (selection) => selection.isHighlightVisible());
|
|
113
|
+
const handles = useSelectionSettings((settings) => settings.handles);
|
|
114
|
+
const accent = require_runtime.useViewerSettings((settings) => settings.accent);
|
|
115
|
+
const endpoints = require_runtime.useSelector(_embedpdf_plugin_selection_contract_host.SelectionToken, (selection) => (0, _embedpdf_plugin_selection.selectionHandleEndpointsOf)(selection.getSnapshot()), _embedpdf_web.sameSelectionEndpoints);
|
|
116
|
+
require_runtime.useKernelValue(() => stage?.listVisiblePages() ?? null);
|
|
135
117
|
const [dragging, setDragging] = (0, react.useState)(null);
|
|
136
118
|
const armSource = (0, react.useRef)(null);
|
|
137
119
|
armSource.current = stage && endpoints ? {
|
|
@@ -140,28 +122,22 @@ function SelectionHandles({ color = "#2196f3", token = _embedpdf_plugin_stage_co
|
|
|
140
122
|
} : null;
|
|
141
123
|
const bindHandle = (0, react.useMemo)(() => {
|
|
142
124
|
const detach = {};
|
|
143
|
-
const make = (role) => (
|
|
125
|
+
const make = (role) => (element) => {
|
|
144
126
|
detach[role]?.();
|
|
145
127
|
delete detach[role];
|
|
146
|
-
if (!
|
|
147
|
-
detach[role] = (0, _embedpdf_web.attachSelectionHandle)(
|
|
128
|
+
if (!element) return;
|
|
129
|
+
detach[role] = (0, _embedpdf_web.attachSelectionHandle)(element, { arm: () => {
|
|
148
130
|
const src = armSource.current;
|
|
149
131
|
if (!src) return null;
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
if (!geom) return null;
|
|
153
|
-
const opposite = src.endpoints[role === "start" ? "end" : "start"];
|
|
154
|
-
const drag = (0, _embedpdf_plugin_selection.createSelectionHandleDrag)(host, view, opposite, src.endpoints[role].pon);
|
|
132
|
+
const armed = (0, _embedpdf_plugin_selection.armSelectionHandle)(host, (0, _embedpdf_plugin_selection.selectionHandleViewOf)(src.stage), src.endpoints, role);
|
|
133
|
+
if (!armed) return null;
|
|
155
134
|
setDragging(role);
|
|
156
135
|
return {
|
|
157
|
-
base:
|
|
158
|
-
x: (geom.bar.from.x + geom.bar.to.x) / 2,
|
|
159
|
-
y: (geom.bar.from.y + geom.bar.to.y) / 2
|
|
160
|
-
},
|
|
136
|
+
base: armed.base,
|
|
161
137
|
session: {
|
|
162
|
-
move: drag.move,
|
|
138
|
+
move: armed.drag.move,
|
|
163
139
|
end: () => {
|
|
164
|
-
drag.end();
|
|
140
|
+
armed.drag.end();
|
|
165
141
|
setDragging(null);
|
|
166
142
|
}
|
|
167
143
|
}
|
|
@@ -175,22 +151,24 @@ function SelectionHandles({ color = "#2196f3", token = _embedpdf_plugin_stage_co
|
|
|
175
151
|
}, [host]);
|
|
176
152
|
if (!stage || !endpoints || !visible) return null;
|
|
177
153
|
if (selecting && !dragging) return null;
|
|
178
|
-
const view =
|
|
154
|
+
const view = (0, _embedpdf_plugin_selection.selectionHandleViewOf)(stage);
|
|
155
|
+
const color = (0, _embedpdf_web.paint)("text-selection-handle", handles.color ?? accent);
|
|
156
|
+
const shadow = (0, _embedpdf_web.paint)("text-selection-handle-shadow", handles.shadow);
|
|
179
157
|
const renderHandle = (role) => {
|
|
180
|
-
const
|
|
181
|
-
if (!
|
|
158
|
+
const geometry = (0, _embedpdf_plugin_selection.selectionHandleGeom)(view, endpoints[role], role);
|
|
159
|
+
if (!geometry) return null;
|
|
182
160
|
const barTop = _embedpdf_plugin_selection.HANDLE_PAD + (role === "start" ? _embedpdf_plugin_selection.HANDLE_HEAD : 0);
|
|
183
161
|
const pivotX = _embedpdf_plugin_selection.HANDLE_PAD + _embedpdf_plugin_selection.HANDLE_BAR / 2;
|
|
184
162
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
185
163
|
ref: bindHandle[role],
|
|
186
164
|
style: {
|
|
187
165
|
position: "absolute",
|
|
188
|
-
left:
|
|
189
|
-
top:
|
|
166
|
+
left: geometry.bar.from.x - pivotX,
|
|
167
|
+
top: geometry.bar.from.y - barTop,
|
|
190
168
|
width: _embedpdf_plugin_selection.HANDLE_BAR + 2 * _embedpdf_plugin_selection.HANDLE_PAD,
|
|
191
|
-
height:
|
|
192
|
-
...
|
|
193
|
-
transform: `rotate(${
|
|
169
|
+
height: geometry.length + _embedpdf_plugin_selection.HANDLE_HEAD + 2 * _embedpdf_plugin_selection.HANDLE_PAD,
|
|
170
|
+
...geometry.upright ? null : {
|
|
171
|
+
transform: `rotate(${geometry.rotation}deg)`,
|
|
194
172
|
transformOrigin: `${pivotX}px ${barTop}px`
|
|
195
173
|
},
|
|
196
174
|
touchAction: "none",
|
|
@@ -202,33 +180,49 @@ function SelectionHandles({ color = "#2196f3", token = _embedpdf_plugin_stage_co
|
|
|
202
180
|
left: _embedpdf_plugin_selection.HANDLE_PAD,
|
|
203
181
|
top: barTop,
|
|
204
182
|
width: _embedpdf_plugin_selection.HANDLE_BAR,
|
|
205
|
-
height:
|
|
183
|
+
height: geometry.length,
|
|
206
184
|
background: color,
|
|
207
185
|
borderRadius: _embedpdf_plugin_selection.HANDLE_BAR / 2
|
|
208
186
|
} }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
209
187
|
position: "absolute",
|
|
210
188
|
left: pivotX - _embedpdf_plugin_selection.HANDLE_HEAD / 2,
|
|
211
|
-
top: role === "start" ? _embedpdf_plugin_selection.HANDLE_PAD : _embedpdf_plugin_selection.HANDLE_PAD +
|
|
189
|
+
top: role === "start" ? _embedpdf_plugin_selection.HANDLE_PAD : _embedpdf_plugin_selection.HANDLE_PAD + geometry.length,
|
|
212
190
|
width: _embedpdf_plugin_selection.HANDLE_HEAD,
|
|
213
191
|
height: _embedpdf_plugin_selection.HANDLE_HEAD,
|
|
214
192
|
borderRadius: "50%",
|
|
215
193
|
background: color,
|
|
216
|
-
boxShadow:
|
|
194
|
+
boxShadow: shadow
|
|
217
195
|
} })]
|
|
218
196
|
}, role);
|
|
219
197
|
};
|
|
220
198
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [renderHandle("start"), renderHandle("end")] });
|
|
221
199
|
}
|
|
222
200
|
/**
|
|
223
|
-
* Mount
|
|
201
|
+
* Mount once per viewer to wire clipboard copy: prefetches the selected text
|
|
224
202
|
* when the selection settles, answers the native `copy` event synchronously,
|
|
225
203
|
* and falls back to the async Clipboard API for ctrl/cmd+C when the page has
|
|
226
|
-
* no DOM selection.
|
|
227
|
-
* `
|
|
204
|
+
* no DOM selection. A selection the user may not copy isn't copied, and
|
|
205
|
+
* `onRefused` is called. Renders nothing, and wires nothing until a document
|
|
206
|
+
* is ready. For a toolbar Copy button, call `copySelection(useSelection())`
|
|
207
|
+
* from its click handler instead.
|
|
228
208
|
*/
|
|
229
|
-
function SelectionClipboard({ prefetch } = {}) {
|
|
230
|
-
const selection = require_runtime.
|
|
231
|
-
|
|
209
|
+
function SelectionClipboard({ prefetch, onRefused, target } = {}) {
|
|
210
|
+
const selection = require_runtime.useOptionalCapability(_embedpdf_plugin_selection.SelectionToken);
|
|
211
|
+
const refused = (0, react.useRef)(onRefused);
|
|
212
|
+
refused.current = onRefused;
|
|
213
|
+
(0, react.useEffect)(() => {
|
|
214
|
+
const element = target ? target.current : void 0;
|
|
215
|
+
if (!selection || element === null) return;
|
|
216
|
+
return (0, _embedpdf_web.wireSelectionClipboard)(selection, {
|
|
217
|
+
...prefetch === void 0 ? {} : { prefetch },
|
|
218
|
+
...element ? { target: element } : {},
|
|
219
|
+
onRefused: () => refused.current?.()
|
|
220
|
+
});
|
|
221
|
+
}, [
|
|
222
|
+
selection,
|
|
223
|
+
prefetch,
|
|
224
|
+
target
|
|
225
|
+
]);
|
|
232
226
|
return null;
|
|
233
227
|
}
|
|
234
228
|
//#endregion
|
|
@@ -243,6 +237,9 @@ Object.defineProperty(exports, "copySelection", {
|
|
|
243
237
|
}
|
|
244
238
|
});
|
|
245
239
|
exports.useSelection = useSelection;
|
|
240
|
+
exports.useSelectionEvent = useSelectionEvent;
|
|
241
|
+
exports.useSelectionSettings = useSelectionSettings;
|
|
242
|
+
exports.useSelectionState = useSelectionState;
|
|
246
243
|
Object.keys(_embedpdf_plugin_selection).forEach(function(k) {
|
|
247
244
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
248
245
|
enumerable: true,
|