@olenbetong/synergi-react 2.3.8 → 2.4.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.
- package/es/components/FilePond.d.ts +1 -1
- package/es/components/FilePond.js +1 -1
- package/es/components/ImageEditor/CropCanvas.d.ts +16 -0
- package/es/components/ImageEditor/CropCanvas.js +79 -0
- package/es/components/ImageEditor/DragHandle.d.ts +14 -0
- package/es/components/ImageEditor/DragHandle.js +40 -0
- package/es/components/ImageEditor/EdgeHandle.d.ts +16 -0
- package/es/components/ImageEditor/EdgeHandle.js +43 -0
- package/es/components/ImageEditor/ImageEditor.css +224 -0
- package/es/components/ImageEditor/ImageEditor.d.ts +24 -0
- package/es/components/ImageEditor/ImageEditor.js +108 -0
- package/es/components/ImageEditor/ResponsiveButton.d.ts +11 -0
- package/es/components/ImageEditor/ResponsiveButton.js +9 -0
- package/es/components/ImageEditor/defaultPlugins.d.ts +4 -0
- package/es/components/ImageEditor/defaultPlugins.js +8 -0
- package/es/components/ImageEditor/index.d.ts +6 -0
- package/es/components/ImageEditor/index.js +4 -0
- package/es/components/ImageEditor/plugins/cropPlugin/CropContext.d.ts +10 -0
- package/es/components/ImageEditor/plugins/cropPlugin/CropContext.js +14 -0
- package/es/components/ImageEditor/plugins/cropPlugin/CropOverlay.d.ts +2 -0
- package/es/components/ImageEditor/plugins/cropPlugin/CropOverlay.js +30 -0
- package/es/components/ImageEditor/plugins/cropPlugin/CropToolbar.d.ts +2 -0
- package/es/components/ImageEditor/plugins/cropPlugin/CropToolbar.js +16 -0
- package/es/components/ImageEditor/plugins/cropPlugin/index.d.ts +6 -0
- package/es/components/ImageEditor/plugins/cropPlugin/index.js +16 -0
- package/es/components/ImageEditor/plugins/cropPlugin/useCropTool.d.ts +34 -0
- package/es/components/ImageEditor/plugins/cropPlugin/useCropTool.js +138 -0
- package/es/components/ImageEditor/plugins/redactPlugin/RedactContext.d.ts +10 -0
- package/es/components/ImageEditor/plugins/redactPlugin/RedactContext.js +14 -0
- package/es/components/ImageEditor/plugins/redactPlugin/RedactOverlay.d.ts +6 -0
- package/es/components/ImageEditor/plugins/redactPlugin/RedactOverlay.js +29 -0
- package/es/components/ImageEditor/plugins/redactPlugin/RedactToolbar.d.ts +2 -0
- package/es/components/ImageEditor/plugins/redactPlugin/RedactToolbar.js +29 -0
- package/es/components/ImageEditor/plugins/redactPlugin/index.d.ts +6 -0
- package/es/components/ImageEditor/plugins/redactPlugin/index.js +16 -0
- package/es/components/ImageEditor/plugins/redactPlugin/useRedactTool.d.ts +49 -0
- package/es/components/ImageEditor/plugins/redactPlugin/useRedactTool.js +142 -0
- package/es/components/ImageEditor/plugins/rotatePlugin.d.ts +3 -0
- package/es/components/ImageEditor/plugins/rotatePlugin.js +39 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/ZoomCanvas.d.ts +20 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/ZoomCanvas.js +91 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/ZoomContext.d.ts +6 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/ZoomContext.js +14 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/ZoomControls.d.ts +6 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/ZoomControls.js +11 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/index.d.ts +2 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/index.js +10 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/useZoomPan.d.ts +33 -0
- package/es/components/ImageEditor/plugins/zoomPlugin/useZoomPan.js +80 -0
- package/es/components/ImageEditor/types.d.ts +69 -0
- package/es/components/ImageEditor/types.js +1 -0
- package/es/components/ImageEditor/useActiveTool.d.ts +9 -0
- package/es/components/ImageEditor/useActiveTool.js +11 -0
- package/es/components/ImageEditor/useEdgeDetection.d.ts +18 -0
- package/es/components/ImageEditor/useEdgeDetection.js +125 -0
- package/es/components/ImageEditor/useImageEditor.d.ts +12 -0
- package/es/components/ImageEditor/useImageEditor.js +28 -0
- package/es/components/ImageEditor/useImageHistory.d.ts +21 -0
- package/es/components/ImageEditor/useImageHistory.js +153 -0
- package/es/components/ImageEditor/useOpenCV.d.ts +14 -0
- package/es/components/ImageEditor/useOpenCV.js +92 -0
- package/es/components/MergeProgressDialog/index.d.ts +8 -0
- package/es/components/MergeProgressDialog/index.js +136 -0
- package/es/components/PdfViewer/PdfViewer.css +12 -0
- package/es/components/PdfViewer/PdfViewer.d.ts +7 -0
- package/es/components/PdfViewer/PdfViewer.js +108 -0
- package/es/components/PdfViewer/index.d.ts +1 -0
- package/es/components/PdfViewer/index.js +1 -0
- package/es/index.d.ts +3 -0
- package/es/index.js +3 -0
- package/package.json +8 -3
- package/src/components/FilePond.tsx +1 -1
- package/src/components/ImageEditor/CropCanvas.tsx +100 -0
- package/src/components/ImageEditor/DragHandle.tsx +65 -0
- package/src/components/ImageEditor/EdgeHandle.tsx +65 -0
- package/src/components/ImageEditor/ImageEditor.css +224 -0
- package/src/components/ImageEditor/ImageEditor.tsx +310 -0
- package/src/components/ImageEditor/ResponsiveButton.tsx +32 -0
- package/src/components/ImageEditor/defaultPlugins.ts +10 -0
- package/src/components/ImageEditor/index.ts +6 -0
- package/src/components/ImageEditor/plugins/cropPlugin/CropContext.tsx +24 -0
- package/src/components/ImageEditor/plugins/cropPlugin/CropOverlay.tsx +119 -0
- package/src/components/ImageEditor/plugins/cropPlugin/CropToolbar.tsx +36 -0
- package/src/components/ImageEditor/plugins/cropPlugin/index.ts +20 -0
- package/src/components/ImageEditor/plugins/cropPlugin/useCropTool.ts +176 -0
- package/src/components/ImageEditor/plugins/redactPlugin/RedactContext.tsx +23 -0
- package/src/components/ImageEditor/plugins/redactPlugin/RedactOverlay.tsx +144 -0
- package/src/components/ImageEditor/plugins/redactPlugin/RedactToolbar.tsx +56 -0
- package/src/components/ImageEditor/plugins/redactPlugin/index.ts +20 -0
- package/src/components/ImageEditor/plugins/redactPlugin/useRedactTool.ts +197 -0
- package/src/components/ImageEditor/plugins/rotatePlugin.ts +43 -0
- package/src/components/ImageEditor/plugins/zoomPlugin/ZoomCanvas.tsx +123 -0
- package/src/components/ImageEditor/plugins/zoomPlugin/ZoomContext.tsx +15 -0
- package/src/components/ImageEditor/plugins/zoomPlugin/ZoomControls.tsx +43 -0
- package/src/components/ImageEditor/plugins/zoomPlugin/index.ts +12 -0
- package/src/components/ImageEditor/plugins/zoomPlugin/useZoomPan.ts +126 -0
- package/src/components/ImageEditor/types.ts +69 -0
- package/src/components/ImageEditor/useActiveTool.ts +21 -0
- package/src/components/ImageEditor/useEdgeDetection.ts +167 -0
- package/src/components/ImageEditor/useImageEditor.ts +39 -0
- package/src/components/ImageEditor/useImageHistory.ts +189 -0
- package/src/components/ImageEditor/useOpenCV.ts +134 -0
- package/src/components/MergeProgressDialog/index.tsx +249 -0
- package/src/components/PdfViewer/PdfViewer.css +12 -0
- package/src/components/PdfViewer/PdfViewer.tsx +139 -0
- package/src/components/PdfViewer/index.ts +1 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { Document, Page, pdfjs } from "react-pdf";
|
|
3
|
+
import "./PdfViewer.css";
|
|
4
|
+
|
|
5
|
+
// Use new URL(..., import.meta.url) — understood by Rolldown/Rollup on all platforms,
|
|
6
|
+
// including Windows where ?raw query strings are invalid in file paths.
|
|
7
|
+
pdfjs.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url).toString();
|
|
8
|
+
|
|
9
|
+
type PdfViewerProps = { url?: string; file?: string | Blob | ArrayBuffer };
|
|
10
|
+
|
|
11
|
+
export function PdfViewer({ url, file }: PdfViewerProps) {
|
|
12
|
+
let [numPages, setNumPages] = useState(0);
|
|
13
|
+
let [error, setError] = useState<string | null>(null);
|
|
14
|
+
let containerRef = useRef<HTMLDivElement | null>(null);
|
|
15
|
+
let [containerWidth, setContainerWidth] = useState<number>(0);
|
|
16
|
+
let [containerHeight, setContainerHeight] = useState<number>(0);
|
|
17
|
+
let [scale, setScale] = useState<number>(1);
|
|
18
|
+
let [naturalPageSize, setNaturalPageSize] = useState<{
|
|
19
|
+
w: number;
|
|
20
|
+
h: number;
|
|
21
|
+
} | null>(null);
|
|
22
|
+
|
|
23
|
+
const pages = useMemo(() => Array.from({ length: numPages }, (_, i) => i + 1), [numPages]);
|
|
24
|
+
|
|
25
|
+
// Observe container size to support fit-to-page calculations
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
let el = containerRef.current;
|
|
28
|
+
if (!el) return;
|
|
29
|
+
let ro = new ResizeObserver((entries) => {
|
|
30
|
+
let cr = entries[0].contentRect;
|
|
31
|
+
setContainerWidth(Math.max(1, Math.floor(cr.width)));
|
|
32
|
+
setContainerHeight(Math.max(1, Math.floor(cr.height)));
|
|
33
|
+
});
|
|
34
|
+
ro.observe(el);
|
|
35
|
+
setContainerWidth(Math.max(1, Math.floor(el.clientWidth)));
|
|
36
|
+
setContainerHeight(Math.max(1, Math.floor(el.clientHeight)));
|
|
37
|
+
return () => ro.disconnect();
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
// Intercept browser zoom gestures and zoom the PDF instead
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
let el = containerRef.current;
|
|
43
|
+
if (!el) return;
|
|
44
|
+
|
|
45
|
+
const clamp = (v: number, min: number, max: number) => Math.min(max, Math.max(min, v));
|
|
46
|
+
const zoomBy = (delta: number) => {
|
|
47
|
+
// Smooth exponential zoom for trackpads/mice
|
|
48
|
+
const factor = Math.exp(delta * 0.001);
|
|
49
|
+
setScale((s) => clamp(s * factor, 0.25, 5));
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const onWheel = (e: WheelEvent) => {
|
|
53
|
+
if (e.ctrlKey) {
|
|
54
|
+
// ctrl+wheel is usually browser zoom; override for PDF zoom
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
zoomBy(-e.deltaY);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
61
|
+
if (!e.ctrlKey) return;
|
|
62
|
+
const key = e.key;
|
|
63
|
+
if (key === "+" || key === "=" || key === "Add") {
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
setScale((s) => clamp(s * 1.1, 0.25, 5));
|
|
66
|
+
} else if (key === "-" || key === "_" || key === "Subtract") {
|
|
67
|
+
e.preventDefault();
|
|
68
|
+
setScale((s) => clamp(s / 1.1, 0.25, 5));
|
|
69
|
+
} else if (key === "0") {
|
|
70
|
+
e.preventDefault();
|
|
71
|
+
setScale(1);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
76
|
+
window.addEventListener("keydown", onKeyDown, { passive: false });
|
|
77
|
+
return () => {
|
|
78
|
+
el.removeEventListener("wheel", onWheel as EventListener);
|
|
79
|
+
window.removeEventListener("keydown", onKeyDown as EventListener);
|
|
80
|
+
};
|
|
81
|
+
}, []);
|
|
82
|
+
|
|
83
|
+
// When source changes, reset auto-fit baseline
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
setNaturalPageSize(null);
|
|
86
|
+
setScale(1);
|
|
87
|
+
}, [url, file]);
|
|
88
|
+
|
|
89
|
+
// Compute base width to fit full page into container, then apply zoom scale.
|
|
90
|
+
// If we don't yet know page's natural size, default to fit-to-width.
|
|
91
|
+
const fitBaseWidth = useMemo(() => {
|
|
92
|
+
if (!naturalPageSize) return containerWidth || 1000;
|
|
93
|
+
const { w, h } = naturalPageSize;
|
|
94
|
+
if (w <= 0 || h <= 0) return containerWidth || 1000;
|
|
95
|
+
// width to fit by height: containerHeight * (w/h)
|
|
96
|
+
const widthByHeight = (containerHeight || 1000) * (w / h);
|
|
97
|
+
// Fit to page means respecting both constraints
|
|
98
|
+
return Math.min(Math.max(1, containerWidth || 1000), Math.max(1, widthByHeight));
|
|
99
|
+
}, [naturalPageSize, containerWidth, containerHeight]);
|
|
100
|
+
|
|
101
|
+
const pageWidth = Math.max(1, Math.round(fitBaseWidth * scale));
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div ref={containerRef} className="pdfViewerContainer">
|
|
105
|
+
<div className="pdfViewerContent">
|
|
106
|
+
<Document
|
|
107
|
+
file={file ?? url}
|
|
108
|
+
onLoadSuccess={({ numPages }) => setNumPages(numPages)}
|
|
109
|
+
onLoadError={(e) => setError((e as Error)?.message ?? "Failed to load PDF")}
|
|
110
|
+
>
|
|
111
|
+
{pages.map((pageNumber) => (
|
|
112
|
+
<Page
|
|
113
|
+
key={pageNumber}
|
|
114
|
+
pageNumber={pageNumber}
|
|
115
|
+
renderTextLayer={false}
|
|
116
|
+
renderAnnotationLayer={false}
|
|
117
|
+
width={pageWidth}
|
|
118
|
+
onLoadSuccess={(p) => {
|
|
119
|
+
// Capture natural page size once for fit-to-page calculation
|
|
120
|
+
try {
|
|
121
|
+
// pdf.js viewport at scale 1
|
|
122
|
+
const vp = p.getViewport({ scale: 1 });
|
|
123
|
+
const w = Number(vp?.width) || Number((p as any).width) || 0;
|
|
124
|
+
const h = Number(vp?.height) || Number((p as any).height) || 0;
|
|
125
|
+
if (w > 0 && h > 0 && !naturalPageSize) {
|
|
126
|
+
setNaturalPageSize({ w, h });
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
// Ignore, fallback to fit-to-width when unknown
|
|
130
|
+
}
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
))}
|
|
134
|
+
</Document>
|
|
135
|
+
</div>
|
|
136
|
+
{error && <div style={{ color: "#b00020", padding: 8 }}>Error loading PDF: {error}</div>}
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PdfViewer } from "./PdfViewer.js";
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,9 @@ export { Checkbox, type CheckboxProps } from "./components/Checkbox/index.js";
|
|
|
2
2
|
export { CardColumn, CardDetail, CardLabel, CardStep, CardStepList, ColorCard } from "./components/ColorCard/index.js";
|
|
3
3
|
export { DateNavigator } from "./components/DateNavigator/index.js";
|
|
4
4
|
export * from "./components/FilePond.js";
|
|
5
|
+
export * from "./components/ImageEditor/index.js";
|
|
5
6
|
export { Card, LinkedList, LinkedListItem } from "./components/LinkedCardList/index.js";
|
|
7
|
+
export { MergeProgressDialog, type MergeProgressDialogProps } from "./components/MergeProgressDialog/index.js";
|
|
6
8
|
export {
|
|
7
9
|
BannerImage as PageBannerImage,
|
|
8
10
|
type BannerImageProps,
|
|
@@ -15,6 +17,7 @@ export {
|
|
|
15
17
|
Title as PageBannerTitle,
|
|
16
18
|
type TitleProps as PageBannerTitleProps,
|
|
17
19
|
} from "./components/PageBanner/index.js";
|
|
20
|
+
export * from "./components/PdfViewer/index.js";
|
|
18
21
|
export { Portal } from "./components/Portal/index.js";
|
|
19
22
|
export { ProgressBar } from "./components/ProgressBar/index.js";
|
|
20
23
|
export { Sidebar, type SidebarProps } from "./components/Sidebar/index.js";
|