@signiphi/pdf-signer 0.1.1
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/INSTALLING_LOCALLY.md +184 -0
- package/LICENSE +2 -0
- package/README.md +1093 -0
- package/assets/viewer.html +314 -0
- package/dist/__tests__/helpers/fixtures.d.ts +43 -0
- package/dist/__tests__/helpers/fixtures.d.ts.map +1 -0
- package/dist/__tests__/helpers/mocks.d.ts +333 -0
- package/dist/__tests__/helpers/mocks.d.ts.map +1 -0
- package/dist/__tests__/setup.d.ts +6 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/components/AttachmentUpload.d.ts +17 -0
- package/dist/components/AttachmentUpload.d.ts.map +1 -0
- package/dist/components/EditableFieldsPanel.d.ts +30 -0
- package/dist/components/EditableFieldsPanel.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +67 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/FormFieldsView.d.ts +42 -0
- package/dist/components/FormFieldsView.d.ts.map +1 -0
- package/dist/components/PdfViewerStyled.d.ts +16 -0
- package/dist/components/PdfViewerStyled.d.ts.map +1 -0
- package/dist/components/PoweredBySigniphi.d.ts +11 -0
- package/dist/components/PoweredBySigniphi.d.ts.map +1 -0
- package/dist/components/SignatureCanvas.d.ts +12 -0
- package/dist/components/SignatureCanvas.d.ts.map +1 -0
- package/dist/components/SignatureInitialsBox.d.ts +23 -0
- package/dist/components/SignatureInitialsBox.d.ts.map +1 -0
- package/dist/components/SignatureModal.d.ts +22 -0
- package/dist/components/SignatureModal.d.ts.map +1 -0
- package/dist/components/SigningInstructions.d.ts +12 -0
- package/dist/components/SigningInstructions.d.ts.map +1 -0
- package/dist/components/SubmissionForm.d.ts +52 -0
- package/dist/components/SubmissionForm.d.ts.map +1 -0
- package/dist/components/ViewToggleToolbar.d.ts +30 -0
- package/dist/components/ViewToggleToolbar.d.ts.map +1 -0
- package/dist/components/form-fields/CheckboxRenderer.d.ts +10 -0
- package/dist/components/form-fields/CheckboxRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/DateFieldRenderer.d.ts +14 -0
- package/dist/components/form-fields/DateFieldRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/DropdownRenderer.d.ts +14 -0
- package/dist/components/form-fields/DropdownRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/FormFieldRenderer.d.ts +20 -0
- package/dist/components/form-fields/FormFieldRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/InitialsFieldRenderer.d.ts +14 -0
- package/dist/components/form-fields/InitialsFieldRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/RadioGroupRenderer.d.ts +10 -0
- package/dist/components/form-fields/RadioGroupRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/SignatureFieldRenderer.d.ts +16 -0
- package/dist/components/form-fields/SignatureFieldRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/TextFieldRenderer.d.ts +14 -0
- package/dist/components/form-fields/TextFieldRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/TextLabelRenderer.d.ts +14 -0
- package/dist/components/form-fields/TextLabelRenderer.d.ts.map +1 -0
- package/dist/components/form-fields/index.d.ts +14 -0
- package/dist/components/form-fields/index.d.ts.map +1 -0
- package/dist/components/index.d.ts +14 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +6297 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +6248 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/core/PdfViewerCore.d.ts +19 -0
- package/dist/core/PdfViewerCore.d.ts.map +1 -0
- package/dist/core/SignatureCaptureCore.d.ts +37 -0
- package/dist/core/SignatureCaptureCore.d.ts.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +907 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +884 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2167 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +2139 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/hooks/useAttachments.d.ts +25 -0
- package/dist/hooks/useAttachments.d.ts.map +1 -0
- package/dist/hooks/useFieldFiltering.d.ts +29 -0
- package/dist/hooks/useFieldFiltering.d.ts.map +1 -0
- package/dist/hooks/useFormFields.d.ts +23 -0
- package/dist/hooks/useFormFields.d.ts.map +1 -0
- package/dist/hooks/useMultiSignerContext.d.ts +25 -0
- package/dist/hooks/useMultiSignerContext.d.ts.map +1 -0
- package/dist/hooks/usePdfViewer.d.ts +52 -0
- package/dist/hooks/usePdfViewer.d.ts.map +1 -0
- package/dist/hooks/useSignatureCapture.d.ts +17 -0
- package/dist/hooks/useSignatureCapture.d.ts.map +1 -0
- package/dist/hooks/useSignatures.d.ts +25 -0
- package/dist/hooks/useSignatures.d.ts.map +1 -0
- package/dist/index.css +4929 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7220 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7093 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integrations/index.d.ts +6 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +242 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/index.mjs +218 -0
- package/dist/integrations/index.mjs.map +1 -0
- package/dist/integrations/next-config.d.ts +46 -0
- package/dist/integrations/next-config.d.ts.map +1 -0
- package/dist/integrations/vite-plugin.d.ts +48 -0
- package/dist/integrations/vite-plugin.d.ts.map +1 -0
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/ui/alert.d.ts +9 -0
- package/dist/lib/ui/alert.d.ts.map +1 -0
- package/dist/lib/ui/button.d.ts +12 -0
- package/dist/lib/ui/button.d.ts.map +1 -0
- package/dist/lib/ui/calendar.d.ts +10 -0
- package/dist/lib/ui/calendar.d.ts.map +1 -0
- package/dist/lib/ui/card.d.ts +9 -0
- package/dist/lib/ui/card.d.ts.map +1 -0
- package/dist/lib/ui/checkbox.d.ts +5 -0
- package/dist/lib/ui/checkbox.d.ts.map +1 -0
- package/dist/lib/ui/dialog.d.ts +20 -0
- package/dist/lib/ui/dialog.d.ts.map +1 -0
- package/dist/lib/ui/index.d.ts +12 -0
- package/dist/lib/ui/index.d.ts.map +1 -0
- package/dist/lib/ui/input.d.ts +6 -0
- package/dist/lib/ui/input.d.ts.map +1 -0
- package/dist/lib/ui/label.d.ts +6 -0
- package/dist/lib/ui/label.d.ts.map +1 -0
- package/dist/lib/ui/popover.d.ts +7 -0
- package/dist/lib/ui/popover.d.ts.map +1 -0
- package/dist/lib/ui/radio-group.d.ts +6 -0
- package/dist/lib/ui/radio-group.d.ts.map +1 -0
- package/dist/lib/ui/select.d.ts +14 -0
- package/dist/lib/ui/select.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +7 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/styles/index.css +5004 -0
- package/dist/types/index.d.ts +265 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +26 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.mjs +23 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/utils/attachment-validators.d.ts +118 -0
- package/dist/utils/attachment-validators.d.ts.map +1 -0
- package/dist/utils/audit-trail.d.ts +27 -0
- package/dist/utils/audit-trail.d.ts.map +1 -0
- package/dist/utils/date-validation.d.ts +30 -0
- package/dist/utils/date-validation.d.ts.map +1 -0
- package/dist/utils/errors.d.ts +106 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/field-extraction.d.ts +27 -0
- package/dist/utils/field-extraction.d.ts.map +1 -0
- package/dist/utils/field-visibility.d.ts +104 -0
- package/dist/utils/field-visibility.d.ts.map +1 -0
- package/dist/utils/index.d.ts +17 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2501 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +2404 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/pdf-field-type-helpers.d.ts +78 -0
- package/dist/utils/pdf-field-type-helpers.d.ts.map +1 -0
- package/dist/utils/pdf-helpers.d.ts +38 -0
- package/dist/utils/pdf-helpers.d.ts.map +1 -0
- package/dist/utils/pdf-lib-loader.d.ts +45 -0
- package/dist/utils/pdf-lib-loader.d.ts.map +1 -0
- package/dist/utils/pdf-manipulation.d.ts +93 -0
- package/dist/utils/pdf-manipulation.d.ts.map +1 -0
- package/dist/utils/pdf-validators.d.ts +149 -0
- package/dist/utils/pdf-validators.d.ts.map +1 -0
- package/dist/utils/pdf-viewer-filter.d.ts +35 -0
- package/dist/utils/pdf-viewer-filter.d.ts.map +1 -0
- package/dist/utils/pdf-widget-helpers.d.ts +98 -0
- package/dist/utils/pdf-widget-helpers.d.ts.map +1 -0
- package/dist/utils/pdfjs-config.d.ts +56 -0
- package/dist/utils/pdfjs-config.d.ts.map +1 -0
- package/dist/utils/pdfjs-version-check.d.ts +28 -0
- package/dist/utils/pdfjs-version-check.d.ts.map +1 -0
- package/dist/utils/performance-monitor.d.ts +172 -0
- package/dist/utils/performance-monitor.d.ts.map +1 -0
- package/dist/utils/tracking.d.ts +89 -0
- package/dist/utils/tracking.d.ts.map +1 -0
- package/package.json +180 -0
- package/scripts/analyze-bundle.js +271 -0
- package/scripts/copy-utils.js +227 -0
- package/scripts/copy-utils.test.js +164 -0
- package/scripts/postinstall.js +109 -0
- package/scripts/setup.js +108 -0
- package/src/styles/index.css +139 -0
|
@@ -0,0 +1,907 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var pdfjsLib = require('pdfjs-dist');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
function _interopNamespace(e) {
|
|
8
|
+
if (e && e.__esModule) return e;
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
|
|
26
|
+
|
|
27
|
+
// src/core/PdfViewerCore.tsx
|
|
28
|
+
var _workerSrcComputed = false;
|
|
29
|
+
var _cachedWorkerSrc = null;
|
|
30
|
+
function getDefaultWorkerSrc() {
|
|
31
|
+
if (_workerSrcComputed && _cachedWorkerSrc !== null) {
|
|
32
|
+
return _cachedWorkerSrc;
|
|
33
|
+
}
|
|
34
|
+
let workerSrc = "/pdfjs/build/pdf.worker.mjs";
|
|
35
|
+
if (typeof window !== "undefined" && typeof URL !== "undefined") {
|
|
36
|
+
try {
|
|
37
|
+
const meta = (function() {
|
|
38
|
+
try {
|
|
39
|
+
return new Function("return import.meta")();
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
})();
|
|
44
|
+
if (meta && meta.url) {
|
|
45
|
+
workerSrc = new URL("pdfjs-dist/build/pdf.worker.mjs", meta.url).href;
|
|
46
|
+
}
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
_workerSrcComputed = true;
|
|
51
|
+
_cachedWorkerSrc = workerSrc;
|
|
52
|
+
return workerSrc;
|
|
53
|
+
}
|
|
54
|
+
var globalConfig = {
|
|
55
|
+
viewerBasePath: "/pdfjs",
|
|
56
|
+
workerSrc: ""
|
|
57
|
+
// Lazy-initialized below
|
|
58
|
+
};
|
|
59
|
+
var _configInitialized = false;
|
|
60
|
+
function ensureConfigInitialized() {
|
|
61
|
+
if (!_configInitialized) {
|
|
62
|
+
globalConfig.workerSrc = getDefaultWorkerSrc();
|
|
63
|
+
_configInitialized = true;
|
|
64
|
+
if (typeof window !== "undefined") {
|
|
65
|
+
pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = globalConfig.workerSrc;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function getPdfJsConfig() {
|
|
70
|
+
ensureConfigInitialized();
|
|
71
|
+
return { ...globalConfig };
|
|
72
|
+
}
|
|
73
|
+
function initializePdfJs() {
|
|
74
|
+
ensureConfigInitialized();
|
|
75
|
+
}
|
|
76
|
+
async function checkPdfJsVersion(viewerBasePath = "/pdfjs") {
|
|
77
|
+
const workerVersion = pdfjsLib__namespace.version;
|
|
78
|
+
try {
|
|
79
|
+
const versionUrl = `${viewerBasePath}/.version`;
|
|
80
|
+
const response = await fetch(versionUrl);
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
return {
|
|
83
|
+
viewerExists: false,
|
|
84
|
+
versionMatch: false,
|
|
85
|
+
workerVersion,
|
|
86
|
+
errorMessage: "PDF.js viewer files not found. Run: npx signiphi-setup"
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const viewerVersion = (await response.text()).trim();
|
|
90
|
+
const versionMatch = viewerVersion === workerVersion;
|
|
91
|
+
if (!versionMatch) {
|
|
92
|
+
return {
|
|
93
|
+
viewerExists: true,
|
|
94
|
+
versionMatch: false,
|
|
95
|
+
viewerVersion,
|
|
96
|
+
workerVersion,
|
|
97
|
+
errorMessage: `Version mismatch: viewer=${viewerVersion}, worker=${workerVersion}. Run: npx signiphi-setup`
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
viewerExists: true,
|
|
102
|
+
versionMatch: true,
|
|
103
|
+
viewerVersion,
|
|
104
|
+
workerVersion
|
|
105
|
+
};
|
|
106
|
+
} catch (error) {
|
|
107
|
+
return {
|
|
108
|
+
viewerExists: false,
|
|
109
|
+
versionMatch: false,
|
|
110
|
+
workerVersion,
|
|
111
|
+
errorMessage: "Unable to check PDF.js version. Viewer files may not be installed."
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/utils/logger.ts
|
|
117
|
+
function isProduction() {
|
|
118
|
+
return typeof process !== "undefined" && process.env.NODE_ENV === "production";
|
|
119
|
+
}
|
|
120
|
+
function createPrefix(level) {
|
|
121
|
+
return `[@signiphi/pdf-signer] [${level.toUpperCase()}]`;
|
|
122
|
+
}
|
|
123
|
+
function createLogger() {
|
|
124
|
+
const isProd = isProduction();
|
|
125
|
+
return {
|
|
126
|
+
debug(message, ...args) {
|
|
127
|
+
if (!isProd) {
|
|
128
|
+
console.log(createPrefix("debug"), message, ...args);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
info(message, ...args) {
|
|
132
|
+
if (!isProd) {
|
|
133
|
+
console.log(createPrefix("info"), message, ...args);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
warn(message, ...args) {
|
|
137
|
+
if (!isProd) {
|
|
138
|
+
console.warn(createPrefix("warn"), message, ...args);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
error(message, ...args) {
|
|
142
|
+
console.error(createPrefix("error"), message, ...args);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
var logger = createLogger();
|
|
147
|
+
var PdfViewerCore = react.forwardRef(
|
|
148
|
+
({ onLoad, onError, pdfjsBasePath, children }, ref) => {
|
|
149
|
+
const iframeRef = react.useRef(null);
|
|
150
|
+
const loadedPdfUrl = react.useRef(null);
|
|
151
|
+
const initializationPromise = react.useRef(null);
|
|
152
|
+
const isLoadingRef = react.useRef(false);
|
|
153
|
+
const [versionChecked, setVersionChecked] = react.useState(false);
|
|
154
|
+
const [setupError, setSetupError] = react.useState(null);
|
|
155
|
+
const getPDFViewerApplication = react.useCallback(() => {
|
|
156
|
+
try {
|
|
157
|
+
const iframe = iframeRef.current;
|
|
158
|
+
if (!iframe || !iframe.contentWindow) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
const PDFViewerApplication = iframe.contentWindow.PDFViewerApplication;
|
|
162
|
+
if (!PDFViewerApplication) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return PDFViewerApplication;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
logger.error("Error accessing PDFViewerApplication:", error);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}, []);
|
|
171
|
+
const waitForInitialization = react.useCallback(async () => {
|
|
172
|
+
const PDFViewerApplication = getPDFViewerApplication();
|
|
173
|
+
if (!PDFViewerApplication) {
|
|
174
|
+
throw new Error("PDFViewerApplication not available");
|
|
175
|
+
}
|
|
176
|
+
if (PDFViewerApplication.initializedPromise) {
|
|
177
|
+
await PDFViewerApplication.initializedPromise;
|
|
178
|
+
}
|
|
179
|
+
if (PDFViewerApplication.pdfLoadingTask) {
|
|
180
|
+
await PDFViewerApplication.pdfLoadingTask.promise;
|
|
181
|
+
}
|
|
182
|
+
return PDFViewerApplication;
|
|
183
|
+
}, [getPDFViewerApplication]);
|
|
184
|
+
const loadPdf = react.useCallback(
|
|
185
|
+
async (pdfUrl) => {
|
|
186
|
+
const iframe = iframeRef.current;
|
|
187
|
+
if (!iframe) {
|
|
188
|
+
logger.error("PDF viewer iframe not available");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (isLoadingRef.current || loadedPdfUrl.current === pdfUrl) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
isLoadingRef.current = true;
|
|
195
|
+
loadedPdfUrl.current = pdfUrl;
|
|
196
|
+
try {
|
|
197
|
+
initializePdfJs();
|
|
198
|
+
const response = await fetch(pdfUrl);
|
|
199
|
+
if (!response.ok) {
|
|
200
|
+
throw new Error(`Failed to fetch PDF: ${response.status}`);
|
|
201
|
+
}
|
|
202
|
+
const pdfBytes = await response.arrayBuffer();
|
|
203
|
+
const blob = new Blob([pdfBytes], { type: "application/pdf" });
|
|
204
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
205
|
+
const config = getPdfJsConfig();
|
|
206
|
+
const basePath = pdfjsBasePath ?? config.viewerBasePath;
|
|
207
|
+
const viewerUrl = `${basePath}/web/viewer.html?file=${encodeURIComponent(blobUrl)}`;
|
|
208
|
+
iframe.src = viewerUrl;
|
|
209
|
+
initializationPromise.current = new Promise((resolve, reject) => {
|
|
210
|
+
const checkInitialization = () => {
|
|
211
|
+
try {
|
|
212
|
+
const PDFViewerApplication = getPDFViewerApplication();
|
|
213
|
+
if (PDFViewerApplication && PDFViewerApplication.initializedPromise) {
|
|
214
|
+
PDFViewerApplication.initializedPromise.then(() => {
|
|
215
|
+
resolve();
|
|
216
|
+
}).catch(reject);
|
|
217
|
+
} else {
|
|
218
|
+
setTimeout(checkInitialization, 100);
|
|
219
|
+
}
|
|
220
|
+
} catch (error) {
|
|
221
|
+
reject(error);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
setTimeout(checkInitialization, 500);
|
|
225
|
+
});
|
|
226
|
+
} catch (error) {
|
|
227
|
+
logger.error("Error fetching PDF:", error);
|
|
228
|
+
isLoadingRef.current = false;
|
|
229
|
+
onError?.(error instanceof Error ? error.message : "Unknown error");
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
[getPDFViewerApplication, onError, pdfjsBasePath]
|
|
233
|
+
);
|
|
234
|
+
const getFormFieldValues = react.useCallback(async () => {
|
|
235
|
+
try {
|
|
236
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
237
|
+
if (!PDFViewerApplication.pdfDocument) {
|
|
238
|
+
return {};
|
|
239
|
+
}
|
|
240
|
+
const pdfDocument = PDFViewerApplication.pdfDocument;
|
|
241
|
+
const values = {};
|
|
242
|
+
if (pdfDocument.annotationStorage) {
|
|
243
|
+
const annotationStorage = pdfDocument.annotationStorage;
|
|
244
|
+
let fieldObjects = {};
|
|
245
|
+
try {
|
|
246
|
+
if (pdfDocument.getFieldObjects) {
|
|
247
|
+
const result = await pdfDocument.getFieldObjects();
|
|
248
|
+
fieldObjects = result || {};
|
|
249
|
+
}
|
|
250
|
+
} catch (error) {
|
|
251
|
+
logger.warn("Error getting field objects:", error);
|
|
252
|
+
}
|
|
253
|
+
const idToNameMap = {};
|
|
254
|
+
const fieldInfo = {};
|
|
255
|
+
for (const [name, fields] of Object.entries(fieldObjects)) {
|
|
256
|
+
const fieldArray = fields;
|
|
257
|
+
fieldInfo[name] = {
|
|
258
|
+
type: fieldArray[0]?.type || "",
|
|
259
|
+
widgets: fieldArray
|
|
260
|
+
};
|
|
261
|
+
for (const field of fieldArray) {
|
|
262
|
+
if (field.id) {
|
|
263
|
+
idToNameMap[field.id] = name;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
let storedData = {};
|
|
268
|
+
if (annotationStorage.serializable && annotationStorage.serializable.map) {
|
|
269
|
+
const storageMap = annotationStorage.serializable.map;
|
|
270
|
+
for (const [key, value] of storageMap.entries()) {
|
|
271
|
+
storedData[key] = value;
|
|
272
|
+
}
|
|
273
|
+
} else if (typeof annotationStorage.getAll === "function") {
|
|
274
|
+
storedData = annotationStorage.getAll();
|
|
275
|
+
}
|
|
276
|
+
const radioGroups = {};
|
|
277
|
+
for (const [id, data] of Object.entries(storedData)) {
|
|
278
|
+
const fieldName = idToNameMap[id];
|
|
279
|
+
if (!fieldName) continue;
|
|
280
|
+
const fieldType = fieldInfo[fieldName]?.type;
|
|
281
|
+
const isRadioButton = fieldType && (fieldType.toLowerCase().includes("radio") || fieldType.toLowerCase().includes("radiobutton") || fieldType === "radiobutton");
|
|
282
|
+
const widgetCount = fieldInfo[fieldName]?.widgets?.length || 0;
|
|
283
|
+
const isLikelyRadioGroup = widgetCount > 1 && fieldName.toLowerCase().includes("radio");
|
|
284
|
+
if (fieldName && (isRadioButton || isLikelyRadioGroup)) {
|
|
285
|
+
if (!radioGroups[fieldName]) {
|
|
286
|
+
radioGroups[fieldName] = [];
|
|
287
|
+
}
|
|
288
|
+
const widget = fieldInfo[fieldName]?.widgets?.find((w) => w.id === id);
|
|
289
|
+
radioGroups[fieldName].push({ id, data, widget });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
for (const [fieldName, radioButtons] of Object.entries(radioGroups)) {
|
|
293
|
+
const selectedRadio = radioButtons.find(
|
|
294
|
+
(rb) => rb.data && typeof rb.data === "object" && rb.data.value === true
|
|
295
|
+
);
|
|
296
|
+
if (selectedRadio) {
|
|
297
|
+
const sortedRadioButtons = [...radioButtons].sort((a, b) => {
|
|
298
|
+
const aNum = parseInt(a.id.replace(/\D/g, ""), 10) || 0;
|
|
299
|
+
const bNum = parseInt(b.id.replace(/\D/g, ""), 10) || 0;
|
|
300
|
+
return aNum - bNum;
|
|
301
|
+
});
|
|
302
|
+
const selectedIndex = sortedRadioButtons.findIndex((rb) => rb.id === selectedRadio.id);
|
|
303
|
+
if (selectedIndex >= 0) {
|
|
304
|
+
const exportValue = `__RADIO_OPTION_INDEX_${selectedIndex}__`;
|
|
305
|
+
values[fieldName] = exportValue;
|
|
306
|
+
} else {
|
|
307
|
+
values[fieldName] = "true";
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
for (const [id, data] of Object.entries(storedData)) {
|
|
312
|
+
const fieldName = idToNameMap[id];
|
|
313
|
+
if (fieldName && values[fieldName]) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (fieldName) {
|
|
317
|
+
let extractedValue;
|
|
318
|
+
if (data && typeof data === "object") {
|
|
319
|
+
const dataObj = data;
|
|
320
|
+
if ("value" in dataObj) {
|
|
321
|
+
extractedValue = String(dataObj.value);
|
|
322
|
+
} else if ("formValue" in dataObj) {
|
|
323
|
+
extractedValue = String(dataObj.formValue);
|
|
324
|
+
} else if ("textContent" in dataObj) {
|
|
325
|
+
extractedValue = String(dataObj.textContent);
|
|
326
|
+
}
|
|
327
|
+
} else if (data !== void 0 && data !== null) {
|
|
328
|
+
extractedValue = String(data);
|
|
329
|
+
}
|
|
330
|
+
if (extractedValue !== void 0 && extractedValue !== "") {
|
|
331
|
+
values[fieldName] = extractedValue;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
for (const [name, fields] of Object.entries(fieldObjects)) {
|
|
336
|
+
if (!values[name]) {
|
|
337
|
+
const fieldArray = fields;
|
|
338
|
+
const field = fieldArray[0];
|
|
339
|
+
if (field && field.value !== void 0 && field.value !== null) {
|
|
340
|
+
const fieldValue = String(field.value);
|
|
341
|
+
const fieldType = fieldInfo[name]?.type;
|
|
342
|
+
const isRadioButton = fieldType && (fieldType.toLowerCase().includes("radio") || fieldType === "radiobutton");
|
|
343
|
+
if (isRadioButton && fieldValue !== "true" && fieldValue !== "false") {
|
|
344
|
+
const widgets = fieldInfo[name]?.widgets || [];
|
|
345
|
+
if (widgets.length > 0) {
|
|
346
|
+
const sortedWidgets = [...widgets].sort((a, b) => {
|
|
347
|
+
const aNum = parseInt((a.id || "").replace(/\D/g, ""), 10) || 0;
|
|
348
|
+
const bNum = parseInt((b.id || "").replace(/\D/g, ""), 10) || 0;
|
|
349
|
+
return aNum - bNum;
|
|
350
|
+
});
|
|
351
|
+
const selectedIndex = sortedWidgets.findIndex(
|
|
352
|
+
(widget) => widget.exportValue === fieldValue || widget.buttonValue === fieldValue
|
|
353
|
+
);
|
|
354
|
+
if (selectedIndex >= 0) {
|
|
355
|
+
values[name] = `__RADIO_OPTION_INDEX_${selectedIndex}__`;
|
|
356
|
+
} else {
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
values[name] = fieldValue;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return values;
|
|
367
|
+
} catch (error) {
|
|
368
|
+
logger.error("Error extracting form field values:", error);
|
|
369
|
+
return {};
|
|
370
|
+
}
|
|
371
|
+
}, [waitForInitialization]);
|
|
372
|
+
const setFormFieldValues = react.useCallback(async (values) => {
|
|
373
|
+
const iframe = iframeRef.current;
|
|
374
|
+
if (!iframe || !iframe.contentWindow) {
|
|
375
|
+
logger.warn("Cannot set field values: iframe not available");
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
await waitForInitialization();
|
|
380
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
381
|
+
const iframeDoc = iframe.contentWindow.document;
|
|
382
|
+
for (const [fieldName, value] of Object.entries(values)) {
|
|
383
|
+
try {
|
|
384
|
+
let decodedFieldName = fieldName;
|
|
385
|
+
if (fieldName.includes("__LABEL__")) {
|
|
386
|
+
decodedFieldName = fieldName.substring(0, fieldName.indexOf("__LABEL__"));
|
|
387
|
+
} else if (fieldName.includes("__SIGNER__")) {
|
|
388
|
+
decodedFieldName = fieldName.substring(0, fieldName.indexOf("__SIGNER__"));
|
|
389
|
+
} else if (fieldName.includes("__PLACEHOLDER__")) {
|
|
390
|
+
decodedFieldName = fieldName.substring(0, fieldName.indexOf("__PLACEHOLDER__"));
|
|
391
|
+
}
|
|
392
|
+
let elements = iframeDoc.querySelectorAll(
|
|
393
|
+
`[data-element-id="${fieldName}"], [name="${fieldName}"], [data-element-id="${decodedFieldName}"], [name="${decodedFieldName}"]`
|
|
394
|
+
);
|
|
395
|
+
if (elements.length === 0) {
|
|
396
|
+
logger.warn(`Field element not found for: ${fieldName}`);
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
const firstElement = elements[0];
|
|
400
|
+
const isRadioGroup = elements.length > 1 && (firstElement.tagName || "").toLowerCase() === "input" && (firstElement.type || "") === "radio";
|
|
401
|
+
if (isRadioGroup) {
|
|
402
|
+
if (value.includes("__RADIO_OPTION_INDEX_")) {
|
|
403
|
+
const match = value.match(/__RADIO_OPTION_INDEX_(\d+)__/);
|
|
404
|
+
if (match && match[1]) {
|
|
405
|
+
const selectedIndex = parseInt(match[1], 10);
|
|
406
|
+
if (selectedIndex < elements.length) {
|
|
407
|
+
const radioElement = elements[selectedIndex];
|
|
408
|
+
radioElement.checked = true;
|
|
409
|
+
radioElement.dispatchEvent(new Event("change", { bubbles: true }));
|
|
410
|
+
radioElement.dispatchEvent(new Event("input", { bubbles: true }));
|
|
411
|
+
radioElement.dispatchEvent(new Event("click", { bubbles: true }));
|
|
412
|
+
} else {
|
|
413
|
+
logger.warn(`Radio button index ${selectedIndex} out of range for ${fieldName}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
const element = elements[0];
|
|
419
|
+
const tagName = (element.tagName || "").toLowerCase();
|
|
420
|
+
if (tagName === "input") {
|
|
421
|
+
const inputType = element.type || "text";
|
|
422
|
+
if (inputType === "checkbox") {
|
|
423
|
+
const boolValue = value === "true" || value === "Yes" || value === "On";
|
|
424
|
+
element.checked = boolValue;
|
|
425
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
426
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
427
|
+
element.dispatchEvent(new Event("click", { bubbles: true }));
|
|
428
|
+
} else if (inputType === "radio") {
|
|
429
|
+
element.checked = value === "true" || value === element.value;
|
|
430
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
431
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
432
|
+
element.dispatchEvent(new Event("click", { bubbles: true }));
|
|
433
|
+
} else {
|
|
434
|
+
element.value = value;
|
|
435
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
436
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
437
|
+
}
|
|
438
|
+
} else if (tagName === "select") {
|
|
439
|
+
element.value = value;
|
|
440
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
441
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
442
|
+
} else if (tagName === "textarea") {
|
|
443
|
+
element.value = value;
|
|
444
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
445
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
446
|
+
} else {
|
|
447
|
+
logger.warn(`Unknown element type for field ${fieldName}: ${tagName}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
} catch (fieldError) {
|
|
451
|
+
logger.error(`Error setting value for field ${fieldName}:`, fieldError);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
} catch (error) {
|
|
455
|
+
logger.error("Error setting form field values:", error);
|
|
456
|
+
}
|
|
457
|
+
}, [waitForInitialization]);
|
|
458
|
+
const getAllFieldNames = react.useCallback(async () => {
|
|
459
|
+
try {
|
|
460
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
461
|
+
if (!PDFViewerApplication.pdfDocument) {
|
|
462
|
+
return [];
|
|
463
|
+
}
|
|
464
|
+
const pdfDocument = PDFViewerApplication.pdfDocument;
|
|
465
|
+
let fieldObjects = {};
|
|
466
|
+
try {
|
|
467
|
+
if (pdfDocument.getFieldObjects) {
|
|
468
|
+
const result = await pdfDocument.getFieldObjects();
|
|
469
|
+
fieldObjects = result || {};
|
|
470
|
+
}
|
|
471
|
+
} catch (error) {
|
|
472
|
+
return [];
|
|
473
|
+
}
|
|
474
|
+
return Object.keys(fieldObjects);
|
|
475
|
+
} catch (error) {
|
|
476
|
+
logger.error("Error getting all field names:", error);
|
|
477
|
+
return [];
|
|
478
|
+
}
|
|
479
|
+
}, [waitForInitialization]);
|
|
480
|
+
const saveDocument = react.useCallback(async () => {
|
|
481
|
+
try {
|
|
482
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
483
|
+
if (!PDFViewerApplication.pdfDocument) {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
const pdfDocument = PDFViewerApplication.pdfDocument;
|
|
487
|
+
if (typeof pdfDocument.saveDocument === "function") {
|
|
488
|
+
const savedBytes = await pdfDocument.saveDocument();
|
|
489
|
+
return new Uint8Array(savedBytes);
|
|
490
|
+
} else if (pdfDocument.getData) {
|
|
491
|
+
const originalData = await pdfDocument.getData();
|
|
492
|
+
return new Uint8Array(originalData);
|
|
493
|
+
}
|
|
494
|
+
return null;
|
|
495
|
+
} catch (error) {
|
|
496
|
+
logger.error("Error saving PDF document:", error);
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
}, [waitForInitialization]);
|
|
500
|
+
const injectPlaceholders = react.useCallback((fields) => {
|
|
501
|
+
const iframe = iframeRef.current;
|
|
502
|
+
if (!iframe || !iframe.contentWindow) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
setTimeout(() => {
|
|
506
|
+
try {
|
|
507
|
+
const iframeDoc = iframe.contentWindow.document;
|
|
508
|
+
const placeholderMap = /* @__PURE__ */ new Map();
|
|
509
|
+
fields.forEach((field) => {
|
|
510
|
+
if (field.placeholder) {
|
|
511
|
+
placeholderMap.set(field.name, field.placeholder);
|
|
512
|
+
placeholderMap.set(field.id, field.placeholder);
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
const inputs = iframeDoc.querySelectorAll("input[data-element-id], input[name]");
|
|
516
|
+
inputs.forEach((input) => {
|
|
517
|
+
const htmlInput = input;
|
|
518
|
+
const fieldId = htmlInput.getAttribute("data-element-id") || htmlInput.name;
|
|
519
|
+
if (fieldId) {
|
|
520
|
+
const placeholder = placeholderMap.get(fieldId);
|
|
521
|
+
if (placeholder) {
|
|
522
|
+
htmlInput.placeholder = placeholder;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
} catch (error) {
|
|
527
|
+
logger.error("Error injecting placeholders:", error);
|
|
528
|
+
}
|
|
529
|
+
}, 1e3);
|
|
530
|
+
}, []);
|
|
531
|
+
const zoomIn = react.useCallback(async () => {
|
|
532
|
+
try {
|
|
533
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
534
|
+
if (PDFViewerApplication.pdfViewer && typeof PDFViewerApplication.pdfViewer.increaseScale === "function") {
|
|
535
|
+
PDFViewerApplication.pdfViewer.increaseScale();
|
|
536
|
+
}
|
|
537
|
+
} catch (error) {
|
|
538
|
+
logger.error("Error zooming in:", error);
|
|
539
|
+
}
|
|
540
|
+
}, [waitForInitialization]);
|
|
541
|
+
const zoomOut = react.useCallback(async () => {
|
|
542
|
+
try {
|
|
543
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
544
|
+
if (PDFViewerApplication.pdfViewer && typeof PDFViewerApplication.pdfViewer.decreaseScale === "function") {
|
|
545
|
+
PDFViewerApplication.pdfViewer.decreaseScale();
|
|
546
|
+
}
|
|
547
|
+
} catch (error) {
|
|
548
|
+
logger.error("Error zooming out:", error);
|
|
549
|
+
}
|
|
550
|
+
}, [waitForInitialization]);
|
|
551
|
+
const nextPage = react.useCallback(async () => {
|
|
552
|
+
try {
|
|
553
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
554
|
+
if (PDFViewerApplication.pdfViewer && typeof PDFViewerApplication.pdfViewer.nextPage === "function") {
|
|
555
|
+
PDFViewerApplication.pdfViewer.nextPage();
|
|
556
|
+
}
|
|
557
|
+
} catch (error) {
|
|
558
|
+
logger.error("Error going to next page:", error);
|
|
559
|
+
}
|
|
560
|
+
}, [waitForInitialization]);
|
|
561
|
+
const previousPage = react.useCallback(async () => {
|
|
562
|
+
try {
|
|
563
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
564
|
+
if (PDFViewerApplication.pdfViewer && typeof PDFViewerApplication.pdfViewer.previousPage === "function") {
|
|
565
|
+
PDFViewerApplication.pdfViewer.previousPage();
|
|
566
|
+
}
|
|
567
|
+
} catch (error) {
|
|
568
|
+
logger.error("Error going to previous page:", error);
|
|
569
|
+
}
|
|
570
|
+
}, [waitForInitialization]);
|
|
571
|
+
const getCurrentPage = react.useCallback(async () => {
|
|
572
|
+
try {
|
|
573
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
574
|
+
if (PDFViewerApplication.pdfViewer && typeof PDFViewerApplication.pdfViewer.currentPageNumber === "number") {
|
|
575
|
+
return PDFViewerApplication.pdfViewer.currentPageNumber;
|
|
576
|
+
}
|
|
577
|
+
return null;
|
|
578
|
+
} catch (error) {
|
|
579
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
580
|
+
if (!errorMsg.includes("not available") && !errorMsg.includes("not yet initialized")) {
|
|
581
|
+
logger.error("Error getting current page:", error);
|
|
582
|
+
}
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
}, [waitForInitialization]);
|
|
586
|
+
const getTotalPages = react.useCallback(async () => {
|
|
587
|
+
try {
|
|
588
|
+
const PDFViewerApplication = await waitForInitialization();
|
|
589
|
+
if (PDFViewerApplication.pdfViewer && typeof PDFViewerApplication.pdfViewer.pagesCount === "number") {
|
|
590
|
+
return PDFViewerApplication.pdfViewer.pagesCount;
|
|
591
|
+
}
|
|
592
|
+
return null;
|
|
593
|
+
} catch (error) {
|
|
594
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
595
|
+
if (!errorMsg.includes("not available") && !errorMsg.includes("not yet initialized")) {
|
|
596
|
+
logger.error("Error getting total pages:", error);
|
|
597
|
+
}
|
|
598
|
+
return null;
|
|
599
|
+
}
|
|
600
|
+
}, [waitForInitialization]);
|
|
601
|
+
react.useEffect(() => {
|
|
602
|
+
if (!versionChecked) {
|
|
603
|
+
const config = getPdfJsConfig();
|
|
604
|
+
const basePath = pdfjsBasePath ?? config.viewerBasePath;
|
|
605
|
+
checkPdfJsVersion(basePath).then((result) => {
|
|
606
|
+
setVersionChecked(true);
|
|
607
|
+
if (!result.viewerExists) {
|
|
608
|
+
const errorMsg = `\u26A0\uFE0F PDF.js files not found
|
|
609
|
+
|
|
610
|
+
The PDF viewer requires PDF.js files to be installed.
|
|
611
|
+
This should happen automatically, but you can run:
|
|
612
|
+
|
|
613
|
+
npx signiphi-setup
|
|
614
|
+
|
|
615
|
+
Or reinstall the package:
|
|
616
|
+
|
|
617
|
+
npm install @signiphi/pdf-signer`;
|
|
618
|
+
setSetupError(errorMsg);
|
|
619
|
+
logger.error(errorMsg);
|
|
620
|
+
} else if (!result.versionMatch) {
|
|
621
|
+
logger.warn(
|
|
622
|
+
`\u26A0\uFE0F PDF.js version mismatch:
|
|
623
|
+
Viewer: ${result.viewerVersion}
|
|
624
|
+
Worker: ${result.workerVersion}
|
|
625
|
+
Run: npx signiphi-setup to sync versions`
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
}).catch((error) => {
|
|
629
|
+
logger.error("Failed to check PDF.js version:", error);
|
|
630
|
+
setVersionChecked(true);
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
}, [pdfjsBasePath, versionChecked]);
|
|
634
|
+
const handleIframeLoad = react.useCallback(() => {
|
|
635
|
+
const iframe = iframeRef.current;
|
|
636
|
+
if (!iframe || !iframe.contentWindow) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
try {
|
|
640
|
+
if (iframe.contentDocument) {
|
|
641
|
+
const title = iframe.contentDocument.title;
|
|
642
|
+
const body = iframe.contentDocument.body;
|
|
643
|
+
if (title?.includes("404") || title?.includes("Not Found") || body?.textContent?.includes("404") || body?.textContent?.includes("Cannot GET")) {
|
|
644
|
+
const errorMsg = setupError || `\u26A0\uFE0F PDF.js viewer not found
|
|
645
|
+
|
|
646
|
+
The viewer.html file could not be loaded from the configured path.
|
|
647
|
+
Run: npx signiphi-setup
|
|
648
|
+
|
|
649
|
+
Or check your configuration.`;
|
|
650
|
+
logger.error(errorMsg);
|
|
651
|
+
isLoadingRef.current = false;
|
|
652
|
+
onError?.(errorMsg);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
setTimeout(async () => {
|
|
657
|
+
try {
|
|
658
|
+
if (initializationPromise.current) {
|
|
659
|
+
await initializationPromise.current;
|
|
660
|
+
isLoadingRef.current = false;
|
|
661
|
+
onLoad?.();
|
|
662
|
+
} else {
|
|
663
|
+
const PDFViewerApplication = getPDFViewerApplication();
|
|
664
|
+
if (PDFViewerApplication) {
|
|
665
|
+
isLoadingRef.current = false;
|
|
666
|
+
onLoad?.();
|
|
667
|
+
} else {
|
|
668
|
+
throw new Error("PDFViewerApplication not found after iframe load");
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
} catch (error) {
|
|
672
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error loading PDF viewer";
|
|
673
|
+
logger.error("Error in PDF.js initialization:", error);
|
|
674
|
+
isLoadingRef.current = false;
|
|
675
|
+
onError?.(errorMessage);
|
|
676
|
+
}
|
|
677
|
+
}, 1e3);
|
|
678
|
+
} catch (error) {
|
|
679
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error in iframe load handler";
|
|
680
|
+
logger.error("Error in iframe load handler:", error);
|
|
681
|
+
isLoadingRef.current = false;
|
|
682
|
+
onError?.(errorMessage);
|
|
683
|
+
}
|
|
684
|
+
}, [getPDFViewerApplication, onLoad, onError, setupError]);
|
|
685
|
+
react.useImperativeHandle(
|
|
686
|
+
ref,
|
|
687
|
+
() => ({
|
|
688
|
+
loadPdf,
|
|
689
|
+
getFormFieldValues,
|
|
690
|
+
setFormFieldValues,
|
|
691
|
+
getAllFieldNames,
|
|
692
|
+
saveDocument,
|
|
693
|
+
getPDFViewerApplication,
|
|
694
|
+
injectPlaceholders,
|
|
695
|
+
zoomIn,
|
|
696
|
+
zoomOut,
|
|
697
|
+
nextPage,
|
|
698
|
+
previousPage,
|
|
699
|
+
getCurrentPage,
|
|
700
|
+
getTotalPages
|
|
701
|
+
}),
|
|
702
|
+
[loadPdf, getFormFieldValues, setFormFieldValues, getAllFieldNames, saveDocument, getPDFViewerApplication, injectPlaceholders, zoomIn, zoomOut, nextPage, previousPage, getCurrentPage, getTotalPages]
|
|
703
|
+
);
|
|
704
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children({ iframeRef, handleIframeLoad }) });
|
|
705
|
+
}
|
|
706
|
+
);
|
|
707
|
+
PdfViewerCore.displayName = "PdfViewerCore";
|
|
708
|
+
var SignatureCaptureCore = react.forwardRef(
|
|
709
|
+
({ width = 400, height = 200, onSignature, children }, ref) => {
|
|
710
|
+
const canvasRef = react.useRef(null);
|
|
711
|
+
const containerRef = react.useRef(null);
|
|
712
|
+
const [isDrawing, setIsDrawing] = react.useState(false);
|
|
713
|
+
const [isEmpty, setIsEmpty] = react.useState(true);
|
|
714
|
+
const [lastPoint, setLastPoint] = react.useState(null);
|
|
715
|
+
const [canvasSize, setCanvasSize] = react.useState({ width, height });
|
|
716
|
+
react.useEffect(() => {
|
|
717
|
+
const updateCanvasSize = () => {
|
|
718
|
+
if (containerRef.current) {
|
|
719
|
+
const containerWidth = containerRef.current.offsetWidth;
|
|
720
|
+
const maxWidth = Math.max(containerWidth - 16, width);
|
|
721
|
+
const aspectRatio = width / height;
|
|
722
|
+
const newHeight = maxWidth / aspectRatio;
|
|
723
|
+
setCanvasSize({
|
|
724
|
+
width: maxWidth,
|
|
725
|
+
height: newHeight
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
setTimeout(updateCanvasSize, 100);
|
|
730
|
+
window.addEventListener("resize", updateCanvasSize);
|
|
731
|
+
return () => window.removeEventListener("resize", updateCanvasSize);
|
|
732
|
+
}, [width, height]);
|
|
733
|
+
const getCanvasContext = react.useCallback(() => {
|
|
734
|
+
const canvas = canvasRef.current;
|
|
735
|
+
if (!canvas) return null;
|
|
736
|
+
const ctx = canvas.getContext("2d");
|
|
737
|
+
if (!ctx) return null;
|
|
738
|
+
return { canvas, ctx };
|
|
739
|
+
}, []);
|
|
740
|
+
const setupCanvas = react.useCallback(() => {
|
|
741
|
+
const result = getCanvasContext();
|
|
742
|
+
if (!result) return;
|
|
743
|
+
const { canvas, ctx } = result;
|
|
744
|
+
canvas.width = canvasSize.width;
|
|
745
|
+
canvas.height = canvasSize.height;
|
|
746
|
+
ctx.strokeStyle = "#000000";
|
|
747
|
+
ctx.lineWidth = window.innerWidth < 768 ? 3 : 2;
|
|
748
|
+
ctx.lineCap = "round";
|
|
749
|
+
ctx.lineJoin = "round";
|
|
750
|
+
ctx.imageSmoothingEnabled = true;
|
|
751
|
+
ctx.fillStyle = "#ffffff";
|
|
752
|
+
ctx.fillRect(0, 0, canvasSize.width, canvasSize.height);
|
|
753
|
+
}, [canvasSize, getCanvasContext]);
|
|
754
|
+
const clear = react.useCallback(() => {
|
|
755
|
+
const result = getCanvasContext();
|
|
756
|
+
if (!result) return;
|
|
757
|
+
const { ctx } = result;
|
|
758
|
+
ctx.fillStyle = "#ffffff";
|
|
759
|
+
ctx.fillRect(0, 0, canvasSize.width, canvasSize.height);
|
|
760
|
+
queueMicrotask(() => setIsEmpty(true));
|
|
761
|
+
}, [canvasSize, getCanvasContext]);
|
|
762
|
+
const getSignatureDataUrl = react.useCallback(() => {
|
|
763
|
+
const canvas = canvasRef.current;
|
|
764
|
+
if (!canvas || isEmpty) return null;
|
|
765
|
+
return canvas.toDataURL("image/png");
|
|
766
|
+
}, [isEmpty]);
|
|
767
|
+
const getRelativePosition = react.useCallback(
|
|
768
|
+
(e) => {
|
|
769
|
+
const canvas = canvasRef.current;
|
|
770
|
+
if (!canvas) return null;
|
|
771
|
+
const rect = canvas.getBoundingClientRect();
|
|
772
|
+
const scaleX = canvas.width / rect.width;
|
|
773
|
+
const scaleY = canvas.height / rect.height;
|
|
774
|
+
let clientX, clientY;
|
|
775
|
+
if ("touches" in e) {
|
|
776
|
+
const touch = e.touches[0] || e.changedTouches[0];
|
|
777
|
+
if (!touch) return null;
|
|
778
|
+
clientX = touch.clientX;
|
|
779
|
+
clientY = touch.clientY;
|
|
780
|
+
} else {
|
|
781
|
+
clientX = e.clientX;
|
|
782
|
+
clientY = e.clientY;
|
|
783
|
+
}
|
|
784
|
+
return {
|
|
785
|
+
x: (clientX - rect.left) * scaleX,
|
|
786
|
+
y: (clientY - rect.top) * scaleY
|
|
787
|
+
};
|
|
788
|
+
},
|
|
789
|
+
[]
|
|
790
|
+
);
|
|
791
|
+
const drawLine = react.useCallback(
|
|
792
|
+
(from, to) => {
|
|
793
|
+
const result = getCanvasContext();
|
|
794
|
+
if (!result) return;
|
|
795
|
+
const { ctx } = result;
|
|
796
|
+
ctx.beginPath();
|
|
797
|
+
ctx.moveTo(from.x, from.y);
|
|
798
|
+
ctx.lineTo(to.x, to.y);
|
|
799
|
+
ctx.stroke();
|
|
800
|
+
queueMicrotask(() => setIsEmpty(false));
|
|
801
|
+
},
|
|
802
|
+
[getCanvasContext]
|
|
803
|
+
);
|
|
804
|
+
const startDrawing = react.useCallback(
|
|
805
|
+
(e) => {
|
|
806
|
+
e.preventDefault();
|
|
807
|
+
const point = getRelativePosition(e);
|
|
808
|
+
if (!point) return;
|
|
809
|
+
setIsDrawing(true);
|
|
810
|
+
setLastPoint(point);
|
|
811
|
+
},
|
|
812
|
+
[getRelativePosition]
|
|
813
|
+
);
|
|
814
|
+
const draw = react.useCallback(
|
|
815
|
+
(e) => {
|
|
816
|
+
if (!isDrawing || !lastPoint) return;
|
|
817
|
+
e.preventDefault();
|
|
818
|
+
const point = getRelativePosition(e);
|
|
819
|
+
if (!point) return;
|
|
820
|
+
drawLine(lastPoint, point);
|
|
821
|
+
setLastPoint(point);
|
|
822
|
+
},
|
|
823
|
+
[isDrawing, lastPoint, getRelativePosition, drawLine]
|
|
824
|
+
);
|
|
825
|
+
const stopDrawing = react.useCallback(() => {
|
|
826
|
+
setIsDrawing(false);
|
|
827
|
+
setLastPoint(null);
|
|
828
|
+
}, []);
|
|
829
|
+
const handleSave = react.useCallback(() => {
|
|
830
|
+
if (isEmpty) return;
|
|
831
|
+
const dataUrl = getSignatureDataUrl();
|
|
832
|
+
if (dataUrl && onSignature) {
|
|
833
|
+
onSignature(dataUrl);
|
|
834
|
+
}
|
|
835
|
+
}, [isEmpty, getSignatureDataUrl, onSignature]);
|
|
836
|
+
react.useEffect(() => {
|
|
837
|
+
setupCanvas();
|
|
838
|
+
}, [setupCanvas]);
|
|
839
|
+
const handleMouseDown = react.useCallback(
|
|
840
|
+
(e) => {
|
|
841
|
+
startDrawing(e);
|
|
842
|
+
},
|
|
843
|
+
[startDrawing]
|
|
844
|
+
);
|
|
845
|
+
const handleMouseMove = react.useCallback(
|
|
846
|
+
(e) => {
|
|
847
|
+
draw(e);
|
|
848
|
+
},
|
|
849
|
+
[draw]
|
|
850
|
+
);
|
|
851
|
+
const handleMouseUp = react.useCallback(() => {
|
|
852
|
+
stopDrawing();
|
|
853
|
+
}, [stopDrawing]);
|
|
854
|
+
const handleMouseLeave = react.useCallback(() => {
|
|
855
|
+
stopDrawing();
|
|
856
|
+
}, [stopDrawing]);
|
|
857
|
+
const handleTouchStart = react.useCallback(
|
|
858
|
+
(e) => {
|
|
859
|
+
startDrawing(e);
|
|
860
|
+
},
|
|
861
|
+
[startDrawing]
|
|
862
|
+
);
|
|
863
|
+
const handleTouchMove = react.useCallback(
|
|
864
|
+
(e) => {
|
|
865
|
+
draw(e);
|
|
866
|
+
},
|
|
867
|
+
[draw]
|
|
868
|
+
);
|
|
869
|
+
const handleTouchEnd = react.useCallback(() => {
|
|
870
|
+
stopDrawing();
|
|
871
|
+
}, [stopDrawing]);
|
|
872
|
+
react.useImperativeHandle(
|
|
873
|
+
ref,
|
|
874
|
+
() => ({
|
|
875
|
+
clear,
|
|
876
|
+
getSignatureDataUrl,
|
|
877
|
+
isEmpty: () => isEmpty
|
|
878
|
+
}),
|
|
879
|
+
[clear, getSignatureDataUrl, isEmpty]
|
|
880
|
+
);
|
|
881
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children({
|
|
882
|
+
canvasRef,
|
|
883
|
+
containerRef,
|
|
884
|
+
isEmpty,
|
|
885
|
+
canvasSize,
|
|
886
|
+
handlers: {
|
|
887
|
+
onMouseDown: handleMouseDown,
|
|
888
|
+
onMouseMove: handleMouseMove,
|
|
889
|
+
onMouseUp: handleMouseUp,
|
|
890
|
+
onMouseLeave: handleMouseLeave,
|
|
891
|
+
onTouchStart: handleTouchStart,
|
|
892
|
+
onTouchMove: handleTouchMove,
|
|
893
|
+
onTouchEnd: handleTouchEnd
|
|
894
|
+
},
|
|
895
|
+
actions: {
|
|
896
|
+
clear,
|
|
897
|
+
save: handleSave
|
|
898
|
+
}
|
|
899
|
+
}) });
|
|
900
|
+
}
|
|
901
|
+
);
|
|
902
|
+
SignatureCaptureCore.displayName = "SignatureCaptureCore";
|
|
903
|
+
|
|
904
|
+
exports.PdfViewerCore = PdfViewerCore;
|
|
905
|
+
exports.SignatureCaptureCore = SignatureCaptureCore;
|
|
906
|
+
//# sourceMappingURL=index.js.map
|
|
907
|
+
//# sourceMappingURL=index.js.map
|