@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.
Files changed (107) hide show
  1. package/es/components/FilePond.d.ts +1 -1
  2. package/es/components/FilePond.js +1 -1
  3. package/es/components/ImageEditor/CropCanvas.d.ts +16 -0
  4. package/es/components/ImageEditor/CropCanvas.js +79 -0
  5. package/es/components/ImageEditor/DragHandle.d.ts +14 -0
  6. package/es/components/ImageEditor/DragHandle.js +40 -0
  7. package/es/components/ImageEditor/EdgeHandle.d.ts +16 -0
  8. package/es/components/ImageEditor/EdgeHandle.js +43 -0
  9. package/es/components/ImageEditor/ImageEditor.css +224 -0
  10. package/es/components/ImageEditor/ImageEditor.d.ts +24 -0
  11. package/es/components/ImageEditor/ImageEditor.js +108 -0
  12. package/es/components/ImageEditor/ResponsiveButton.d.ts +11 -0
  13. package/es/components/ImageEditor/ResponsiveButton.js +9 -0
  14. package/es/components/ImageEditor/defaultPlugins.d.ts +4 -0
  15. package/es/components/ImageEditor/defaultPlugins.js +8 -0
  16. package/es/components/ImageEditor/index.d.ts +6 -0
  17. package/es/components/ImageEditor/index.js +4 -0
  18. package/es/components/ImageEditor/plugins/cropPlugin/CropContext.d.ts +10 -0
  19. package/es/components/ImageEditor/plugins/cropPlugin/CropContext.js +14 -0
  20. package/es/components/ImageEditor/plugins/cropPlugin/CropOverlay.d.ts +2 -0
  21. package/es/components/ImageEditor/plugins/cropPlugin/CropOverlay.js +30 -0
  22. package/es/components/ImageEditor/plugins/cropPlugin/CropToolbar.d.ts +2 -0
  23. package/es/components/ImageEditor/plugins/cropPlugin/CropToolbar.js +16 -0
  24. package/es/components/ImageEditor/plugins/cropPlugin/index.d.ts +6 -0
  25. package/es/components/ImageEditor/plugins/cropPlugin/index.js +16 -0
  26. package/es/components/ImageEditor/plugins/cropPlugin/useCropTool.d.ts +34 -0
  27. package/es/components/ImageEditor/plugins/cropPlugin/useCropTool.js +138 -0
  28. package/es/components/ImageEditor/plugins/redactPlugin/RedactContext.d.ts +10 -0
  29. package/es/components/ImageEditor/plugins/redactPlugin/RedactContext.js +14 -0
  30. package/es/components/ImageEditor/plugins/redactPlugin/RedactOverlay.d.ts +6 -0
  31. package/es/components/ImageEditor/plugins/redactPlugin/RedactOverlay.js +29 -0
  32. package/es/components/ImageEditor/plugins/redactPlugin/RedactToolbar.d.ts +2 -0
  33. package/es/components/ImageEditor/plugins/redactPlugin/RedactToolbar.js +29 -0
  34. package/es/components/ImageEditor/plugins/redactPlugin/index.d.ts +6 -0
  35. package/es/components/ImageEditor/plugins/redactPlugin/index.js +16 -0
  36. package/es/components/ImageEditor/plugins/redactPlugin/useRedactTool.d.ts +49 -0
  37. package/es/components/ImageEditor/plugins/redactPlugin/useRedactTool.js +142 -0
  38. package/es/components/ImageEditor/plugins/rotatePlugin.d.ts +3 -0
  39. package/es/components/ImageEditor/plugins/rotatePlugin.js +39 -0
  40. package/es/components/ImageEditor/plugins/zoomPlugin/ZoomCanvas.d.ts +20 -0
  41. package/es/components/ImageEditor/plugins/zoomPlugin/ZoomCanvas.js +91 -0
  42. package/es/components/ImageEditor/plugins/zoomPlugin/ZoomContext.d.ts +6 -0
  43. package/es/components/ImageEditor/plugins/zoomPlugin/ZoomContext.js +14 -0
  44. package/es/components/ImageEditor/plugins/zoomPlugin/ZoomControls.d.ts +6 -0
  45. package/es/components/ImageEditor/plugins/zoomPlugin/ZoomControls.js +11 -0
  46. package/es/components/ImageEditor/plugins/zoomPlugin/index.d.ts +2 -0
  47. package/es/components/ImageEditor/plugins/zoomPlugin/index.js +10 -0
  48. package/es/components/ImageEditor/plugins/zoomPlugin/useZoomPan.d.ts +33 -0
  49. package/es/components/ImageEditor/plugins/zoomPlugin/useZoomPan.js +80 -0
  50. package/es/components/ImageEditor/types.d.ts +69 -0
  51. package/es/components/ImageEditor/types.js +1 -0
  52. package/es/components/ImageEditor/useActiveTool.d.ts +9 -0
  53. package/es/components/ImageEditor/useActiveTool.js +11 -0
  54. package/es/components/ImageEditor/useEdgeDetection.d.ts +18 -0
  55. package/es/components/ImageEditor/useEdgeDetection.js +125 -0
  56. package/es/components/ImageEditor/useImageEditor.d.ts +12 -0
  57. package/es/components/ImageEditor/useImageEditor.js +28 -0
  58. package/es/components/ImageEditor/useImageHistory.d.ts +21 -0
  59. package/es/components/ImageEditor/useImageHistory.js +153 -0
  60. package/es/components/ImageEditor/useOpenCV.d.ts +14 -0
  61. package/es/components/ImageEditor/useOpenCV.js +92 -0
  62. package/es/components/MergeProgressDialog/index.d.ts +8 -0
  63. package/es/components/MergeProgressDialog/index.js +136 -0
  64. package/es/components/PdfViewer/PdfViewer.css +12 -0
  65. package/es/components/PdfViewer/PdfViewer.d.ts +7 -0
  66. package/es/components/PdfViewer/PdfViewer.js +108 -0
  67. package/es/components/PdfViewer/index.d.ts +1 -0
  68. package/es/components/PdfViewer/index.js +1 -0
  69. package/es/index.d.ts +3 -0
  70. package/es/index.js +3 -0
  71. package/package.json +8 -3
  72. package/src/components/FilePond.tsx +1 -1
  73. package/src/components/ImageEditor/CropCanvas.tsx +100 -0
  74. package/src/components/ImageEditor/DragHandle.tsx +65 -0
  75. package/src/components/ImageEditor/EdgeHandle.tsx +65 -0
  76. package/src/components/ImageEditor/ImageEditor.css +224 -0
  77. package/src/components/ImageEditor/ImageEditor.tsx +310 -0
  78. package/src/components/ImageEditor/ResponsiveButton.tsx +32 -0
  79. package/src/components/ImageEditor/defaultPlugins.ts +10 -0
  80. package/src/components/ImageEditor/index.ts +6 -0
  81. package/src/components/ImageEditor/plugins/cropPlugin/CropContext.tsx +24 -0
  82. package/src/components/ImageEditor/plugins/cropPlugin/CropOverlay.tsx +119 -0
  83. package/src/components/ImageEditor/plugins/cropPlugin/CropToolbar.tsx +36 -0
  84. package/src/components/ImageEditor/plugins/cropPlugin/index.ts +20 -0
  85. package/src/components/ImageEditor/plugins/cropPlugin/useCropTool.ts +176 -0
  86. package/src/components/ImageEditor/plugins/redactPlugin/RedactContext.tsx +23 -0
  87. package/src/components/ImageEditor/plugins/redactPlugin/RedactOverlay.tsx +144 -0
  88. package/src/components/ImageEditor/plugins/redactPlugin/RedactToolbar.tsx +56 -0
  89. package/src/components/ImageEditor/plugins/redactPlugin/index.ts +20 -0
  90. package/src/components/ImageEditor/plugins/redactPlugin/useRedactTool.ts +197 -0
  91. package/src/components/ImageEditor/plugins/rotatePlugin.ts +43 -0
  92. package/src/components/ImageEditor/plugins/zoomPlugin/ZoomCanvas.tsx +123 -0
  93. package/src/components/ImageEditor/plugins/zoomPlugin/ZoomContext.tsx +15 -0
  94. package/src/components/ImageEditor/plugins/zoomPlugin/ZoomControls.tsx +43 -0
  95. package/src/components/ImageEditor/plugins/zoomPlugin/index.ts +12 -0
  96. package/src/components/ImageEditor/plugins/zoomPlugin/useZoomPan.ts +126 -0
  97. package/src/components/ImageEditor/types.ts +69 -0
  98. package/src/components/ImageEditor/useActiveTool.ts +21 -0
  99. package/src/components/ImageEditor/useEdgeDetection.ts +167 -0
  100. package/src/components/ImageEditor/useImageEditor.ts +39 -0
  101. package/src/components/ImageEditor/useImageHistory.ts +189 -0
  102. package/src/components/ImageEditor/useOpenCV.ts +134 -0
  103. package/src/components/MergeProgressDialog/index.tsx +249 -0
  104. package/src/components/PdfViewer/PdfViewer.css +12 -0
  105. package/src/components/PdfViewer/PdfViewer.tsx +139 -0
  106. package/src/components/PdfViewer/index.ts +1 -0
  107. 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";