@embedpdf/plugin-selection 2.4.1 → 2.6.0

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.
Files changed (45) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +159 -81
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/handlers/marquee-selection.handler.d.ts +9 -7
  6. package/dist/lib/handlers/text-selection.handler.d.ts +8 -6
  7. package/dist/lib/selection-plugin.d.ts +7 -4
  8. package/dist/lib/types.d.ts +71 -2
  9. package/dist/preact/index.cjs +1 -1
  10. package/dist/preact/index.cjs.map +1 -1
  11. package/dist/preact/index.js +65 -19
  12. package/dist/preact/index.js.map +1 -1
  13. package/dist/react/index.cjs +1 -1
  14. package/dist/react/index.cjs.map +1 -1
  15. package/dist/react/index.js +65 -19
  16. package/dist/react/index.js.map +1 -1
  17. package/dist/shared/components/index.d.ts +1 -0
  18. package/dist/shared/components/marquee-selection.d.ts +18 -5
  19. package/dist/shared/components/selection-layer.d.ts +18 -1
  20. package/dist/shared/components/text-selection.d.ts +21 -0
  21. package/dist/shared-preact/components/index.d.ts +1 -0
  22. package/dist/shared-preact/components/marquee-selection.d.ts +18 -5
  23. package/dist/shared-preact/components/selection-layer.d.ts +18 -1
  24. package/dist/shared-preact/components/text-selection.d.ts +21 -0
  25. package/dist/shared-react/components/index.d.ts +1 -0
  26. package/dist/shared-react/components/marquee-selection.d.ts +18 -5
  27. package/dist/shared-react/components/selection-layer.d.ts +18 -1
  28. package/dist/shared-react/components/text-selection.d.ts +21 -0
  29. package/dist/svelte/components/MarqueeSelection.svelte.d.ts +12 -2
  30. package/dist/svelte/components/SelectionLayer.svelte.d.ts +11 -1
  31. package/dist/svelte/components/TextSelection.svelte.d.ts +22 -0
  32. package/dist/svelte/components/index.d.ts +1 -0
  33. package/dist/svelte/index.cjs +1 -1
  34. package/dist/svelte/index.cjs.map +1 -1
  35. package/dist/svelte/index.js +103 -20
  36. package/dist/svelte/index.js.map +1 -1
  37. package/dist/vue/components/index.d.ts +1 -0
  38. package/dist/vue/components/marquee-selection.vue.d.ts +13 -4
  39. package/dist/vue/components/selection-layer.vue.d.ts +15 -5
  40. package/dist/vue/components/text-selection.vue.d.ts +51 -0
  41. package/dist/vue/index.cjs +1 -1
  42. package/dist/vue/index.cjs.map +1 -1
  43. package/dist/vue/index.js +97 -34
  44. package/dist/vue/index.js.map +1 -1
  45. package/package.json +9 -9
@@ -2,13 +2,12 @@ import { createPluginPackage } from "@embedpdf/core";
2
2
  import { SelectionPlugin, SelectionPluginPackage as SelectionPluginPackage$1 } from "@embedpdf/plugin-selection";
3
3
  export * from "@embedpdf/plugin-selection";
4
4
  import { jsxs, Fragment, jsx } from "react/jsx-runtime";
5
- import { useState, useEffect, useMemo } from "react";
6
- import { Rotation } from "@embedpdf/models";
5
+ import { useState, useEffect, useMemo, Fragment as Fragment$1 } from "react";
7
6
  import { useCapability, usePlugin, useDocumentState } from "@embedpdf/core/react";
8
7
  import { CounterRotate } from "@embedpdf/utils/react";
9
8
  const useSelectionCapability = () => useCapability(SelectionPlugin.id);
10
9
  const useSelectionPlugin = () => usePlugin(SelectionPlugin.id);
11
- function SelectionLayer({
10
+ function TextSelection({
12
11
  documentId,
13
12
  pageIndex,
14
13
  scale: scaleOverride,
@@ -16,8 +15,10 @@ function SelectionLayer({
16
15
  background = "rgba(33,150,243)",
17
16
  selectionMenu
18
17
  }) {
18
+ var _a, _b;
19
19
  const { plugin: selPlugin } = useSelectionPlugin();
20
20
  const documentState = useDocumentState(documentId);
21
+ const page = (_b = (_a = documentState == null ? void 0 : documentState.document) == null ? void 0 : _a.pages) == null ? void 0 : _b[pageIndex];
21
22
  const [rects, setRects] = useState([]);
22
23
  const [boundingRect, setBoundingRect] = useState(null);
23
24
  const [placement, setPlacement] = useState(null);
@@ -44,8 +45,10 @@ function SelectionLayer({
44
45
  }, [scaleOverride, documentState == null ? void 0 : documentState.scale]);
45
46
  const actualRotation = useMemo(() => {
46
47
  if (rotationOverride !== void 0) return rotationOverride;
47
- return (documentState == null ? void 0 : documentState.rotation) ?? Rotation.Degree0;
48
- }, [rotationOverride, documentState == null ? void 0 : documentState.rotation]);
48
+ const pageRotation = (page == null ? void 0 : page.rotation) ?? 0;
49
+ const docRotation = (documentState == null ? void 0 : documentState.rotation) ?? 0;
50
+ return (pageRotation + docRotation) % 4;
51
+ }, [rotationOverride, page == null ? void 0 : page.rotation, documentState == null ? void 0 : documentState.rotation]);
49
52
  const shouldRenderMenu = selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;
50
53
  if (!boundingRect) return null;
51
54
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -105,27 +108,22 @@ function SelectionLayer({
105
108
  )
106
109
  ] });
107
110
  }
108
- function CopyToClipboard() {
109
- const { provides: sel } = useSelectionCapability();
110
- useEffect(() => {
111
- if (!sel) return;
112
- return sel.onCopyToClipboard(({ text }) => {
113
- navigator.clipboard.writeText(text);
114
- });
115
- }, [sel]);
116
- return null;
117
- }
118
111
  const MarqueeSelection = ({
119
112
  documentId,
120
113
  pageIndex,
121
114
  scale,
122
115
  className,
123
- stroke = "rgba(0,122,204,0.8)",
124
- fill = "rgba(0,122,204,0.15)"
116
+ background,
117
+ borderColor,
118
+ borderStyle = "dashed",
119
+ stroke,
120
+ fill
125
121
  }) => {
126
122
  const { plugin: selPlugin } = useSelectionPlugin();
127
123
  const documentState = useDocumentState(documentId);
128
124
  const [rect, setRect] = useState(null);
125
+ const resolvedBorderColor = borderColor ?? stroke ?? "rgba(0,122,204,0.8)";
126
+ const resolvedBackground = background ?? fill ?? "rgba(0,122,204,0.15)";
129
127
  const actualScale = useMemo(() => {
130
128
  if (scale !== void 0) return scale;
131
129
  return (documentState == null ? void 0 : documentState.scale) ?? 1;
@@ -150,8 +148,8 @@ const MarqueeSelection = ({
150
148
  top: rect.origin.y * actualScale,
151
149
  width: rect.size.width * actualScale,
152
150
  height: rect.size.height * actualScale,
153
- border: `1px dashed ${stroke}`,
154
- background: fill,
151
+ border: `1px ${borderStyle} ${resolvedBorderColor}`,
152
+ background: resolvedBackground,
155
153
  boxSizing: "border-box",
156
154
  zIndex: 1e3
157
155
  },
@@ -159,12 +157,60 @@ const MarqueeSelection = ({
159
157
  }
160
158
  );
161
159
  };
160
+ function SelectionLayer({
161
+ documentId,
162
+ pageIndex,
163
+ scale,
164
+ rotation,
165
+ background,
166
+ textStyle,
167
+ marqueeStyle,
168
+ marqueeClassName,
169
+ selectionMenu
170
+ }) {
171
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
172
+ /* @__PURE__ */ jsx(
173
+ TextSelection,
174
+ {
175
+ documentId,
176
+ pageIndex,
177
+ scale,
178
+ rotation,
179
+ background: (textStyle == null ? void 0 : textStyle.background) ?? background,
180
+ selectionMenu
181
+ }
182
+ ),
183
+ /* @__PURE__ */ jsx(
184
+ MarqueeSelection,
185
+ {
186
+ documentId,
187
+ pageIndex,
188
+ scale,
189
+ background: marqueeStyle == null ? void 0 : marqueeStyle.background,
190
+ borderColor: marqueeStyle == null ? void 0 : marqueeStyle.borderColor,
191
+ borderStyle: marqueeStyle == null ? void 0 : marqueeStyle.borderStyle,
192
+ className: marqueeClassName
193
+ }
194
+ )
195
+ ] });
196
+ }
197
+ function CopyToClipboard() {
198
+ const { provides: sel } = useSelectionCapability();
199
+ useEffect(() => {
200
+ if (!sel) return;
201
+ return sel.onCopyToClipboard(({ text }) => {
202
+ navigator.clipboard.writeText(text);
203
+ });
204
+ }, [sel]);
205
+ return null;
206
+ }
162
207
  const SelectionPluginPackage = createPluginPackage(SelectionPluginPackage$1).addUtility(CopyToClipboard).build();
163
208
  export {
164
209
  CopyToClipboard,
165
210
  MarqueeSelection,
166
211
  SelectionLayer,
167
212
  SelectionPluginPackage,
213
+ TextSelection,
168
214
  useSelectionCapability,
169
215
  useSelectionPlugin
170
216
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/selection-layer.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/components/marquee-selection.tsx","../../src/shared/index.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useEffect, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: Props) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n // Optimization: We could filter here, but React state updates are cheap enough usually.\n // Ideally, check: if (newPlacement?.pageIndex === pageIndex)\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n return documentState?.rotation ?? Rotation.Degree0;\n }, [rotationOverride, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n","import { useEffect } from '@framework';\n\nimport { useSelectionCapability } from '../hooks';\n\nexport function CopyToClipboard() {\n const { provides: sel } = useSelectionCapability();\n\n useEffect(() => {\n if (!sel) return;\n return sel.onCopyToClipboard(({ text }) => {\n navigator.clipboard.writeText(text);\n });\n }, [sel]);\n\n return null;\n}\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke colour (default: 'rgba(0,122,204,0.8)') */\n stroke?: string;\n /** Fill colour (default: 'rgba(0,122,204,0.15)') */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * Place this component on each page where you want marquee selection to work.\n *\n * Other plugins (e.g., annotation, form) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n stroke = 'rgba(0,122,204,0.8)',\n fill = 'rgba(0,122,204,0.15)',\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px dashed ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["rects","boundingRect","BaseSelectionPluginPackage"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-selection.ts","../../src/shared/components/text-selection.tsx","../../src/shared/components/marquee-selection.tsx","../../src/shared/components/selection-layer.tsx","../../src/shared/components/copy-to-clipboard.tsx","../../src/shared/index.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { SelectionPlugin } from '@embedpdf/plugin-selection';\n\nexport const useSelectionCapability = () => useCapability<SelectionPlugin>(SelectionPlugin.id);\nexport const useSelectionPlugin = () => usePlugin<SelectionPlugin>(SelectionPlugin.id);\n","import { useEffect, useMemo, useState } from '@framework';\nimport { Rect, Rotation } from '@embedpdf/models';\nimport { useSelectionPlugin } from '../hooks';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { SelectionMenuPlacement } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\n\ntype TextSelectionProps = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */\n background?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * TextSelection renders text selection highlight rects and the selection menu.\n * It registers the text selection handler on the page and subscribes to menu\n * placement changes.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport function TextSelection({\n documentId,\n pageIndex,\n scale: scaleOverride,\n rotation: rotationOverride,\n background = 'rgba(33,150,243)',\n selectionMenu,\n}: TextSelectionProps) {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const page = documentState?.document?.pages?.[pageIndex];\n const [rects, setRects] = useState<Rect[]>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n // Store the placement object from the plugin\n const [placement, setPlacement] = useState<SelectionMenuPlacement | null>(null);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerSelectionOnPage({\n documentId,\n pageIndex,\n onRectsChange: ({ rects, boundingRect }) => {\n setRects(rects);\n setBoundingRect(boundingRect);\n },\n });\n }, [selPlugin, documentId, pageIndex]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n // Subscribe to menu placement changes for this specific document\n return selPlugin.onMenuPlacement(documentId, (newPlacement) => {\n setPlacement(newPlacement);\n });\n }, [selPlugin, documentId]);\n\n const actualScale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotationOverride !== undefined) return rotationOverride;\n // Combine page intrinsic rotation with document rotation\n const pageRotation = page?.rotation ?? 0;\n const docRotation = documentState?.rotation ?? 0;\n return ((pageRotation + docRotation) % 4) as Rotation;\n }, [rotationOverride, page?.rotation, documentState?.rotation]);\n\n const shouldRenderMenu =\n selectionMenu && placement && placement.pageIndex === pageIndex && placement.isVisible;\n\n if (!boundingRect) return null;\n\n return (\n <>\n <div\n style={{\n position: 'absolute',\n left: boundingRect.origin.x * actualScale,\n top: boundingRect.origin.y * actualScale,\n width: boundingRect.size.width * actualScale,\n height: boundingRect.size.height * actualScale,\n mixBlendMode: 'multiply',\n isolation: 'isolate',\n pointerEvents: 'none',\n }}\n >\n {rects.map((b, i) => (\n <div\n key={i}\n style={{\n position: 'absolute',\n left: (b.origin.x - boundingRect.origin.x) * actualScale,\n top: (b.origin.y - boundingRect.origin.y) * actualScale,\n width: b.size.width * actualScale,\n height: b.size.height * actualScale,\n background,\n }}\n />\n ))}\n </div>\n {shouldRenderMenu && (\n <CounterRotate\n rect={{\n origin: {\n x: placement.rect.origin.x * actualScale,\n y: placement.rect.origin.y * actualScale,\n },\n size: {\n width: placement.rect.size.width * actualScale,\n height: placement.rect.size.height * actualScale,\n },\n }}\n rotation={actualRotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'selection',\n pageIndex,\n },\n selected: true,\n placement,\n })\n }\n </CounterRotate>\n )}\n </>\n );\n}\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useSelectionPlugin } from '../hooks';\n\ninterface MarqueeSelectionProps {\n /** Document ID */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page (optional, defaults to document scale) */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */\n background?: string;\n /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */\n borderColor?: string;\n /** Border style. Default: 'dashed' */\n borderStyle?: 'solid' | 'dashed' | 'dotted';\n /**\n * @deprecated Use `borderColor` instead.\n */\n stroke?: string;\n /**\n * @deprecated Use `background` instead.\n */\n fill?: string;\n}\n\n/**\n * MarqueeSelection renders a selection rectangle when the user drags to select items.\n * It registers the marquee handler on the page.\n *\n * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to\n * determine which objects intersect with the marquee rect.\n *\n * Use this component directly for advanced cases, or use `SelectionLayer`\n * which composes both `TextSelection` and `MarqueeSelection`.\n */\nexport const MarqueeSelection = ({\n documentId,\n pageIndex,\n scale,\n className,\n background,\n borderColor,\n borderStyle = 'dashed',\n stroke,\n fill,\n}: MarqueeSelectionProps) => {\n const { plugin: selPlugin } = useSelectionPlugin();\n const documentState = useDocumentState(documentId);\n const [rect, setRect] = useState<Rect | null>(null);\n\n // Resolve deprecated props: new CSS-standard props take precedence\n const resolvedBorderColor = borderColor ?? stroke ?? 'rgba(0,122,204,0.8)';\n const resolvedBackground = background ?? fill ?? 'rgba(0,122,204,0.15)';\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n useEffect(() => {\n if (!selPlugin || !documentId) return;\n\n return selPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale: actualScale,\n onRectChange: setRect,\n });\n }, [selPlugin, documentId, pageIndex, actualScale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * actualScale,\n top: rect.origin.y * actualScale,\n width: rect.size.width * actualScale,\n height: rect.size.height * actualScale,\n border: `1px ${borderStyle} ${resolvedBorderColor}`,\n background: resolvedBackground,\n boxSizing: 'border-box',\n zIndex: 1000,\n }}\n className={className}\n />\n );\n};\n","import { Fragment } from '@framework';\nimport { Rotation } from '@embedpdf/models';\nimport { TextSelectionStyle, MarqueeSelectionStyle } from '@embedpdf/plugin-selection';\nimport { SelectionSelectionMenuRenderFn } from '../types';\nimport { TextSelection } from './text-selection';\nimport { MarqueeSelection } from './marquee-selection';\n\ntype Props = {\n documentId: string;\n pageIndex: number;\n scale?: number;\n rotation?: Rotation;\n /**\n * @deprecated Use `textStyle.background` instead.\n */\n background?: string;\n /** Styling options for text selection highlights */\n textStyle?: TextSelectionStyle;\n /** Styling options for the marquee selection rectangle */\n marqueeStyle?: MarqueeSelectionStyle;\n /** Optional CSS class applied to the marquee rectangle */\n marqueeClassName?: string;\n selectionMenu?: SelectionSelectionMenuRenderFn;\n};\n\n/**\n * SelectionLayer is a convenience component that composes both text selection\n * and marquee selection on a single page.\n *\n * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`\n * individually.\n */\nexport function SelectionLayer({\n documentId,\n pageIndex,\n scale,\n rotation,\n background,\n textStyle,\n marqueeStyle,\n marqueeClassName,\n selectionMenu,\n}: Props) {\n return (\n <Fragment>\n <TextSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n rotation={rotation}\n background={textStyle?.background ?? background}\n selectionMenu={selectionMenu}\n />\n <MarqueeSelection\n documentId={documentId}\n pageIndex={pageIndex}\n scale={scale}\n background={marqueeStyle?.background}\n borderColor={marqueeStyle?.borderColor}\n borderStyle={marqueeStyle?.borderStyle}\n className={marqueeClassName}\n />\n </Fragment>\n );\n}\n","import { useEffect } from '@framework';\n\nimport { useSelectionCapability } from '../hooks';\n\nexport function CopyToClipboard() {\n const { provides: sel } = useSelectionCapability();\n\n useEffect(() => {\n if (!sel) return;\n return sel.onCopyToClipboard(({ text }) => {\n navigator.clipboard.writeText(text);\n });\n }, [sel]);\n\n return null;\n}\n","import { createPluginPackage } from '@embedpdf/core';\nimport { SelectionPluginPackage as BaseSelectionPluginPackage } from '@embedpdf/plugin-selection';\n\nimport { CopyToClipboard } from './components';\n\nexport * from './hooks';\nexport * from './components';\nexport * from './types';\nexport * from '@embedpdf/plugin-selection';\n\nexport const SelectionPluginPackage = createPluginPackage(BaseSelectionPluginPackage)\n .addUtility(CopyToClipboard)\n .build();\n"],"names":["rects","boundingRect","Fragment","BaseSelectionPluginPackage"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export * from './selection-layer';
2
+ export * from './text-selection';
2
3
  export * from './copy-to-clipboard';
3
4
  export * from './marquee-selection';
@@ -7,17 +7,30 @@ interface MarqueeSelectionProps {
7
7
  scale?: number;
8
8
  /** Optional CSS class applied to the marquee rectangle */
9
9
  className?: string;
10
- /** Stroke colour (default: 'rgba(0,122,204,0.8)') */
10
+ /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */
11
+ background?: string;
12
+ /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */
13
+ borderColor?: string;
14
+ /** Border style. Default: 'dashed' */
15
+ borderStyle?: 'solid' | 'dashed' | 'dotted';
16
+ /**
17
+ * @deprecated Use `borderColor` instead.
18
+ */
11
19
  stroke?: string;
12
- /** Fill colour (default: 'rgba(0,122,204,0.15)') */
20
+ /**
21
+ * @deprecated Use `background` instead.
22
+ */
13
23
  fill?: string;
14
24
  }
15
25
  /**
16
26
  * MarqueeSelection renders a selection rectangle when the user drags to select items.
17
- * Place this component on each page where you want marquee selection to work.
27
+ * It registers the marquee handler on the page.
18
28
  *
19
- * Other plugins (e.g., annotation, form) can subscribe to `onMarqueeEnd` to
29
+ * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to
20
30
  * determine which objects intersect with the marquee rect.
31
+ *
32
+ * Use this component directly for advanced cases, or use `SelectionLayer`
33
+ * which composes both `TextSelection` and `MarqueeSelection`.
21
34
  */
22
- export declare const MarqueeSelection: ({ documentId, pageIndex, scale, className, stroke, fill, }: MarqueeSelectionProps) => import("react/jsx-runtime").JSX.Element | null;
35
+ export declare const MarqueeSelection: ({ documentId, pageIndex, scale, className, background, borderColor, borderStyle, stroke, fill, }: MarqueeSelectionProps) => import("react/jsx-runtime").JSX.Element | null;
23
36
  export {};
@@ -1,12 +1,29 @@
1
1
  import { Rotation } from '@embedpdf/models';
2
+ import { TextSelectionStyle, MarqueeSelectionStyle } from '../../index.ts';
2
3
  import { SelectionSelectionMenuRenderFn } from '../types';
3
4
  type Props = {
4
5
  documentId: string;
5
6
  pageIndex: number;
6
7
  scale?: number;
7
8
  rotation?: Rotation;
9
+ /**
10
+ * @deprecated Use `textStyle.background` instead.
11
+ */
8
12
  background?: string;
13
+ /** Styling options for text selection highlights */
14
+ textStyle?: TextSelectionStyle;
15
+ /** Styling options for the marquee selection rectangle */
16
+ marqueeStyle?: MarqueeSelectionStyle;
17
+ /** Optional CSS class applied to the marquee rectangle */
18
+ marqueeClassName?: string;
9
19
  selectionMenu?: SelectionSelectionMenuRenderFn;
10
20
  };
11
- export declare function SelectionLayer({ documentId, pageIndex, scale: scaleOverride, rotation: rotationOverride, background, selectionMenu, }: Props): import("react/jsx-runtime").JSX.Element | null;
21
+ /**
22
+ * SelectionLayer is a convenience component that composes both text selection
23
+ * and marquee selection on a single page.
24
+ *
25
+ * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`
26
+ * individually.
27
+ */
28
+ export declare function SelectionLayer({ documentId, pageIndex, scale, rotation, background, textStyle, marqueeStyle, marqueeClassName, selectionMenu, }: Props): import("react/jsx-runtime").JSX.Element;
12
29
  export {};
@@ -0,0 +1,21 @@
1
+ import { Rotation } from '@embedpdf/models';
2
+ import { SelectionSelectionMenuRenderFn } from '../types';
3
+ type TextSelectionProps = {
4
+ documentId: string;
5
+ pageIndex: number;
6
+ scale?: number;
7
+ rotation?: Rotation;
8
+ /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */
9
+ background?: string;
10
+ selectionMenu?: SelectionSelectionMenuRenderFn;
11
+ };
12
+ /**
13
+ * TextSelection renders text selection highlight rects and the selection menu.
14
+ * It registers the text selection handler on the page and subscribes to menu
15
+ * placement changes.
16
+ *
17
+ * Use this component directly for advanced cases, or use `SelectionLayer`
18
+ * which composes both `TextSelection` and `MarqueeSelection`.
19
+ */
20
+ export declare function TextSelection({ documentId, pageIndex, scale: scaleOverride, rotation: rotationOverride, background, selectionMenu, }: TextSelectionProps): import("react/jsx-runtime").JSX.Element | null;
21
+ export {};
@@ -1,3 +1,4 @@
1
1
  export * from './selection-layer';
2
+ export * from './text-selection';
2
3
  export * from './copy-to-clipboard';
3
4
  export * from './marquee-selection';
@@ -7,17 +7,30 @@ interface MarqueeSelectionProps {
7
7
  scale?: number;
8
8
  /** Optional CSS class applied to the marquee rectangle */
9
9
  className?: string;
10
- /** Stroke colour (default: 'rgba(0,122,204,0.8)') */
10
+ /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */
11
+ background?: string;
12
+ /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */
13
+ borderColor?: string;
14
+ /** Border style. Default: 'dashed' */
15
+ borderStyle?: 'solid' | 'dashed' | 'dotted';
16
+ /**
17
+ * @deprecated Use `borderColor` instead.
18
+ */
11
19
  stroke?: string;
12
- /** Fill colour (default: 'rgba(0,122,204,0.15)') */
20
+ /**
21
+ * @deprecated Use `background` instead.
22
+ */
13
23
  fill?: string;
14
24
  }
15
25
  /**
16
26
  * MarqueeSelection renders a selection rectangle when the user drags to select items.
17
- * Place this component on each page where you want marquee selection to work.
27
+ * It registers the marquee handler on the page.
18
28
  *
19
- * Other plugins (e.g., annotation, form) can subscribe to `onMarqueeEnd` to
29
+ * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to
20
30
  * determine which objects intersect with the marquee rect.
31
+ *
32
+ * Use this component directly for advanced cases, or use `SelectionLayer`
33
+ * which composes both `TextSelection` and `MarqueeSelection`.
21
34
  */
22
- export declare const MarqueeSelection: ({ documentId, pageIndex, scale, className, stroke, fill, }: MarqueeSelectionProps) => import("preact").JSX.Element | null;
35
+ export declare const MarqueeSelection: ({ documentId, pageIndex, scale, className, background, borderColor, borderStyle, stroke, fill, }: MarqueeSelectionProps) => import("preact").JSX.Element | null;
23
36
  export {};
@@ -1,12 +1,29 @@
1
1
  import { Rotation } from '@embedpdf/models';
2
+ import { TextSelectionStyle, MarqueeSelectionStyle } from '../../lib/index.ts';
2
3
  import { SelectionSelectionMenuRenderFn } from '../types';
3
4
  type Props = {
4
5
  documentId: string;
5
6
  pageIndex: number;
6
7
  scale?: number;
7
8
  rotation?: Rotation;
9
+ /**
10
+ * @deprecated Use `textStyle.background` instead.
11
+ */
8
12
  background?: string;
13
+ /** Styling options for text selection highlights */
14
+ textStyle?: TextSelectionStyle;
15
+ /** Styling options for the marquee selection rectangle */
16
+ marqueeStyle?: MarqueeSelectionStyle;
17
+ /** Optional CSS class applied to the marquee rectangle */
18
+ marqueeClassName?: string;
9
19
  selectionMenu?: SelectionSelectionMenuRenderFn;
10
20
  };
11
- export declare function SelectionLayer({ documentId, pageIndex, scale: scaleOverride, rotation: rotationOverride, background, selectionMenu, }: Props): import("preact").JSX.Element | null;
21
+ /**
22
+ * SelectionLayer is a convenience component that composes both text selection
23
+ * and marquee selection on a single page.
24
+ *
25
+ * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`
26
+ * individually.
27
+ */
28
+ export declare function SelectionLayer({ documentId, pageIndex, scale, rotation, background, textStyle, marqueeStyle, marqueeClassName, selectionMenu, }: Props): import("preact").JSX.Element;
12
29
  export {};
@@ -0,0 +1,21 @@
1
+ import { Rotation } from '@embedpdf/models';
2
+ import { SelectionSelectionMenuRenderFn } from '../types';
3
+ type TextSelectionProps = {
4
+ documentId: string;
5
+ pageIndex: number;
6
+ scale?: number;
7
+ rotation?: Rotation;
8
+ /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */
9
+ background?: string;
10
+ selectionMenu?: SelectionSelectionMenuRenderFn;
11
+ };
12
+ /**
13
+ * TextSelection renders text selection highlight rects and the selection menu.
14
+ * It registers the text selection handler on the page and subscribes to menu
15
+ * placement changes.
16
+ *
17
+ * Use this component directly for advanced cases, or use `SelectionLayer`
18
+ * which composes both `TextSelection` and `MarqueeSelection`.
19
+ */
20
+ export declare function TextSelection({ documentId, pageIndex, scale: scaleOverride, rotation: rotationOverride, background, selectionMenu, }: TextSelectionProps): import("preact").JSX.Element | null;
21
+ export {};
@@ -1,3 +1,4 @@
1
1
  export * from './selection-layer';
2
+ export * from './text-selection';
2
3
  export * from './copy-to-clipboard';
3
4
  export * from './marquee-selection';
@@ -7,17 +7,30 @@ interface MarqueeSelectionProps {
7
7
  scale?: number;
8
8
  /** Optional CSS class applied to the marquee rectangle */
9
9
  className?: string;
10
- /** Stroke colour (default: 'rgba(0,122,204,0.8)') */
10
+ /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */
11
+ background?: string;
12
+ /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */
13
+ borderColor?: string;
14
+ /** Border style. Default: 'dashed' */
15
+ borderStyle?: 'solid' | 'dashed' | 'dotted';
16
+ /**
17
+ * @deprecated Use `borderColor` instead.
18
+ */
11
19
  stroke?: string;
12
- /** Fill colour (default: 'rgba(0,122,204,0.15)') */
20
+ /**
21
+ * @deprecated Use `background` instead.
22
+ */
13
23
  fill?: string;
14
24
  }
15
25
  /**
16
26
  * MarqueeSelection renders a selection rectangle when the user drags to select items.
17
- * Place this component on each page where you want marquee selection to work.
27
+ * It registers the marquee handler on the page.
18
28
  *
19
- * Other plugins (e.g., annotation, form) can subscribe to `onMarqueeEnd` to
29
+ * Other plugins (e.g., annotation, form, redaction) can subscribe to `onMarqueeEnd` to
20
30
  * determine which objects intersect with the marquee rect.
31
+ *
32
+ * Use this component directly for advanced cases, or use `SelectionLayer`
33
+ * which composes both `TextSelection` and `MarqueeSelection`.
21
34
  */
22
- export declare const MarqueeSelection: ({ documentId, pageIndex, scale, className, stroke, fill, }: MarqueeSelectionProps) => import("react/jsx-runtime").JSX.Element | null;
35
+ export declare const MarqueeSelection: ({ documentId, pageIndex, scale, className, background, borderColor, borderStyle, stroke, fill, }: MarqueeSelectionProps) => import("react/jsx-runtime").JSX.Element | null;
23
36
  export {};
@@ -1,12 +1,29 @@
1
1
  import { Rotation } from '@embedpdf/models';
2
+ import { TextSelectionStyle, MarqueeSelectionStyle } from '../../lib/index.ts';
2
3
  import { SelectionSelectionMenuRenderFn } from '../types';
3
4
  type Props = {
4
5
  documentId: string;
5
6
  pageIndex: number;
6
7
  scale?: number;
7
8
  rotation?: Rotation;
9
+ /**
10
+ * @deprecated Use `textStyle.background` instead.
11
+ */
8
12
  background?: string;
13
+ /** Styling options for text selection highlights */
14
+ textStyle?: TextSelectionStyle;
15
+ /** Styling options for the marquee selection rectangle */
16
+ marqueeStyle?: MarqueeSelectionStyle;
17
+ /** Optional CSS class applied to the marquee rectangle */
18
+ marqueeClassName?: string;
9
19
  selectionMenu?: SelectionSelectionMenuRenderFn;
10
20
  };
11
- export declare function SelectionLayer({ documentId, pageIndex, scale: scaleOverride, rotation: rotationOverride, background, selectionMenu, }: Props): import("react/jsx-runtime").JSX.Element | null;
21
+ /**
22
+ * SelectionLayer is a convenience component that composes both text selection
23
+ * and marquee selection on a single page.
24
+ *
25
+ * For advanced use cases, you can use `TextSelection` and `MarqueeSelection`
26
+ * individually.
27
+ */
28
+ export declare function SelectionLayer({ documentId, pageIndex, scale, rotation, background, textStyle, marqueeStyle, marqueeClassName, selectionMenu, }: Props): import("react/jsx-runtime").JSX.Element;
12
29
  export {};
@@ -0,0 +1,21 @@
1
+ import { Rotation } from '@embedpdf/models';
2
+ import { SelectionSelectionMenuRenderFn } from '../types';
3
+ type TextSelectionProps = {
4
+ documentId: string;
5
+ pageIndex: number;
6
+ scale?: number;
7
+ rotation?: Rotation;
8
+ /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */
9
+ background?: string;
10
+ selectionMenu?: SelectionSelectionMenuRenderFn;
11
+ };
12
+ /**
13
+ * TextSelection renders text selection highlight rects and the selection menu.
14
+ * It registers the text selection handler on the page and subscribes to menu
15
+ * placement changes.
16
+ *
17
+ * Use this component directly for advanced cases, or use `SelectionLayer`
18
+ * which composes both `TextSelection` and `MarqueeSelection`.
19
+ */
20
+ export declare function TextSelection({ documentId, pageIndex, scale: scaleOverride, rotation: rotationOverride, background, selectionMenu, }: TextSelectionProps): import("react/jsx-runtime").JSX.Element | null;
21
+ export {};
@@ -7,9 +7,19 @@ interface MarqueeSelectionProps {
7
7
  scale?: number;
8
8
  /** Optional CSS class applied to the marquee rectangle */
9
9
  class?: string;
10
- /** Stroke colour (default: 'rgba(0,122,204,0.8)') */
10
+ /** Fill/background color inside the marquee rectangle. Default: 'rgba(0,122,204,0.15)' */
11
+ background?: string;
12
+ /** Border color of the marquee rectangle. Default: 'rgba(0,122,204,0.8)' */
13
+ borderColor?: string;
14
+ /** Border style. Default: 'dashed' */
15
+ borderStyle?: 'solid' | 'dashed' | 'dotted';
16
+ /**
17
+ * @deprecated Use `borderColor` instead.
18
+ */
11
19
  stroke?: string;
12
- /** Fill colour (default: 'rgba(0,122,204,0.15)') */
20
+ /**
21
+ * @deprecated Use `background` instead.
22
+ */
13
23
  fill?: string;
14
24
  }
15
25
  declare const MarqueeSelection: import('svelte', { with: { "resolution-mode": "import" } }).Component<MarqueeSelectionProps, {}, "">;
@@ -1,5 +1,6 @@
1
1
  import { Snippet } from 'svelte';
2
2
  import { Rotation } from '@embedpdf/models';
3
+ import { TextSelectionStyle, MarqueeSelectionStyle } from '../../lib/index.ts';
3
4
  import { SelectionSelectionMenuRenderFn, SelectionSelectionMenuProps } from '../types';
4
5
  interface SelectionLayerProps {
5
6
  /** Document ID */
@@ -10,8 +11,17 @@ interface SelectionLayerProps {
10
11
  scale?: number;
11
12
  /** Rotation of the page (optional, defaults to document rotation) */
12
13
  rotation?: Rotation;
13
- /** Background color for selection rectangles */
14
+ /**
15
+ * @deprecated Use `textStyle.background` instead.
16
+ * Background color for selection rectangles.
17
+ */
14
18
  background?: string;
19
+ /** Styling options for text selection highlights */
20
+ textStyle?: TextSelectionStyle;
21
+ /** Styling options for the marquee selection rectangle */
22
+ marqueeStyle?: MarqueeSelectionStyle;
23
+ /** Optional CSS class applied to the marquee rectangle */
24
+ marqueeClass?: string;
15
25
  /** Render function for selection menu (schema-driven approach) */
16
26
  selectionMenu?: SelectionSelectionMenuRenderFn;
17
27
  /** Snippet for custom selection menu (slot-based approach) */
@@ -0,0 +1,22 @@
1
+ import { Snippet } from 'svelte';
2
+ import { Rotation } from '@embedpdf/models';
3
+ import { SelectionSelectionMenuRenderFn, SelectionSelectionMenuProps } from '../types';
4
+ interface TextSelectionProps {
5
+ /** Document ID */
6
+ documentId: string;
7
+ /** Index of the page this layer lives on */
8
+ pageIndex: number;
9
+ /** Scale of the page (optional, defaults to document scale) */
10
+ scale?: number;
11
+ /** Rotation of the page (optional, defaults to document rotation) */
12
+ rotation?: Rotation;
13
+ /** Background color for text selection highlights. Default: 'rgba(33,150,243)' */
14
+ background?: string;
15
+ /** Render function for selection menu (schema-driven approach) */
16
+ selectionMenu?: SelectionSelectionMenuRenderFn;
17
+ /** Snippet for custom selection menu (slot-based approach) */
18
+ selectionMenuSnippet?: Snippet<[SelectionSelectionMenuProps]>;
19
+ }
20
+ declare const TextSelection: import('svelte', { with: { "resolution-mode": "import" } }).Component<TextSelectionProps, {}, "">;
21
+ type TextSelection = ReturnType<typeof TextSelection>;
22
+ export default TextSelection;
@@ -1,3 +1,4 @@
1
1
  export { default as SelectionLayer } from './SelectionLayer.svelte';
2
+ export { default as TextSelection } from './TextSelection.svelte';
2
3
  export { default as CopyToClipboard } from './CopyToClipboard.svelte';
3
4
  export { default as MarqueeSelection } from './MarqueeSelection.svelte';
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection");require("svelte/internal/disclose-version");const i=require("svelte/internal/client"),n=require("@embedpdf/models"),o=require("@embedpdf/core/svelte"),r=require("@embedpdf/utils/svelte");function l(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const i in e)if("default"!==i){const n=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,n.get?n:{enumerable:!0,get:()=>e[i]})}return t.default=e,Object.freeze(t)}const s=l(i),p=()=>o.useCapability(t.SelectionPlugin.id),c=()=>o.usePlugin(t.SelectionPlugin.id);var d=s.from_html("<div></div>"),g=s.from_html("<div></div> <!>",1);function a(e,t){s.push(t,!0);const i=p();s.user_effect(()=>{if(i.provides)return i.provides.onCopyToClipboard(({text:e})=>{navigator.clipboard.writeText(e).catch(e=>{console.error("Failed to copy text to clipboard:",e)})})}),s.pop()}var u=s.from_html("<div></div>");const f=e.createPluginPackage(t.SelectionPluginPackage).addUtility(a).build();exports.CopyToClipboard=a,exports.MarqueeSelection=function(e,t){s.push(t,!0);let i=s.prop(t,"stroke",3,"rgba(0,122,204,0.8)"),n=s.prop(t,"fill",3,"rgba(0,122,204,0.15)");const r=c(),l=o.useDocumentState(()=>t.documentId);let p=s.state(null);const d=s.derived(()=>{var e;return void 0!==t.scale?t.scale:(null==(e=l.current)?void 0:e.scale)??1});s.user_effect(()=>{if(s.set(p,null),r.plugin)return r.plugin.registerMarqueeOnPage({documentId:t.documentId,pageIndex:t.pageIndex,scale:s.get(d),onRectChange:e=>{s.set(p,e,!0)}})});var g=s.comment(),a=s.first_child(g),f=e=>{var o=u();let r;s.template_effect(()=>{s.set_class(o,1,s.clsx(t.class)),r=s.set_style(o,"",r,{position:"absolute","pointer-events":"none",left:s.get(p).origin.x*s.get(d)+"px",top:s.get(p).origin.y*s.get(d)+"px",width:s.get(p).size.width*s.get(d)+"px",height:s.get(p).size.height*s.get(d)+"px",border:`1px dashed ${i()}`,background:n(),"box-sizing":"border-box","z-index":"1000"})}),s.append(e,o)};s.if(a,e=>{s.get(p)&&e(f)}),s.append(e,g),s.pop()},exports.SelectionLayer=function(e,t){s.push(t,!0);let i=s.prop(t,"background",3,"rgba(33,150,243)");const l=c(),p=o.useDocumentState(()=>t.documentId);let a=s.state(s.proxy([])),u=s.state(null),f=s.state(null);const v=s.derived(()=>{var e;return void 0!==t.scale?t.scale:(null==(e=p.current)?void 0:e.scale)??1}),m=s.derived(()=>{var e;return void 0!==t.rotation?t.rotation:(null==(e=p.current)?void 0:e.rotation)??n.Rotation.Degree0}),x=s.derived(()=>Boolean(s.get(f)&&s.get(f).pageIndex===t.pageIndex&&s.get(f).isVisible&&(t.selectionMenu||t.selectionMenuSnippet)));s.user_effect(()=>l.plugin&&t.documentId?l.plugin.registerSelectionOnPage({documentId:t.documentId,pageIndex:t.pageIndex,onRectsChange:({rects:e,boundingRect:t})=>{s.set(a,e,!0),s.set(u,t,!0)}}):(s.set(a,[],!0),void s.set(u,null))),s.user_effect(()=>{if(l.plugin&&t.documentId)return l.plugin.onMenuPlacement(t.documentId,e=>{s.set(f,e,!0)});s.set(f,null)});var h=s.comment(),b=s.first_child(h),y=e=>{var n=g(),o=s.first_child(n);let l;s.each(o,21,()=>s.get(a),s.index,(e,t)=>{var n=d();let o;s.template_effect(()=>o=s.set_style(n,"",o,{position:"absolute",left:(s.get(t).origin.x-s.get(u).origin.x)*s.get(v)+"px",top:(s.get(t).origin.y-s.get(u).origin.y)*s.get(v)+"px",width:s.get(t).size.width*s.get(v)+"px",height:s.get(t).size.height*s.get(v)+"px",background:i(),"pointer-events":"none"})),s.append(e,n)}),s.reset(o);var p=s.sibling(o,2),c=e=>{{const i=(e,i)=>{const n=s.derived(()=>function(e,i){return{context:{type:"selection",pageIndex:t.pageIndex},selected:!0,rect:e,placement:{suggestTop:(null==(n=s.get(f))?void 0:n.suggestTop)??!1,spaceAbove:(null==(o=s.get(f))?void 0:o.spaceAbove)??0,spaceBelow:(null==(r=s.get(f))?void 0:r.spaceBelow)??0},menuWrapperProps:i};var n,o,r}(null==i?void 0:i().rect,null==i?void 0:i().menuWrapperProps));var o=s.comment(),r=s.first_child(o),l=e=>{const i=s.derived(()=>t.selectionMenu(s.get(n)));var o=s.comment(),r=s.first_child(o),l=e=>{var t=s.comment(),n=s.first_child(t);s.component(n,()=>s.get(i).component,(e,t)=>{t(e,s.spread_props(()=>s.get(i).props))}),s.append(e,t)};s.if(r,e=>{s.get(i)&&e(l)}),s.append(e,o)},p=e=>{var i=s.comment(),o=s.first_child(i),r=e=>{var i=s.comment(),o=s.first_child(i);s.snippet(o,()=>t.selectionMenuSnippet,()=>s.get(n)),s.append(e,i)};s.if(o,e=>{t.selectionMenuSnippet&&e(r)},!0),s.append(e,i)};s.if(r,e=>{t.selectionMenu?e(l):e(p,!1)}),s.append(e,o)};let n=s.derived(()=>({origin:{x:s.get(f).rect.origin.x*s.get(v),y:s.get(f).rect.origin.y*s.get(v)},size:{width:s.get(f).rect.size.width*s.get(v),height:s.get(f).rect.size.height*s.get(v)}}));r.CounterRotate(e,{get rect(){return s.get(n)},get rotation(){return s.get(m)},children:i,$$slots:{default:!0}})}};s.if(p,e=>{s.get(x)&&s.get(f)&&e(c)}),s.template_effect(()=>l=s.set_style(o,"",l,{position:"absolute",left:s.get(u).origin.x*s.get(v)+"px",top:s.get(u).origin.y*s.get(v)+"px",width:s.get(u).size.width*s.get(v)+"px",height:s.get(u).size.height*s.get(v)+"px","mix-blend-mode":"multiply",isolation:"isolate","pointer-events":"none"})),s.append(e,n)};s.if(b,e=>{s.get(u)&&e(y)}),s.append(e,h),s.pop()},exports.SelectionPluginPackage=f,exports.useSelectionCapability=p,exports.useSelectionPlugin=c,Object.keys(t).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})});
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-selection");require("svelte/internal/disclose-version");const n=require("svelte/internal/client");require("@embedpdf/models");const r=require("@embedpdf/core/svelte"),o=require("@embedpdf/utils/svelte");function i(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}const l=i(n),d=()=>r.useCapability(t.SelectionPlugin.id),s=()=>r.usePlugin(t.SelectionPlugin.id);var u=l.from_html("<div></div>"),c=l.from_html("<div></div> <!>",1);function g(e,t){l.push(t,!0);let n=l.prop(t,"background",3,"rgba(33,150,243)");const i=s(),d=r.useDocumentState(()=>t.documentId),g=l.derived(()=>{var e,n,r;return null==(r=null==(n=null==(e=d.current)?void 0:e.document)?void 0:n.pages)?void 0:r[t.pageIndex]});let a=l.state(l.proxy([])),p=l.state(null),v=l.state(null);const f=l.derived(()=>{var e;return void 0!==t.scale?t.scale:(null==(e=d.current)?void 0:e.scale)??1}),m=l.derived(()=>{var e,n;if(void 0!==t.rotation)return t.rotation;return(((null==(e=l.get(g))?void 0:e.rotation)??0)+((null==(n=d.current)?void 0:n.rotation)??0))%4}),b=l.derived(()=>Boolean(l.get(v)&&l.get(v).pageIndex===t.pageIndex&&l.get(v).isVisible&&(t.selectionMenu||t.selectionMenuSnippet)));l.user_effect(()=>i.plugin&&t.documentId?i.plugin.registerSelectionOnPage({documentId:t.documentId,pageIndex:t.pageIndex,onRectsChange:({rects:e,boundingRect:t})=>{l.set(a,e,!0),l.set(p,t,!0)}}):(l.set(a,[],!0),void l.set(p,null))),l.user_effect(()=>{if(i.plugin&&t.documentId)return i.plugin.onMenuPlacement(t.documentId,e=>{l.set(v,e,!0)});l.set(v,null)});var x=l.comment(),h=l.first_child(x),y=e=>{var r=c(),i=l.first_child(r);let d;l.each(i,21,()=>l.get(a),l.index,(e,t)=>{var r=u();let o;l.template_effect(()=>o=l.set_style(r,"",o,{position:"absolute",left:(l.get(t).origin.x-l.get(p).origin.x)*l.get(f)+"px",top:(l.get(t).origin.y-l.get(p).origin.y)*l.get(f)+"px",width:l.get(t).size.width*l.get(f)+"px",height:l.get(t).size.height*l.get(f)+"px",background:n(),"pointer-events":"none"})),l.append(e,r)}),l.reset(i);var s=l.sibling(i,2),g=e=>{{const n=(e,n)=>{const r=l.derived(()=>function(e,n){return{context:{type:"selection",pageIndex:t.pageIndex},selected:!0,rect:e,placement:{suggestTop:(null==(r=l.get(v))?void 0:r.suggestTop)??!1,spaceAbove:(null==(o=l.get(v))?void 0:o.spaceAbove)??0,spaceBelow:(null==(i=l.get(v))?void 0:i.spaceBelow)??0},menuWrapperProps:n};var r,o,i}(null==n?void 0:n().rect,null==n?void 0:n().menuWrapperProps));var o=l.comment(),i=l.first_child(o),d=e=>{const n=l.derived(()=>t.selectionMenu(l.get(r)));var o=l.comment(),i=l.first_child(o),d=e=>{var t=l.comment(),r=l.first_child(t);l.component(r,()=>l.get(n).component,(e,t)=>{t(e,l.spread_props(()=>l.get(n).props))}),l.append(e,t)};l.if(i,e=>{l.get(n)&&e(d)}),l.append(e,o)},s=e=>{var n=l.comment(),o=l.first_child(n),i=e=>{var n=l.comment(),o=l.first_child(n);l.snippet(o,()=>t.selectionMenuSnippet,()=>l.get(r)),l.append(e,n)};l.if(o,e=>{t.selectionMenuSnippet&&e(i)},!0),l.append(e,n)};l.if(i,e=>{t.selectionMenu?e(d):e(s,!1)}),l.append(e,o)};let r=l.derived(()=>({origin:{x:l.get(v).rect.origin.x*l.get(f),y:l.get(v).rect.origin.y*l.get(f)},size:{width:l.get(v).rect.size.width*l.get(f),height:l.get(v).rect.size.height*l.get(f)}}));o.CounterRotate(e,{get rect(){return l.get(r)},get rotation(){return l.get(m)},children:n,$$slots:{default:!0}})}};l.if(s,e=>{l.get(b)&&l.get(v)&&e(g)}),l.template_effect(()=>d=l.set_style(i,"",d,{position:"absolute",left:l.get(p).origin.x*l.get(f)+"px",top:l.get(p).origin.y*l.get(f)+"px",width:l.get(p).size.width*l.get(f)+"px",height:l.get(p).size.height*l.get(f)+"px","mix-blend-mode":"multiply",isolation:"isolate","pointer-events":"none"})),l.append(e,r)};l.if(h,e=>{l.get(p)&&e(y)}),l.append(e,x),l.pop()}var a=l.from_html("<div></div>");function p(e,t){l.push(t,!0);let n=l.prop(t,"borderStyle",3,"dashed");const o=s(),i=r.useDocumentState(()=>t.documentId),d=l.derived(()=>t.borderColor??t.stroke??"rgba(0,122,204,0.8)"),u=l.derived(()=>t.background??t.fill??"rgba(0,122,204,0.15)");let c=l.state(null);const g=l.derived(()=>{var e;return void 0!==t.scale?t.scale:(null==(e=i.current)?void 0:e.scale)??1});l.user_effect(()=>{if(l.set(c,null),o.plugin)return o.plugin.registerMarqueeOnPage({documentId:t.documentId,pageIndex:t.pageIndex,scale:l.get(g),onRectChange:e=>{l.set(c,e,!0)}})});var p=l.comment(),v=l.first_child(p),f=e=>{var r=a();let o;l.template_effect(()=>{l.set_class(r,1,l.clsx(t.class)),o=l.set_style(r,"",o,{position:"absolute","pointer-events":"none",left:l.get(c).origin.x*l.get(g)+"px",top:l.get(c).origin.y*l.get(g)+"px",width:l.get(c).size.width*l.get(g)+"px",height:l.get(c).size.height*l.get(g)+"px",border:`1px ${n()} ${l.get(d)}`,background:l.get(u),"box-sizing":"border-box","z-index":"1000"})}),l.append(e,r)};l.if(v,e=>{l.get(c)&&e(f)}),l.append(e,p),l.pop()}var v=l.from_html("<!> <!>",1);function f(e,t){l.push(t,!0);const n=d();l.user_effect(()=>{if(n.provides)return n.provides.onCopyToClipboard(({text:e})=>{navigator.clipboard.writeText(e).catch(e=>{console.error("Failed to copy text to clipboard:",e)})})}),l.pop()}const m=e.createPluginPackage(t.SelectionPluginPackage).addUtility(f).build();exports.CopyToClipboard=f,exports.MarqueeSelection=p,exports.SelectionLayer=function(e,t){l.push(t,!0);const n=l.derived(()=>{var e;return(null==(e=t.textStyle)?void 0:e.background)??t.background});var r=v(),o=l.first_child(r);g(o,{get documentId(){return t.documentId},get pageIndex(){return t.pageIndex},get scale(){return t.scale},get rotation(){return t.rotation},get background(){return l.get(n)},get selectionMenu(){return t.selectionMenu},get selectionMenuSnippet(){return t.selectionMenuSnippet}});var i=l.sibling(o,2);{let e=l.derived(()=>{var e;return null==(e=t.marqueeStyle)?void 0:e.background}),n=l.derived(()=>{var e;return null==(e=t.marqueeStyle)?void 0:e.borderColor}),r=l.derived(()=>{var e;return null==(e=t.marqueeStyle)?void 0:e.borderStyle});p(i,{get documentId(){return t.documentId},get pageIndex(){return t.pageIndex},get scale(){return t.scale},get background(){return l.get(e)},get borderColor(){return l.get(n)},get borderStyle(){return l.get(r)},get class(){return t.marqueeClass}})}l.append(e,r),l.pop()},exports.SelectionPluginPackage=m,exports.TextSelection=g,exports.useSelectionCapability=d,exports.useSelectionPlugin=s,Object.keys(t).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})});
2
2
  //# sourceMappingURL=index.cjs.map