@bigbinary/neeto-pdf-frontend 1.0.2 → 1.0.3

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 (64) hide show
  1. package/dist/.ready +1 -1
  2. package/dist/AttachmentCard-Blp45MKz.js +64 -0
  3. package/dist/AttachmentCard-Blp45MKz.js.map +1 -0
  4. package/dist/AttachmentCard-CbDrjY7P.js +67 -0
  5. package/dist/AttachmentCard-CbDrjY7P.js.map +1 -0
  6. package/dist/FilenameUtilities-DFEKeP7n.js +150 -0
  7. package/dist/FilenameUtilities-DFEKeP7n.js.map +1 -0
  8. package/dist/{FilenameUtilities-BRCCinT2.js → FilenameUtilities-Di7TmEIR.js} +9 -184
  9. package/dist/FilenameUtilities-Di7TmEIR.js.map +1 -0
  10. package/dist/FilenameUtilities-SpduImYz.js +139 -0
  11. package/dist/FilenameUtilities-SpduImYz.js.map +1 -0
  12. package/dist/{FilenameUtilities-DHtvZ32y.js → FilenameUtilities-Xttn7r8R.js} +2 -177
  13. package/dist/FilenameUtilities-Xttn7r8R.js.map +1 -0
  14. package/dist/IconBlock-BZvD1k7W.js +17 -0
  15. package/dist/IconBlock-BZvD1k7W.js.map +1 -0
  16. package/dist/IconBlock-Cte1G732.js +15 -0
  17. package/dist/IconBlock-Cte1G732.js.map +1 -0
  18. package/dist/PdfDocumentsPage.js +2 -1
  19. package/dist/PdfDocumentsPage.js.map +1 -1
  20. package/dist/PdfEditorPage.js +3 -146
  21. package/dist/PdfEditorPage.js.map +1 -1
  22. package/dist/cjs/PdfDocumentsPage.js +2 -1
  23. package/dist/cjs/PdfDocumentsPage.js.map +1 -1
  24. package/dist/cjs/PdfEditorPage.js +12 -155
  25. package/dist/cjs/PdfEditorPage.js.map +1 -1
  26. package/dist/cjs/index.js +3 -1
  27. package/dist/cjs/index.js.map +1 -1
  28. package/dist/cjs/v2/PdfAttachmentSelector.js +95 -0
  29. package/dist/cjs/v2/PdfAttachmentSelector.js.map +1 -0
  30. package/dist/cjs/v2/PdfAttachmentsPreview.js +45 -0
  31. package/dist/cjs/v2/PdfAttachmentsPreview.js.map +1 -0
  32. package/dist/cjs/v2/PdfDocumentsPage.js +555 -0
  33. package/dist/cjs/v2/PdfDocumentsPage.js.map +1 -0
  34. package/dist/cjs/v2/PdfEditorPage.js +1920 -0
  35. package/dist/cjs/v2/PdfEditorPage.js.map +1 -0
  36. package/dist/cjs/v2/index.js +67 -0
  37. package/dist/cjs/v2/index.js.map +1 -0
  38. package/dist/constants-DDj0SAA-.js +8 -0
  39. package/dist/constants-DDj0SAA-.js.map +1 -0
  40. package/dist/constants-MHmmvZDo.js +5 -0
  41. package/dist/constants-MHmmvZDo.js.map +1 -0
  42. package/dist/index.js +3 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/pdf_documents-PKt4xiTc.js +181 -0
  45. package/dist/pdf_documents-PKt4xiTc.js.map +1 -0
  46. package/dist/pdf_documents-j2CBlJrR.js +179 -0
  47. package/dist/pdf_documents-j2CBlJrR.js.map +1 -0
  48. package/dist/pdf_mapping_schema-CS6f9Kug.js +149 -0
  49. package/dist/pdf_mapping_schema-CS6f9Kug.js.map +1 -0
  50. package/dist/pdf_mapping_schema-Co4FN4KU.js +147 -0
  51. package/dist/pdf_mapping_schema-Co4FN4KU.js.map +1 -0
  52. package/dist/v2/PdfAttachmentSelector.js +93 -0
  53. package/dist/v2/PdfAttachmentSelector.js.map +1 -0
  54. package/dist/v2/PdfAttachmentsPreview.js +43 -0
  55. package/dist/v2/PdfAttachmentsPreview.js.map +1 -0
  56. package/dist/v2/PdfDocumentsPage.js +553 -0
  57. package/dist/v2/PdfDocumentsPage.js.map +1 -0
  58. package/dist/v2/PdfEditorPage.js +1899 -0
  59. package/dist/v2/PdfEditorPage.js.map +1 -0
  60. package/dist/v2/index.js +58 -0
  61. package/dist/v2/index.js.map +1 -0
  62. package/package.json +13 -1
  63. package/dist/FilenameUtilities-BRCCinT2.js.map +0 -1
  64. package/dist/FilenameUtilities-DHtvZ32y.js.map +0 -1
@@ -0,0 +1,1920 @@
1
+ 'use strict';
2
+
3
+ var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
4
+ var react = require('react');
5
+ var neetoAtoms = require('@bigbinary/neeto-atoms');
6
+ var reactDom = require('react-dom');
7
+ var reactI18next = require('react-i18next');
8
+ var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
9
+ var _regeneratorRuntime = require('@babel/runtime/regenerator');
10
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
11
+ var classNames = require('classnames');
12
+ var neetoCist = require('@bigbinary/neeto-cist');
13
+ var Calendar = require('@bigbinary/neeto-icons/Calendar');
14
+ var Hash = require('@bigbinary/neeto-icons/Hash');
15
+ var TextLines = require('@bigbinary/neeto-icons/TextLines');
16
+ var pdf_mapping_schema = require('../../pdf_mapping_schema-CS6f9Kug.js');
17
+ var jsxRuntime = require('react/jsx-runtime');
18
+ var pdfjsLib = require('pdfjs-dist');
19
+ var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
20
+ var reactUtils = require('@bigbinary/neeto-commons-frontend/v2/react-utils');
21
+ var CenterAlign = require('@bigbinary/neeto-icons/CenterAlign');
22
+ var Delete = require('@bigbinary/neeto-icons/Delete');
23
+ var Folder = require('@bigbinary/neeto-icons/Folder');
24
+ var LeftAlign = require('@bigbinary/neeto-icons/LeftAlign');
25
+ var RightAlign = require('@bigbinary/neeto-icons/RightAlign');
26
+ var Search = require('@bigbinary/neeto-icons/Search');
27
+ var Drag = require('@bigbinary/neeto-icons/Drag');
28
+ var logger = require('js-logger');
29
+ var FilenameUtilities = require('../../FilenameUtilities-DFEKeP7n.js');
30
+ var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
31
+ var ramda = require('ramda');
32
+ var Left = require('@bigbinary/neeto-icons/Left');
33
+ var Right = require('@bigbinary/neeto-icons/Right');
34
+ var _typeof = require('@babel/runtime/helpers/typeof');
35
+ var utils = require('@bigbinary/neeto-commons-frontend/v2/utils');
36
+ var Download = require('@bigbinary/neeto-icons/Download');
37
+ var LeftArrow = require('@bigbinary/neeto-icons/LeftArrow');
38
+ var Minus = require('@bigbinary/neeto-icons/Minus');
39
+ var Plus = require('@bigbinary/neeto-icons/Plus');
40
+ var NavigationHeader = require('@bigbinary/neeto-molecules/v2/NavigationHeader');
41
+ require('@tanstack/react-query');
42
+ require('../../pdf_documents-PKt4xiTc.js');
43
+ require('axios');
44
+
45
+ function _interopNamespaceDefault(e) {
46
+ var n = Object.create(null);
47
+ if (e) {
48
+ Object.keys(e).forEach(function (k) {
49
+ if (k !== 'default') {
50
+ var d = Object.getOwnPropertyDescriptor(e, k);
51
+ Object.defineProperty(n, k, d.get ? d : {
52
+ enumerable: true,
53
+ get: function () { return e[k]; }
54
+ });
55
+ }
56
+ });
57
+ }
58
+ n.default = e;
59
+ return Object.freeze(n);
60
+ }
61
+
62
+ var pdfjsLib__namespace = /*#__PURE__*/_interopNamespaceDefault(pdfjsLib);
63
+
64
+ var mappingDefaults = pdf_mapping_schema.pdfMappingSchema.defaults;
65
+
66
+ // CSS pixels per PDF point (96dpi / 72dpi). `renderScale = CSS_PX_PER_PT * zoom`
67
+ // maps a page's intrinsic point dimensions to on-screen pixels, and font sizes
68
+ // (stored in points) to pixels. Keeping geometry in point-fractions keeps
69
+ // mappings resolution independent.
70
+ var CSS_PX_PER_PT = 96 / 72;
71
+ var ZOOM = {
72
+ MIN: 0.5,
73
+ MAX: 2,
74
+ STEP: 0.1,
75
+ DEFAULT: 1
76
+ };
77
+ var PDF_CANVAS = {
78
+ MAX_DISPLAY_SIZE: 1400,
79
+ MAX_RENDER_SIZE: 8192,
80
+ MAX_RENDER_PIXELS: 16000000
81
+ };
82
+ var EDITOR_MODES = {
83
+ MAP: "map",
84
+ PREVIEW: "preview"
85
+ };
86
+ var PDF_LOAD_INITIAL_STATE = {
87
+ pages: [],
88
+ isLoading: true,
89
+ error: null
90
+ };
91
+ var EMPTY_MAPPINGS = [];
92
+ var FIELD_SOURCES = {
93
+ ANSWER: pdf_mapping_schema.pdfMappingSchema.enums.sources[0],
94
+ SYSTEM: pdf_mapping_schema.pdfMappingSchema.enums.sources[1]
95
+ };
96
+ var DRAG_KINDS = {
97
+ MOVE: "move",
98
+ RESIZE: "resize"
99
+ };
100
+ var ALIGNMENTS = {
101
+ LEFT: pdf_mapping_schema.pdfMappingSchema.enums.alignments[0],
102
+ CENTER: pdf_mapping_schema.pdfMappingSchema.enums.alignments[1],
103
+ RIGHT: pdf_mapping_schema.pdfMappingSchema.enums.alignments[2]
104
+ };
105
+ var FORM_THEME_COLOR = "rgb(var(--neeto-form-answer-color, 0, 128, 104))";
106
+ var FORM_THEME_BACKGROUND = "rgba(var(--neeto-form-answer-color, 0, 128, 104), 0.08)";
107
+ var RESIZE_HANDLES = [{
108
+ key: "top-left",
109
+ x: "left",
110
+ y: "top",
111
+ className: "-left-1.5 -top-1.5 cursor-nwse-resize"
112
+ }, {
113
+ key: "top-right",
114
+ x: "right",
115
+ y: "top",
116
+ className: "-right-1.5 -top-1.5 cursor-nesw-resize"
117
+ }, {
118
+ key: "bottom-left",
119
+ x: "left",
120
+ y: "bottom",
121
+ className: "-left-1.5 -bottom-1.5 cursor-nesw-resize"
122
+ }, {
123
+ key: "bottom-right",
124
+ x: "right",
125
+ y: "bottom",
126
+ className: "-right-1.5 -bottom-1.5 cursor-nwse-resize"
127
+ }];
128
+
129
+ // Curated, PDF/web-safe fonts. The JSON schema also supplies the server-side
130
+ // variants so client/server rendering cannot drift when the list changes.
131
+ var FONTS = pdf_mapping_schema.pdfMappingSchema.fonts.map(function (_ref) {
132
+ var label = _ref.label,
133
+ stack = _ref.stack,
134
+ value = _ref.value;
135
+ return {
136
+ value: value,
137
+ label: label,
138
+ stack: stack
139
+ };
140
+ });
141
+
142
+ // Maps a curated font to pdf-lib StandardFont variant names, indexed by
143
+ // (bold ? 1 : 0) + (italic ? 2 : 0).
144
+ var STANDARD_FONT_VARIANTS = Object.fromEntries(pdf_mapping_schema.pdfMappingSchema.fonts.map(function (_ref2) {
145
+ var clientVariants = _ref2.client_variants,
146
+ value = _ref2.value;
147
+ return [value, clientVariants];
148
+ }));
149
+ var DEFAULT_FONT_SIZE = mappingDefaults.style.font_size;
150
+ var DEFAULT_DISPLAY_FONT_SIZE = DEFAULT_FONT_SIZE * CSS_PX_PER_PT;
151
+ var FONT_SIZE_LIMITS = pdf_mapping_schema.pdfMappingSchema.ranges.font_size;
152
+ var DEFAULT_STYLE = {
153
+ font: mappingDefaults.style.font,
154
+ fontSize: DEFAULT_FONT_SIZE,
155
+ color: mappingDefaults.style.color,
156
+ bold: mappingDefaults.style.bold,
157
+ italic: mappingDefaults.style.italic,
158
+ underline: mappingDefaults.style.underline,
159
+ align: mappingDefaults.style.align
160
+ };
161
+
162
+ // Default placement box as a fraction of the page (top-left origin).
163
+ var DEFAULT_BOX = mappingDefaults.box;
164
+ var MIN_BOX = {
165
+ width: 0.03,
166
+ height: 0.012
167
+ };
168
+ var SYSTEM_FIELD_KEYS = {
169
+ FORM_NAME: "form_name",
170
+ SUBMISSION_ID: "submission_id",
171
+ SUBMISSION_DATE: "submission_date"
172
+ };
173
+
174
+ // System fields are not form questions; they resolve from submission metadata.
175
+ var SYSTEM_FIELDS = [{
176
+ key: SYSTEM_FIELD_KEYS.FORM_NAME,
177
+ labelKey: "neetoPdf.pdfDocuments.editor.systemFields.formName",
178
+ icon: TextLines
179
+ }, {
180
+ key: SYSTEM_FIELD_KEYS.SUBMISSION_ID,
181
+ labelKey: "neetoPdf.pdfDocuments.editor.systemFields.submissionId",
182
+ icon: Hash
183
+ }, {
184
+ key: SYSTEM_FIELD_KEYS.SUBMISSION_DATE,
185
+ labelKey: "neetoPdf.pdfDocuments.editor.systemFields.submissionDate",
186
+ icon: Calendar
187
+ }];
188
+
189
+ var clamp = function clamp(value, min, max) {
190
+ return Math.min(Math.max(value, min), max);
191
+ };
192
+ var getPdfPageDisplayScale = function getPdfPageDisplayScale(_ref) {
193
+ var heightPt = _ref.heightPt,
194
+ rawScale = _ref.rawScale,
195
+ widthPt = _ref.widthPt;
196
+ var maxPageSize = Math.max(widthPt, heightPt);
197
+ if (!maxPageSize) return rawScale;
198
+ var zoom = rawScale / CSS_PX_PER_PT;
199
+ var baseScale = Math.min(CSS_PX_PER_PT, PDF_CANVAS.MAX_DISPLAY_SIZE / maxPageSize);
200
+ return baseScale * zoom;
201
+ };
202
+ var getDefaultFontSizeForScale = function getDefaultFontSizeForScale(scale) {
203
+ if (!scale || Number.isNaN(scale)) return DEFAULT_STYLE.fontSize;
204
+ return clamp(Math.round(DEFAULT_DISPLAY_FONT_SIZE / scale), FONT_SIZE_LIMITS.min, FONT_SIZE_LIMITS.max);
205
+ };
206
+ var getFontStack = function getFontStack(font) {
207
+ var _findBy;
208
+ return ((_findBy = neetoCist.findBy({
209
+ value: font
210
+ }, FONTS)) === null || _findBy === void 0 ? void 0 : _findBy.stack) || FONTS[0].stack;
211
+ };
212
+
213
+ function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
214
+ function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
215
+ var getJustifyContent = function getJustifyContent(align) {
216
+ if (align === "center") return "center";
217
+ if (align === "right") return "flex-end";
218
+ return "flex-start";
219
+ };
220
+ var PlacedField = function PlacedField(_ref) {
221
+ var mapping = _ref.mapping,
222
+ mode = _ref.mode,
223
+ isSelected = _ref.isSelected,
224
+ scale = _ref.scale,
225
+ pageWidthPx = _ref.pageWidthPx,
226
+ pageHeightPx = _ref.pageHeightPx,
227
+ previewValue = _ref.previewValue,
228
+ onSelect = _ref.onSelect,
229
+ onChange = _ref.onChange;
230
+ var dragRef = react.useRef(null);
231
+ var draftPatchRef = react.useRef(null);
232
+ var _useState = react.useState(null),
233
+ _useState2 = _slicedToArray(_useState, 2),
234
+ draftPatch = _useState2[0],
235
+ setDraftPatch = _useState2[1];
236
+ var isPreview = mode === EDITOR_MODES.PREVIEW;
237
+ var displayMapping = draftPatch ? _objectSpread$3(_objectSpread$3({}, mapping), draftPatch) : mapping;
238
+ var style = {
239
+ left: "".concat(displayMapping.x * pageWidthPx, "px"),
240
+ top: "".concat(displayMapping.y * pageHeightPx, "px"),
241
+ width: "".concat(displayMapping.width * pageWidthPx, "px"),
242
+ height: "".concat(displayMapping.height * pageHeightPx, "px")
243
+ };
244
+ var selectedStyle = isSelected ? {
245
+ borderColor: FORM_THEME_COLOR,
246
+ backgroundColor: FORM_THEME_BACKGROUND
247
+ } : {};
248
+ var textStyle = {
249
+ fontFamily: getFontStack(displayMapping.font),
250
+ fontSize: "".concat(displayMapping.fontSize * scale, "px"),
251
+ color: displayMapping.color,
252
+ fontWeight: displayMapping.bold ? 700 : 400,
253
+ fontStyle: displayMapping.italic ? "italic" : "normal",
254
+ textDecoration: displayMapping.underline ? "underline" : "none",
255
+ textAlign: displayMapping.align,
256
+ justifyContent: getJustifyContent(displayMapping.align)
257
+ };
258
+ var getResizePatch = function getResizePatch(_ref2) {
259
+ var drag = _ref2.drag,
260
+ dxFrac = _ref2.dxFrac,
261
+ dyFrac = _ref2.dyFrac;
262
+ var patch = {};
263
+ var originRight = drag.originX + drag.originWidth;
264
+ var originBottom = drag.originY + drag.originHeight;
265
+ if (drag.handle.x === "left") {
266
+ var x = clamp(drag.originX + dxFrac, 0, originRight - MIN_BOX.width);
267
+ patch.x = x;
268
+ patch.width = originRight - x;
269
+ } else {
270
+ patch.width = clamp(drag.originWidth + dxFrac, MIN_BOX.width, 1 - drag.originX);
271
+ }
272
+ if (drag.handle.y === "top") {
273
+ var y = clamp(drag.originY + dyFrac, 0, originBottom - MIN_BOX.height);
274
+ patch.y = y;
275
+ patch.height = originBottom - y;
276
+ } else {
277
+ patch.height = clamp(drag.originHeight + dyFrac, MIN_BOX.height, 1 - drag.originY);
278
+ }
279
+ return patch;
280
+ };
281
+ var handlePointerMove = function handlePointerMove(event) {
282
+ var drag = dragRef.current;
283
+ if (!drag) return;
284
+ var dxFrac = (event.clientX - drag.startX) / pageWidthPx;
285
+ var dyFrac = (event.clientY - drag.startY) / pageHeightPx;
286
+ var patch = drag.kind === DRAG_KINDS.MOVE ? {
287
+ x: clamp(drag.originX + dxFrac, 0, 1 - mapping.width),
288
+ y: clamp(drag.originY + dyFrac, 0, 1 - mapping.height)
289
+ } : getResizePatch({
290
+ drag: drag,
291
+ dxFrac: dxFrac,
292
+ dyFrac: dyFrac
293
+ });
294
+ draftPatchRef.current = patch;
295
+ setDraftPatch(patch);
296
+ };
297
+ var startDrag = function startDrag(event, kind) {
298
+ var handle = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
299
+ if (isPreview) return;
300
+ event.stopPropagation();
301
+ event.preventDefault();
302
+ onSelect(mapping.id);
303
+ event.currentTarget.setPointerCapture(event.pointerId);
304
+ dragRef.current = {
305
+ kind: kind,
306
+ handle: handle,
307
+ startX: event.clientX,
308
+ startY: event.clientY,
309
+ originX: mapping.x,
310
+ originY: mapping.y,
311
+ originWidth: mapping.width,
312
+ originHeight: mapping.height
313
+ };
314
+ draftPatchRef.current = null;
315
+ setDraftPatch(null);
316
+ };
317
+ var endDrag = function endDrag(event) {
318
+ var _event$currentTarget$, _event$currentTarget;
319
+ if (!dragRef.current) return;
320
+ (_event$currentTarget$ = (_event$currentTarget = event.currentTarget).releasePointerCapture) === null || _event$currentTarget$ === void 0 || _event$currentTarget$.call(_event$currentTarget, event.pointerId);
321
+ dragRef.current = null;
322
+ if (draftPatchRef.current) onChange(mapping.id, draftPatchRef.current);
323
+ draftPatchRef.current = null;
324
+ setDraftPatch(null);
325
+ };
326
+ var renderResizeHandle = function renderResizeHandle(handle) {
327
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
328
+ style: {
329
+ backgroundColor: FORM_THEME_COLOR
330
+ },
331
+ className: classNames("rounded-full border-background absolute h-3 w-3 border-2", handle.className),
332
+ onPointerCancel: endDrag,
333
+ onPointerDown: function onPointerDown(event) {
334
+ return startDrag(event, DRAG_KINDS.RESIZE, handle);
335
+ },
336
+ onPointerMove: handlePointerMove,
337
+ onPointerUp: endDrag
338
+ }, handle.key);
339
+ };
340
+ if (isPreview) {
341
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
342
+ style: style,
343
+ className: "pointer-events-none absolute flex items-center",
344
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
345
+ className: "w-full overflow-hidden leading-tight whitespace-pre-wrap",
346
+ style: textStyle,
347
+ children: previewValue
348
+ })
349
+ });
350
+ }
351
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
352
+ style: _objectSpread$3(_objectSpread$3({}, style), selectedStyle),
353
+ className: classNames("rounded-sm absolute flex cursor-move items-center border transition-colors select-none", {
354
+ "z-10": isSelected,
355
+ "border-border bg-opacity-40 bg-background border-dashed": !isSelected
356
+ }),
357
+ onPointerCancel: endDrag,
358
+ onPointerDown: function onPointerDown(event) {
359
+ return startDrag(event, DRAG_KINDS.MOVE);
360
+ },
361
+ onPointerMove: handlePointerMove,
362
+ onPointerUp: endDrag,
363
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
364
+ className: "flex w-full items-center gap-1 overflow-hidden px-1 leading-tight",
365
+ style: textStyle,
366
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
367
+ className: "truncate",
368
+ children: displayMapping.label
369
+ })
370
+ }), isSelected && RESIZE_HANDLES.map(renderResizeHandle)]
371
+ });
372
+ };
373
+
374
+ var getRenderPixelRatio = function getRenderPixelRatio(viewport) {
375
+ var dpr = window.devicePixelRatio || 1;
376
+ var widthRatio = PDF_CANVAS.MAX_RENDER_SIZE / viewport.width;
377
+ var heightRatio = PDF_CANVAS.MAX_RENDER_SIZE / viewport.height;
378
+ var pixelRatio = Math.sqrt(PDF_CANVAS.MAX_RENDER_PIXELS / (viewport.width * viewport.height));
379
+ return Math.min(dpr, widthRatio, heightRatio, pixelRatio);
380
+ };
381
+ var PdfPage = function PdfPage(_ref) {
382
+ var pageDescriptor = _ref.pageDescriptor,
383
+ rawScale = _ref.scale,
384
+ mappings = _ref.mappings,
385
+ selectedId = _ref.selectedId,
386
+ mode = _ref.mode,
387
+ resolveValue = _ref.resolveValue,
388
+ onSelect = _ref.onSelect,
389
+ onChange = _ref.onChange,
390
+ onDropField = _ref.onDropField,
391
+ onScaleChange = _ref.onScaleChange;
392
+ var page = pageDescriptor.page,
393
+ pageNumber = pageDescriptor.pageNumber,
394
+ widthPt = pageDescriptor.widthPt,
395
+ heightPt = pageDescriptor.heightPt;
396
+ var canvasRef = react.useRef(null);
397
+ var overlayRef = react.useRef(null);
398
+ var scale = react.useMemo(function () {
399
+ return getPdfPageDisplayScale({
400
+ heightPt: heightPt,
401
+ rawScale: rawScale,
402
+ widthPt: widthPt
403
+ });
404
+ }, [heightPt, rawScale, widthPt]);
405
+ var defaultMappingScale = react.useMemo(function () {
406
+ return getPdfPageDisplayScale({
407
+ heightPt: heightPt,
408
+ rawScale: CSS_PX_PER_PT,
409
+ widthPt: widthPt
410
+ });
411
+ }, [heightPt, widthPt]);
412
+ var viewport = react.useMemo(function () {
413
+ return page.getViewport({
414
+ scale: scale
415
+ });
416
+ }, [page, scale]);
417
+ var pageWidthPx = viewport.width;
418
+ var pageHeightPx = viewport.height;
419
+ react.useEffect(function () {
420
+ onScaleChange(pageNumber, defaultMappingScale);
421
+ }, [defaultMappingScale, onScaleChange, pageNumber]);
422
+ react.useEffect(function () {
423
+ var canvas = canvasRef.current;
424
+ if (!canvas) return undefined;
425
+ var renderPixelRatio = getRenderPixelRatio(viewport);
426
+ canvas.width = Math.floor(viewport.width * renderPixelRatio);
427
+ canvas.height = Math.floor(viewport.height * renderPixelRatio);
428
+ canvas.style.width = "".concat(viewport.width, "px");
429
+ canvas.style.height = "".concat(viewport.height, "px");
430
+ var renderTask = page.render({
431
+ canvasContext: canvas.getContext("2d"),
432
+ viewport: viewport,
433
+ transform: renderPixelRatio !== 1 ? [renderPixelRatio, 0, 0, renderPixelRatio, 0, 0] : undefined
434
+ });
435
+ var render = /*#__PURE__*/function () {
436
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
437
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
438
+ while (1) switch (_context.prev = _context.next) {
439
+ case 0:
440
+ _context.prev = 0;
441
+ _context.next = 3;
442
+ return renderTask.promise;
443
+ case 3:
444
+ _context.next = 7;
445
+ break;
446
+ case 5:
447
+ _context.prev = 5;
448
+ _context.t0 = _context["catch"](0);
449
+ case 7:
450
+ case "end":
451
+ return _context.stop();
452
+ }
453
+ }, _callee, null, [[0, 5]]);
454
+ }));
455
+ return function render() {
456
+ return _ref2.apply(this, arguments);
457
+ };
458
+ }();
459
+ render();
460
+ return function () {
461
+ return renderTask.cancel();
462
+ };
463
+ }, [page, scale, viewport]);
464
+ var handleDrop = function handleDrop(event) {
465
+ event.preventDefault();
466
+ var rect = overlayRef.current.getBoundingClientRect();
467
+ var xFrac = clamp((event.clientX - rect.left) / rect.width, 0, 1);
468
+ var yFrac = clamp((event.clientY - rect.top) / rect.height, 0, 1);
469
+ onDropField({
470
+ pageNumber: pageNumber,
471
+ scale: defaultMappingScale,
472
+ x: xFrac,
473
+ y: yFrac
474
+ });
475
+ };
476
+ var handleDragOver = function handleDragOver(event) {
477
+ event.preventDefault();
478
+ event.dataTransfer.dropEffect = "copy";
479
+ };
480
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
481
+ className: "shadow-md bg-background relative",
482
+ style: {
483
+ width: "".concat(pageWidthPx, "px"),
484
+ height: "".concat(pageHeightPx, "px")
485
+ },
486
+ children: [/*#__PURE__*/jsxRuntime.jsx("canvas", {
487
+ ref: canvasRef
488
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
489
+ className: "absolute inset-0",
490
+ ref: overlayRef,
491
+ onDragOver: handleDragOver,
492
+ onDrop: handleDrop,
493
+ onPointerDown: function onPointerDown() {
494
+ return onSelect(null);
495
+ },
496
+ children: mappings.map(function (mapping) {
497
+ return /*#__PURE__*/react.createElement(PlacedField, {
498
+ mapping: mapping,
499
+ mode: mode,
500
+ onChange: onChange,
501
+ onSelect: onSelect,
502
+ pageHeightPx: pageHeightPx,
503
+ pageWidthPx: pageWidthPx,
504
+ scale: scale,
505
+ isSelected: mapping.id === selectedId,
506
+ key: mapping.id,
507
+ previewValue: mode === EDITOR_MODES.PREVIEW ? resolveValue(mapping) : null
508
+ });
509
+ })
510
+ })]
511
+ });
512
+ };
513
+
514
+ // The worker is vendored into public/ (see the sync:pdf-worker script) so it is
515
+ // served as a static asset with a JS MIME type. pdf.js always loads it as a
516
+ // module worker. Its version must stay in sync with pdfjs-dist.
517
+ pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.js";
518
+
519
+ // Loads a PDF via pdf.js and returns one descriptor per page:
520
+ // { pageNumber, page (PDFPageProxy), widthPt, heightPt }. Dimensions are in PDF
521
+ // points (viewport scale 1), which the canvas scales by CSS_PX_PER_PT * zoom.
522
+ var usePdfDocument = function usePdfDocument(url) {
523
+ var _useState = react.useState(PDF_LOAD_INITIAL_STATE),
524
+ _useState2 = _slicedToArray(_useState, 2),
525
+ state = _useState2[0],
526
+ setState = _useState2[1];
527
+ react.useEffect(function () {
528
+ if (!url) return undefined;
529
+ var isCancelled = false;
530
+ var pdf;
531
+ setState(PDF_LOAD_INITIAL_STATE);
532
+ var loadingTask = pdfjsLib__namespace.getDocument({
533
+ url: url
534
+ });
535
+ var loadPages = /*#__PURE__*/function () {
536
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
537
+ var pages, pageNumber, page, viewport;
538
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
539
+ while (1) switch (_context.prev = _context.next) {
540
+ case 0:
541
+ _context.prev = 0;
542
+ _context.next = 3;
543
+ return loadingTask.promise;
544
+ case 3:
545
+ pdf = _context.sent;
546
+ pages = [];
547
+ pageNumber = 1;
548
+ case 6:
549
+ if (!(pageNumber <= pdf.numPages)) {
550
+ _context.next = 15;
551
+ break;
552
+ }
553
+ _context.next = 9;
554
+ return pdf.getPage(pageNumber);
555
+ case 9:
556
+ page = _context.sent;
557
+ viewport = page.getViewport({
558
+ scale: 1
559
+ });
560
+ pages.push({
561
+ pageNumber: pageNumber,
562
+ page: page,
563
+ widthPt: viewport.width,
564
+ heightPt: viewport.height
565
+ });
566
+ case 12:
567
+ pageNumber += 1;
568
+ _context.next = 6;
569
+ break;
570
+ case 15:
571
+ if (!isCancelled) setState({
572
+ pages: pages,
573
+ isLoading: false,
574
+ error: null
575
+ });
576
+ _context.next = 21;
577
+ break;
578
+ case 18:
579
+ _context.prev = 18;
580
+ _context.t0 = _context["catch"](0);
581
+ if (!isCancelled) setState({
582
+ pages: [],
583
+ isLoading: false,
584
+ error: _context.t0
585
+ });
586
+ case 21:
587
+ case "end":
588
+ return _context.stop();
589
+ }
590
+ }, _callee, null, [[0, 18]]);
591
+ }));
592
+ return function loadPages() {
593
+ return _ref.apply(this, arguments);
594
+ };
595
+ }();
596
+ loadPages();
597
+ return function () {
598
+ var _loadingTask$destroy, _pdf, _pdf$destroy;
599
+ isCancelled = true;
600
+ (_loadingTask$destroy = loadingTask.destroy) === null || _loadingTask$destroy === void 0 || _loadingTask$destroy.call(loadingTask);
601
+ (_pdf = pdf) === null || _pdf === void 0 || (_pdf$destroy = _pdf.destroy) === null || _pdf$destroy === void 0 || _pdf$destroy.call(_pdf);
602
+ };
603
+ }, [url]);
604
+ return state;
605
+ };
606
+
607
+ var Canvas = function Canvas(_ref) {
608
+ var templateUrl = _ref.templateUrl,
609
+ zoom = _ref.zoom,
610
+ mappings = _ref.mappings,
611
+ selectedId = _ref.selectedId,
612
+ mode = _ref.mode,
613
+ resolveValue = _ref.resolveValue,
614
+ onSelect = _ref.onSelect,
615
+ onChange = _ref.onChange,
616
+ onDropField = _ref.onDropField,
617
+ onPageScaleChange = _ref.onPageScaleChange;
618
+ var _useTranslation = reactI18next.useTranslation(),
619
+ t = _useTranslation.t;
620
+ var _usePdfDocument = usePdfDocument(templateUrl),
621
+ pages = _usePdfDocument.pages,
622
+ isLoading = _usePdfDocument.isLoading,
623
+ error = _usePdfDocument.error;
624
+ var scale = CSS_PX_PER_PT * zoom;
625
+ var mappingsByPage = react.useMemo(function () {
626
+ return mappings.reduce(function (groupedMappings, mapping) {
627
+ var pageMappings = groupedMappings.get(mapping.page) || [];
628
+ pageMappings.push(mapping);
629
+ groupedMappings.set(mapping.page, pageMappings);
630
+ return groupedMappings;
631
+ }, new Map());
632
+ }, [mappings]);
633
+ if (isLoading) {
634
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
635
+ className: "flex h-full w-full items-center justify-center",
636
+ children: /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Spinner, {})
637
+ });
638
+ }
639
+ if (error || !templateUrl) {
640
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
641
+ className: "flex h-full w-full items-center justify-center p-8",
642
+ children: /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
643
+ className: "text-muted-foreground",
644
+ variant: "body2",
645
+ children: t("neetoPdf.pdfDocuments.editor.renderError")
646
+ })
647
+ });
648
+ }
649
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
650
+ className: "bg-muted absolute inset-0 overflow-auto",
651
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
652
+ className: "flex min-h-full min-w-full w-max flex-col items-center gap-6 p-8",
653
+ children: pages.map(function (pageDescriptor) {
654
+ return /*#__PURE__*/react.createElement(PdfPage, {
655
+ mode: mode,
656
+ onChange: onChange,
657
+ onDropField: onDropField,
658
+ onSelect: onSelect,
659
+ pageDescriptor: pageDescriptor,
660
+ resolveValue: resolveValue,
661
+ scale: scale,
662
+ selectedId: selectedId,
663
+ key: pageDescriptor.pageNumber,
664
+ mappings: mappingsByPage.get(pageDescriptor.pageNumber) || EMPTY_MAPPINGS,
665
+ onScaleChange: onPageScaleChange
666
+ });
667
+ })
668
+ })
669
+ });
670
+ };
671
+
672
+ var _excluded = ["isActive", "onClick", "className", "children"];
673
+ function ownKeys$2(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
674
+ function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$2(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$2(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
675
+ var ToggleButton = function ToggleButton(_ref) {
676
+ var isActive = _ref.isActive,
677
+ onClick = _ref.onClick,
678
+ className = _ref.className,
679
+ children = _ref.children,
680
+ rest = _objectWithoutProperties(_ref, _excluded);
681
+ return /*#__PURE__*/jsxRuntime.jsx("button", _objectSpread$2(_objectSpread$2({
682
+ onClick: onClick,
683
+ type: "button",
684
+ className: classNames("border-border flex h-8 items-center justify-center border text-sm first:rounded-l-md last:rounded-r-md", className, {
685
+ "bg-foreground text-background": isActive,
686
+ "bg-background text-foreground hover:bg-muted": !isActive
687
+ })
688
+ }, rest), {}, {
689
+ children: children
690
+ }));
691
+ };
692
+ var EmptyState = reactUtils.withT(function (_ref2) {
693
+ var t = _ref2.t;
694
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
695
+ className: "flex h-full flex-col items-center justify-center gap-2 p-8 text-center",
696
+ children: [/*#__PURE__*/jsxRuntime.jsx(Folder, {
697
+ className: "text-muted-foreground",
698
+ size: 32
699
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
700
+ variant: "body2",
701
+ weight: "medium",
702
+ children: t("neetoPdf.pdfDocuments.editor.field.emptyTitle")
703
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
704
+ className: "text-muted-foreground",
705
+ variant: "body3",
706
+ children: t("neetoPdf.pdfDocuments.editor.field.emptyDescription")
707
+ })]
708
+ });
709
+ });
710
+ var renderFontOptionLabel = function renderFontOptionLabel(_ref3) {
711
+ var label = _ref3.label,
712
+ stack = _ref3.stack;
713
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
714
+ style: {
715
+ fontFamily: stack
716
+ },
717
+ children: label
718
+ });
719
+ };
720
+ var sanitizeFontSize = function sanitizeFontSize(value) {
721
+ var fontSize = Number(value);
722
+ if (Number.isNaN(fontSize)) return FONT_SIZE_LIMITS.min;
723
+ return Math.min(Math.max(fontSize, FONT_SIZE_LIMITS.min), FONT_SIZE_LIMITS.max);
724
+ };
725
+ var FieldPanel = reactUtils.withT(function (_ref4) {
726
+ var t = _ref4.t,
727
+ mapping = _ref4.mapping,
728
+ _onChange = _ref4.onChange,
729
+ onRemove = _ref4.onRemove;
730
+ return mapping ? /*#__PURE__*/jsxRuntime.jsxs("div", {
731
+ className: "border-border bg-background flex h-full w-72 shrink-0 flex-col overflow-y-auto border-l p-4",
732
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
733
+ className: "mb-4 flex place-content-between items-center gap-2",
734
+ children: /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
735
+ className: "truncate",
736
+ "data-testid": "field-header",
737
+ variant: "h3",
738
+ children: mapping.label
739
+ })
740
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
741
+ className: "grow space-y-5",
742
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
743
+ className: "space-y-1",
744
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
745
+ className: "text-foreground",
746
+ variant: "body3",
747
+ children: t("neetoPdf.pdfDocuments.editor.field.font")
748
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Select, {
749
+ formatOptionLabel: renderFontOptionLabel,
750
+ isSearchable: false,
751
+ options: FONTS,
752
+ size: "small",
753
+ value: mapping.font,
754
+ onChange: function onChange(font) {
755
+ return _onChange(mapping.id, {
756
+ font: font
757
+ });
758
+ }
759
+ })]
760
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
761
+ className: "flex gap-4",
762
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
763
+ className: "min-w-0 flex-1 space-y-1",
764
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
765
+ className: "text-foreground",
766
+ variant: "body3",
767
+ children: t("neetoPdf.pdfDocuments.editor.field.size")
768
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Input, {
769
+ max: FONT_SIZE_LIMITS.max,
770
+ min: FONT_SIZE_LIMITS.min,
771
+ size: "small",
772
+ type: "number",
773
+ value: mapping.fontSize,
774
+ onChange: function onChange(event) {
775
+ return _onChange(mapping.id, {
776
+ fontSize: sanitizeFontSize(event.target.value)
777
+ });
778
+ }
779
+ })]
780
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
781
+ className: "space-y-1",
782
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
783
+ className: "text-foreground",
784
+ variant: "body3",
785
+ children: t("neetoPdf.pdfDocuments.editor.field.format")
786
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
787
+ className: "flex",
788
+ children: [/*#__PURE__*/jsxRuntime.jsx(ToggleButton, {
789
+ "aria-label": "bold",
790
+ className: "w-9",
791
+ isActive: mapping.bold,
792
+ onClick: function onClick() {
793
+ return _onChange(mapping.id, {
794
+ bold: !mapping.bold
795
+ });
796
+ },
797
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
798
+ className: "font-bold",
799
+ children: "B"
800
+ })
801
+ }), /*#__PURE__*/jsxRuntime.jsx(ToggleButton, {
802
+ "aria-label": "italic",
803
+ className: "w-9",
804
+ isActive: mapping.italic,
805
+ onClick: function onClick() {
806
+ return _onChange(mapping.id, {
807
+ italic: !mapping.italic
808
+ });
809
+ },
810
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
811
+ className: "italic",
812
+ children: "I"
813
+ })
814
+ }), /*#__PURE__*/jsxRuntime.jsx(ToggleButton, {
815
+ "aria-label": "underline",
816
+ className: "w-9",
817
+ isActive: mapping.underline,
818
+ onClick: function onClick() {
819
+ return _onChange(mapping.id, {
820
+ underline: !mapping.underline
821
+ });
822
+ },
823
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
824
+ className: "underline",
825
+ children: "U"
826
+ })
827
+ })]
828
+ })]
829
+ })]
830
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
831
+ className: "space-y-1",
832
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
833
+ className: "text-foreground",
834
+ variant: "body3",
835
+ children: t("neetoPdf.pdfDocuments.editor.field.fontColor")
836
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.ColorPicker, {
837
+ showHexValue: true,
838
+ color: mapping.color,
839
+ size: "small",
840
+ onChange: function onChange(_ref5) {
841
+ var hex = _ref5.hex;
842
+ return _onChange(mapping.id, {
843
+ color: hex
844
+ });
845
+ }
846
+ })]
847
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
848
+ className: "space-y-1",
849
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
850
+ className: "text-foreground",
851
+ variant: "body3",
852
+ children: t("neetoPdf.pdfDocuments.editor.field.alignment")
853
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
854
+ className: "flex w-full",
855
+ children: [/*#__PURE__*/jsxRuntime.jsx(ToggleButton, {
856
+ "aria-label": "align-left",
857
+ className: "flex-1",
858
+ isActive: mapping.align === ALIGNMENTS.LEFT,
859
+ onClick: function onClick() {
860
+ return _onChange(mapping.id, {
861
+ align: ALIGNMENTS.LEFT
862
+ });
863
+ },
864
+ children: /*#__PURE__*/jsxRuntime.jsx(LeftAlign, {
865
+ size: 16
866
+ })
867
+ }), /*#__PURE__*/jsxRuntime.jsx(ToggleButton, {
868
+ "aria-label": "align-center",
869
+ className: "flex-1",
870
+ isActive: mapping.align === ALIGNMENTS.CENTER,
871
+ onClick: function onClick() {
872
+ return _onChange(mapping.id, {
873
+ align: ALIGNMENTS.CENTER
874
+ });
875
+ },
876
+ children: /*#__PURE__*/jsxRuntime.jsx(CenterAlign, {
877
+ size: 16
878
+ })
879
+ }), /*#__PURE__*/jsxRuntime.jsx(ToggleButton, {
880
+ "aria-label": "align-right",
881
+ className: "flex-1",
882
+ isActive: mapping.align === ALIGNMENTS.RIGHT,
883
+ onClick: function onClick() {
884
+ return _onChange(mapping.id, {
885
+ align: ALIGNMENTS.RIGHT
886
+ });
887
+ },
888
+ children: /*#__PURE__*/jsxRuntime.jsx(RightAlign, {
889
+ size: 16
890
+ })
891
+ })]
892
+ })]
893
+ })]
894
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
895
+ fullWidth: true,
896
+ className: "mt-4",
897
+ icon: Delete,
898
+ label: t("neetoPdf.pdfDocuments.editor.field.remove"),
899
+ variant: "destructive",
900
+ onClick: function onClick() {
901
+ return onRemove(mapping.id);
902
+ }
903
+ })]
904
+ }) : /*#__PURE__*/jsxRuntime.jsx("div", {
905
+ className: "border-border bg-background flex h-full w-72 shrink-0 flex-col border-l",
906
+ children: /*#__PURE__*/jsxRuntime.jsx(EmptyState, {})
907
+ });
908
+ });
909
+
910
+ var FieldCard = function FieldCard(_ref) {
911
+ var field = _ref.field,
912
+ onPlace = _ref.onPlace,
913
+ onDragStart = _ref.onDragStart,
914
+ onDragEnd = _ref.onDragEnd;
915
+ var Icon = field.icon;
916
+ var handleDragStart = function handleDragStart(event) {
917
+ event.dataTransfer.effectAllowed = "copy";
918
+ event.dataTransfer.setData("text/plain", field.key);
919
+ onDragStart(field);
920
+ };
921
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
922
+ onDragEnd: onDragEnd,
923
+ draggable: true,
924
+ className: "border-border bg-background hover:bg-muted rounded-lg relative mb-2 flex h-10 cursor-pointer items-center gap-2 border p-3 transition-all duration-300 ease-in-out",
925
+ "data-testid": "add-".concat(field.key, "-field"),
926
+ onClick: function onClick() {
927
+ return onPlace(field);
928
+ },
929
+ onDragStart: handleDragStart,
930
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
931
+ className: "absolute end-full top-1/2 me-0.5 flex-shrink-0 -translate-y-1/2 cursor-grab",
932
+ "data-testid": "drag-handle",
933
+ children: /*#__PURE__*/jsxRuntime.jsx(Drag, {
934
+ className: "text-muted-foreground hover:text-muted-foreground transition-all duration-300 ease-in-out",
935
+ size: 16
936
+ })
937
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
938
+ className: "flex flex-grow items-center gap-2 overflow-hidden",
939
+ children: [Icon && /*#__PURE__*/jsxRuntime.jsx("div", {
940
+ className: "flex-shrink-0",
941
+ children: /*#__PURE__*/jsxRuntime.jsx(Icon, {})
942
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
943
+ className: "truncate leading-4",
944
+ variant: "body2",
945
+ children: field.label
946
+ })]
947
+ })]
948
+ });
949
+ };
950
+
951
+ var Section = function Section(_ref) {
952
+ var title = _ref.title,
953
+ children = _ref.children;
954
+ if (!(children !== null && children !== void 0 && children.length)) return null;
955
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
956
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
957
+ className: "mt-1 mb-3",
958
+ variant: "h3",
959
+ children: title
960
+ }), children]
961
+ });
962
+ };
963
+ var FieldsPanel = function FieldsPanel(_ref2) {
964
+ var answerFields = _ref2.answerFields,
965
+ systemFields = _ref2.systemFields,
966
+ onPlace = _ref2.onPlace,
967
+ onDragStartField = _ref2.onDragStartField,
968
+ onDragEndField = _ref2.onDragEndField;
969
+ var _useTranslation = reactI18next.useTranslation(),
970
+ t = _useTranslation.t;
971
+ var _useState = react.useState(""),
972
+ _useState2 = _slicedToArray(_useState, 2),
973
+ searchTerm = _useState2[0],
974
+ setSearchTerm = _useState2[1];
975
+ var query = searchTerm.trim().toLowerCase();
976
+ var matches = function matches(field) {
977
+ return field.label.toLowerCase().includes(query);
978
+ };
979
+ var filteredAnswers = query ? answerFields.filter(matches) : answerFields;
980
+ var filteredSystem = query ? systemFields.filter(matches) : systemFields;
981
+ var renderField = function renderField(field) {
982
+ return /*#__PURE__*/react.createElement(FieldCard, {
983
+ field: field,
984
+ onPlace: onPlace,
985
+ key: "".concat(field.source, "-").concat(field.key),
986
+ onDragEnd: onDragEndField,
987
+ onDragStart: onDragStartField
988
+ });
989
+ };
990
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
991
+ className: "border-border bg-muted flex h-full w-[360px] shrink-0 flex-col border-r",
992
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
993
+ className: "p-6 pb-1",
994
+ children: /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
995
+ lineHeight: "normal",
996
+ variant: "h3",
997
+ weight: "semibold",
998
+ children: t("neetoPdf.pdfDocuments.editor.addNewElement")
999
+ })
1000
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1001
+ className: "mb-1 px-6",
1002
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
1003
+ className: "mb-3",
1004
+ variant: "body3",
1005
+ children: t("neetoPdf.pdfDocuments.editor.addNewElementDescription")
1006
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Input, {
1007
+ autoFocus: true,
1008
+ "data-testid": "elements-panel-search-field",
1009
+ placeholder: t("neetoPdf.pdfDocuments.editor.searchElements"),
1010
+ prefix: /*#__PURE__*/jsxRuntime.jsx(Search, {}),
1011
+ type: "search",
1012
+ value: searchTerm,
1013
+ onChange: function onChange(event) {
1014
+ return setSearchTerm(event.target.value);
1015
+ }
1016
+ })]
1017
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1018
+ className: "grow overflow-y-auto px-6 pb-2",
1019
+ "data-testid": "elements-container",
1020
+ children: [/*#__PURE__*/jsxRuntime.jsx(Section, {
1021
+ title: t("neetoPdf.pdfDocuments.editor.answers"),
1022
+ children: filteredAnswers.map(renderField)
1023
+ }), /*#__PURE__*/jsxRuntime.jsx(Section, {
1024
+ title: t("neetoPdf.pdfDocuments.editor.system"),
1025
+ children: filteredSystem.map(renderField)
1026
+ }), filteredAnswers.length === 0 && filteredSystem.length === 0 ? /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
1027
+ className: "text-foreground text-md flex h-full items-center justify-center",
1028
+ weight: "bold",
1029
+ children: t("neetoPdf.pdfDocuments.editor.noFields")
1030
+ }) : null]
1031
+ })]
1032
+ });
1033
+ };
1034
+
1035
+ // pdf-lib StandardFonts only support WinAnsi encoding and single-line text, so
1036
+ // collapse whitespace and drop characters they cannot encode.
1037
+ var sanitizeForPdf = function sanitizeForPdf(text) {
1038
+ return text.replace(/\s+/g, " ").trim().replace(/[^\x20-\x7E\xA0-\xFF]/g, "").trim();
1039
+ };
1040
+ var hexToRgbComponents = function hexToRgbComponents(hex) {
1041
+ var value = (hex || DEFAULT_STYLE.color).replace("#", "");
1042
+ var full = value.length === 3 ? value.split("").map(function (_char) {
1043
+ return _char + _char;
1044
+ }).join("") : value;
1045
+ var _int = parseInt(full, 16);
1046
+ return {
1047
+ r: (_int >> 16 & 255) / 255,
1048
+ g: (_int >> 8 & 255) / 255,
1049
+ b: (_int & 255) / 255
1050
+ };
1051
+ };
1052
+ var standardFontName = function standardFontName(font, bold, italic) {
1053
+ var variants = STANDARD_FONT_VARIANTS[font] || STANDARD_FONT_VARIANTS.Helvetica;
1054
+ return variants[(bold ? 1 : 0) + (italic ? 2 : 0)];
1055
+ };
1056
+ var triggerBlobDownload = function triggerBlobDownload(bytes, fileName) {
1057
+ var blob = new Blob([bytes], {
1058
+ type: "application/pdf"
1059
+ });
1060
+ var url = URL.createObjectURL(blob);
1061
+ var link = window.document.createElement("a");
1062
+ link.href = url;
1063
+ link.download = fileName;
1064
+ window.document.body.appendChild(link);
1065
+ link.click();
1066
+ link.remove();
1067
+ URL.revokeObjectURL(url);
1068
+ };
1069
+
1070
+ // Stamp the resolved values for one submission onto the template PDF (client
1071
+ // side, via pdf-lib) and trigger a browser download. pdf-lib is imported lazily
1072
+ // so it only loads on the first download.
1073
+ var downloadFilledPdf = /*#__PURE__*/function () {
1074
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(_ref) {
1075
+ var templateUrl, mappings, valueFor, fileName, pdfLibModule, PDFDocument, StandardFonts, rgb, response, bytes, pdfDoc, pages, fontNames, embeddedFonts;
1076
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
1077
+ while (1) switch (_context2.prev = _context2.next) {
1078
+ case 0:
1079
+ templateUrl = _ref.templateUrl, mappings = _ref.mappings, valueFor = _ref.valueFor, fileName = _ref.fileName;
1080
+ _context2.next = 3;
1081
+ return import('pdf-lib');
1082
+ case 3:
1083
+ pdfLibModule = _context2.sent;
1084
+ PDFDocument = pdfLibModule.PDFDocument, StandardFonts = pdfLibModule.StandardFonts, rgb = pdfLibModule.rgb;
1085
+ _context2.next = 7;
1086
+ return fetch(templateUrl);
1087
+ case 7:
1088
+ response = _context2.sent;
1089
+ if (response.ok) {
1090
+ _context2.next = 10;
1091
+ break;
1092
+ }
1093
+ throw new Error("Failed to fetch template PDF (".concat(response.status, ")"));
1094
+ case 10:
1095
+ _context2.next = 12;
1096
+ return response.arrayBuffer();
1097
+ case 12:
1098
+ bytes = _context2.sent;
1099
+ _context2.next = 15;
1100
+ return PDFDocument.load(bytes, {
1101
+ ignoreEncryption: true
1102
+ });
1103
+ case 15:
1104
+ pdfDoc = _context2.sent;
1105
+ pages = pdfDoc.getPages();
1106
+ fontNames = _toConsumableArray(new Set(mappings.map(function (mapping) {
1107
+ return standardFontName(mapping.font, mapping.bold, mapping.italic);
1108
+ })));
1109
+ _context2.t0 = Object;
1110
+ _context2.next = 21;
1111
+ return Promise.all(fontNames.map(/*#__PURE__*/function () {
1112
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(name) {
1113
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
1114
+ while (1) switch (_context.prev = _context.next) {
1115
+ case 0:
1116
+ _context.t0 = name;
1117
+ _context.next = 3;
1118
+ return pdfDoc.embedFont(StandardFonts[name]);
1119
+ case 3:
1120
+ _context.t1 = _context.sent;
1121
+ return _context.abrupt("return", [_context.t0, _context.t1]);
1122
+ case 5:
1123
+ case "end":
1124
+ return _context.stop();
1125
+ }
1126
+ }, _callee);
1127
+ }));
1128
+ return function (_x2) {
1129
+ return _ref3.apply(this, arguments);
1130
+ };
1131
+ }()));
1132
+ case 21:
1133
+ _context2.t1 = _context2.sent;
1134
+ embeddedFonts = _context2.t0.fromEntries.call(_context2.t0, _context2.t1);
1135
+ mappings.forEach(function (mapping) {
1136
+ var page = pages[mapping.page - 1];
1137
+ if (!page) return;
1138
+ var text = sanitizeForPdf(valueFor(mapping) || "");
1139
+ if (!text) return;
1140
+ var _page$getSize = page.getSize(),
1141
+ pageWidth = _page$getSize.width,
1142
+ pageHeight = _page$getSize.height;
1143
+ var font = embeddedFonts[standardFontName(mapping.font, mapping.bold, mapping.italic)];
1144
+ var size = mapping.fontSize;
1145
+ var _hexToRgbComponents = hexToRgbComponents(mapping.color),
1146
+ r = _hexToRgbComponents.r,
1147
+ g = _hexToRgbComponents.g,
1148
+ b = _hexToRgbComponents.b;
1149
+ var color = rgb(r, g, b);
1150
+ var boxLeft = mapping.x * pageWidth;
1151
+ var boxWidth = mapping.width * pageWidth;
1152
+ var textWidth = font.widthOfTextAtSize(text, size);
1153
+ var x = boxLeft;
1154
+ if (mapping.align === "center") x = boxLeft + (boxWidth - textWidth) / 2;else if (mapping.align === "right") x = boxLeft + boxWidth - textWidth;
1155
+ var y = pageHeight - mapping.y * pageHeight - size;
1156
+ page.drawText(text, {
1157
+ x: x,
1158
+ y: y,
1159
+ size: size,
1160
+ font: font,
1161
+ color: color
1162
+ });
1163
+ if (mapping.underline) {
1164
+ var lineY = y - size * 0.1;
1165
+ page.drawLine({
1166
+ start: {
1167
+ x: x,
1168
+ y: lineY
1169
+ },
1170
+ end: {
1171
+ x: x + textWidth,
1172
+ y: lineY
1173
+ },
1174
+ thickness: Math.max(0.5, size * 0.06),
1175
+ color: color
1176
+ });
1177
+ }
1178
+ });
1179
+ _context2.t2 = triggerBlobDownload;
1180
+ _context2.next = 27;
1181
+ return pdfDoc.save();
1182
+ case 27:
1183
+ _context2.t3 = _context2.sent;
1184
+ _context2.t4 = fileName;
1185
+ (0, _context2.t2)(_context2.t3, _context2.t4);
1186
+ case 30:
1187
+ case "end":
1188
+ return _context2.stop();
1189
+ }
1190
+ }, _callee2);
1191
+ }));
1192
+ return function downloadFilledPdf(_x) {
1193
+ return _ref2.apply(this, arguments);
1194
+ };
1195
+ }();
1196
+
1197
+ var usePdfDownload = function usePdfDownload(_ref) {
1198
+ var mappings = _ref.mappings,
1199
+ pdfDocument = _ref.pdfDocument,
1200
+ previewRecord = _ref.previewRecord,
1201
+ resolveValue = _ref.resolveValue,
1202
+ t = _ref.t;
1203
+ var _useState = react.useState(false),
1204
+ _useState2 = _slicedToArray(_useState, 2),
1205
+ isDownloading = _useState2[0],
1206
+ setIsDownloading = _useState2[1];
1207
+ var downloadPdf = /*#__PURE__*/function () {
1208
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
1209
+ var _pdfDocument$template;
1210
+ var templateUrl;
1211
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
1212
+ while (1) switch (_context.prev = _context.next) {
1213
+ case 0:
1214
+ templateUrl = pdfDocument === null || pdfDocument === void 0 || (_pdfDocument$template = pdfDocument.templateFile) === null || _pdfDocument$template === void 0 ? void 0 : _pdfDocument$template.url;
1215
+ if (!(!templateUrl || !previewRecord)) {
1216
+ _context.next = 3;
1217
+ break;
1218
+ }
1219
+ return _context.abrupt("return");
1220
+ case 3:
1221
+ setIsDownloading(true);
1222
+ _context.prev = 4;
1223
+ _context.next = 7;
1224
+ return downloadFilledPdf({
1225
+ templateUrl: templateUrl,
1226
+ mappings: mappings,
1227
+ valueFor: resolveValue,
1228
+ fileName: FilenameUtilities.buildOutputFilename(pdfDocument, previewRecord)
1229
+ });
1230
+ case 7:
1231
+ _context.next = 13;
1232
+ break;
1233
+ case 9:
1234
+ _context.prev = 9;
1235
+ _context.t0 = _context["catch"](4);
1236
+ logger.error(_context.t0);
1237
+ neetoAtoms.Toastr.error(t("neetoPdf.pdfDocuments.editor.downloadError"));
1238
+ case 13:
1239
+ _context.prev = 13;
1240
+ setIsDownloading(false);
1241
+ return _context.finish(13);
1242
+ case 16:
1243
+ case "end":
1244
+ return _context.stop();
1245
+ }
1246
+ }, _callee, null, [[4, 9, 13, 16]]);
1247
+ }));
1248
+ return function downloadPdf() {
1249
+ return _ref2.apply(this, arguments);
1250
+ };
1251
+ }();
1252
+ return {
1253
+ downloadPdf: downloadPdf,
1254
+ isDownloading: isDownloading
1255
+ };
1256
+ };
1257
+
1258
+ var usePdfEditorDocument = function usePdfEditorDocument(_ref) {
1259
+ var _pdfDocument$template;
1260
+ var apiBaseUrl = _ref.apiBaseUrl,
1261
+ documentId = _ref.documentId,
1262
+ ownerId = _ref.ownerId,
1263
+ t = _ref.t;
1264
+ var _useFetchPdfDocument = FilenameUtilities.useFetchPdfDocument({
1265
+ apiBaseUrl: apiBaseUrl,
1266
+ ownerId: ownerId,
1267
+ documentId: documentId
1268
+ }),
1269
+ documentResponse = _useFetchPdfDocument.data,
1270
+ isDocumentLoading = _useFetchPdfDocument.isLoading;
1271
+ var pdfDocument = documentResponse === null || documentResponse === void 0 ? void 0 : documentResponse.document;
1272
+ var _useUpdatePdfDocument = FilenameUtilities.useUpdatePdfDocument({
1273
+ apiBaseUrl: apiBaseUrl,
1274
+ ownerId: ownerId,
1275
+ options: {
1276
+ onSuccess: function onSuccess() {
1277
+ return neetoAtoms.Toastr.success(t("neetoPdf.pdfDocuments.editor.saveSuccess"));
1278
+ },
1279
+ onError: function onError(error) {
1280
+ return neetoAtoms.Toastr.error(FilenameUtilities.getPdfDocumentApiErrorMessage(error, t("neetoPdf.pdfDocuments.editor.saveError")));
1281
+ }
1282
+ }
1283
+ }),
1284
+ saveMappings = _useUpdatePdfDocument.mutate,
1285
+ isSaving = _useUpdatePdfDocument.isPending;
1286
+ var _useUpdatePdfDocument2 = FilenameUtilities.useUpdatePdfDocument({
1287
+ apiBaseUrl: apiBaseUrl,
1288
+ ownerId: ownerId,
1289
+ options: {
1290
+ onSuccess: function onSuccess() {
1291
+ return neetoAtoms.Toastr.success(t("neetoPdf.pdfDocuments.rename.success"));
1292
+ },
1293
+ onError: function onError(error) {
1294
+ return neetoAtoms.Toastr.error(FilenameUtilities.getPdfDocumentApiErrorMessage(error, t("neetoPdf.pdfDocuments.rename.error")));
1295
+ }
1296
+ }
1297
+ }),
1298
+ renameDocument = _useUpdatePdfDocument2.mutate;
1299
+ var saveDocumentMappings = function saveDocumentMappings(_ref2) {
1300
+ var mappings = _ref2.mappings,
1301
+ onSuccess = _ref2.onSuccess;
1302
+ saveMappings({
1303
+ documentId: documentId,
1304
+ payload: {
1305
+ mappings: mappings
1306
+ }
1307
+ }, {
1308
+ onSuccess: onSuccess
1309
+ });
1310
+ };
1311
+ var renamePdfDocument = function renamePdfDocument(name) {
1312
+ var trimmedName = name.trim();
1313
+ renameDocument({
1314
+ documentId: documentId,
1315
+ payload: {
1316
+ name: trimmedName,
1317
+ outputFilename: FilenameUtilities.buildOutputFilenameTemplate(trimmedName)
1318
+ }
1319
+ });
1320
+ };
1321
+ return {
1322
+ documentName: (pdfDocument === null || pdfDocument === void 0 ? void 0 : pdfDocument.name) || "",
1323
+ isDocumentLoading: isDocumentLoading,
1324
+ isSaving: isSaving,
1325
+ pdfDocument: pdfDocument,
1326
+ renamePdfDocument: renamePdfDocument,
1327
+ saveDocumentMappings: saveDocumentMappings,
1328
+ templateUrl: pdfDocument === null || pdfDocument === void 0 || (_pdfDocument$template = pdfDocument.templateFile) === null || _pdfDocument$template === void 0 ? void 0 : _pdfDocument$template.url
1329
+ };
1330
+ };
1331
+
1332
+ function ownKeys$1(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
1333
+ function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$1(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$1(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
1334
+ var htmlToPlainText = function htmlToPlainText(value) {
1335
+ var element = window.document.createElement("div");
1336
+ element.innerHTML = value || "";
1337
+ return element.textContent || element.innerText || "";
1338
+ };
1339
+ var generateId = function generateId() {
1340
+ var _window$crypto, _window$crypto$random;
1341
+ return ((_window$crypto = window.crypto) === null || _window$crypto === void 0 || (_window$crypto$random = _window$crypto.randomUUID) === null || _window$crypto$random === void 0 ? void 0 : _window$crypto$random.call(_window$crypto)) || "".concat(Date.now(), "-").concat(Math.random());
1342
+ };
1343
+
1344
+ // Turn the form's records into the "Answers" list shown in the left panel.
1345
+ var buildAnswerFields = function buildAnswerFields() {
1346
+ var fields = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1347
+ return fields.filter(function (field) {
1348
+ return field;
1349
+ }).map(function (field) {
1350
+ return {
1351
+ source: FIELD_SOURCES.ANSWER,
1352
+ key: field.key || field.slug,
1353
+ recordId: field.recordId || field.id || null,
1354
+ slug: field.slug || field.key,
1355
+ label: htmlToPlainText(field.label || ""),
1356
+ kind: field.kind,
1357
+ icon: field.icon,
1358
+ typeLabel: field.typeLabel || field.kind || ""
1359
+ };
1360
+ });
1361
+ };
1362
+ var buildMapping = function buildMapping(_ref) {
1363
+ var _field$recordId;
1364
+ var field = _ref.field,
1365
+ page = _ref.page,
1366
+ scale = _ref.scale;
1367
+ return _objectSpread$1(_objectSpread$1(_objectSpread$1({
1368
+ id: generateId(),
1369
+ source: field.source,
1370
+ fieldSlug: field.key,
1371
+ recordId: (_field$recordId = field.recordId) !== null && _field$recordId !== void 0 ? _field$recordId : null,
1372
+ label: field.label,
1373
+ kind: field.kind,
1374
+ page: page
1375
+ }, DEFAULT_BOX), DEFAULT_STYLE), {}, {
1376
+ fontSize: getDefaultFontSizeForScale(scale)
1377
+ });
1378
+ };
1379
+
1380
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
1381
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
1382
+ var usePdfMappingsState = function usePdfMappingsState(_ref) {
1383
+ var documentId = _ref.documentId,
1384
+ pdfDocument = _ref.pdfDocument;
1385
+ var _useState = react.useState([]),
1386
+ _useState2 = _slicedToArray(_useState, 2),
1387
+ mappings = _useState2[0],
1388
+ setMappings = _useState2[1];
1389
+ var _useState3 = react.useState(null),
1390
+ _useState4 = _slicedToArray(_useState3, 2),
1391
+ selectedId = _useState4[0],
1392
+ setSelectedId = _useState4[1];
1393
+ var _useState5 = react.useState(function () {
1394
+ return new Map();
1395
+ }),
1396
+ _useState6 = _slicedToArray(_useState5, 2),
1397
+ pageScales = _useState6[0],
1398
+ setPageScales = _useState6[1];
1399
+ var _useState7 = react.useState(false),
1400
+ _useState8 = _slicedToArray(_useState7, 2),
1401
+ isDirty = _useState8[0],
1402
+ setIsDirty = _useState8[1];
1403
+ var draggedFieldRef = react.useRef(null);
1404
+ var initializedRef = react.useRef(null);
1405
+ react.useEffect(function () {
1406
+ if (!(pdfDocument && initializedRef.current !== documentId)) return;
1407
+ initializedRef.current = documentId;
1408
+ setMappings(pdfDocument.mappings || []);
1409
+ setIsDirty(false);
1410
+ }, [pdfDocument, documentId]);
1411
+ var selectedMapping = neetoCist.findById(selectedId, mappings) || null;
1412
+ var mutateMappings = function mutateMappings(updater) {
1413
+ setMappings(updater);
1414
+ setIsDirty(true);
1415
+ };
1416
+ var handleAddField = function handleAddField(field) {
1417
+ var mapping = buildMapping({
1418
+ field: field,
1419
+ page: 1,
1420
+ scale: pageScales.get(1)
1421
+ });
1422
+ mutateMappings(ramda.append(mapping));
1423
+ setSelectedId(mapping.id);
1424
+ };
1425
+ var handleDropField = function handleDropField(_ref2) {
1426
+ var pageNumber = _ref2.pageNumber,
1427
+ scale = _ref2.scale,
1428
+ x = _ref2.x,
1429
+ y = _ref2.y;
1430
+ var field = draggedFieldRef.current;
1431
+ if (!field) return;
1432
+ var mapping = _objectSpread(_objectSpread({}, buildMapping({
1433
+ field: field,
1434
+ page: pageNumber,
1435
+ scale: scale
1436
+ })), {}, {
1437
+ x: clamp(x, 0, 1 - DEFAULT_BOX.width),
1438
+ y: clamp(y, 0, 1 - DEFAULT_BOX.height)
1439
+ });
1440
+ mutateMappings(ramda.append(mapping));
1441
+ setSelectedId(mapping.id);
1442
+ };
1443
+ var handleChangeMapping = function handleChangeMapping(id, patch) {
1444
+ return mutateMappings(function (prev) {
1445
+ return prev.map(function (mapping) {
1446
+ return mapping.id === id ? _objectSpread(_objectSpread({}, mapping), patch) : mapping;
1447
+ });
1448
+ });
1449
+ };
1450
+ var handlePageScaleChange = function handlePageScaleChange(pageNumber, scale) {
1451
+ setPageScales(function (prev) {
1452
+ if (prev.get(pageNumber) === scale) return prev;
1453
+ var nextPageScales = new Map(prev);
1454
+ nextPageScales.set(pageNumber, scale);
1455
+ return nextPageScales;
1456
+ });
1457
+ };
1458
+ var handleRemoveMapping = function handleRemoveMapping(id) {
1459
+ mutateMappings(function (prev) {
1460
+ return neetoCist.removeById(id, prev);
1461
+ });
1462
+ setSelectedId(function (current) {
1463
+ return current === id ? null : current;
1464
+ });
1465
+ };
1466
+ var handleDragEndField = function handleDragEndField() {
1467
+ draggedFieldRef.current = null;
1468
+ };
1469
+ var handleDragStartField = function handleDragStartField(field) {
1470
+ draggedFieldRef.current = field;
1471
+ };
1472
+ return {
1473
+ handleAddField: handleAddField,
1474
+ handleChangeMapping: handleChangeMapping,
1475
+ handleDragEndField: handleDragEndField,
1476
+ handleDragStartField: handleDragStartField,
1477
+ handleDropField: handleDropField,
1478
+ handlePageScaleChange: handlePageScaleChange,
1479
+ handleRemoveMapping: handleRemoveMapping,
1480
+ isDirty: isDirty,
1481
+ mappings: mappings,
1482
+ selectedId: selectedId,
1483
+ selectedMapping: selectedMapping,
1484
+ setIsDirty: setIsDirty,
1485
+ setSelectedId: setSelectedId
1486
+ };
1487
+ };
1488
+
1489
+ var usePreviewPagination = function usePreviewPagination(_ref) {
1490
+ var controlledMode = _ref.controlledMode,
1491
+ onModeChange = _ref.onModeChange,
1492
+ onPreviewPageChange = _ref.onPreviewPageChange,
1493
+ previewPage = _ref.previewPage,
1494
+ setSelectedId = _ref.setSelectedId;
1495
+ var _useState = react.useState(previewPage),
1496
+ _useState2 = _slicedToArray(_useState, 2),
1497
+ localPreviewPage = _useState2[0],
1498
+ setLocalPreviewPage = _useState2[1];
1499
+ var _useState3 = react.useState(EDITOR_MODES.MAP),
1500
+ _useState4 = _slicedToArray(_useState3, 2),
1501
+ localMode = _useState4[0],
1502
+ setLocalMode = _useState4[1];
1503
+ var mode = controlledMode || localMode;
1504
+ var isPreview = mode === EDITOR_MODES.PREVIEW;
1505
+ var currentPreviewPage = onPreviewPageChange ? previewPage : localPreviewPage;
1506
+ react.useEffect(function () {
1507
+ if (!isPreview) return;
1508
+ setSelectedId(null);
1509
+ setLocalPreviewPage(1);
1510
+ onPreviewPageChange === null || onPreviewPageChange === void 0 || onPreviewPageChange(1);
1511
+ }, [isPreview, onPreviewPageChange, setSelectedId]);
1512
+ var setPreviewPage = function setPreviewPage(page) {
1513
+ setLocalPreviewPage(page);
1514
+ onPreviewPageChange === null || onPreviewPageChange === void 0 || onPreviewPageChange(page);
1515
+ };
1516
+ var handleModeChange = function handleModeChange(nextMode) {
1517
+ setLocalMode(nextMode);
1518
+ onModeChange === null || onModeChange === void 0 || onModeChange(nextMode);
1519
+ };
1520
+ return {
1521
+ currentPreviewPage: currentPreviewPage,
1522
+ handleModeChange: handleModeChange,
1523
+ isPreview: isPreview,
1524
+ mode: mode,
1525
+ setPreviewPage: setPreviewPage
1526
+ };
1527
+ };
1528
+
1529
+ var PreviewPager = function PreviewPager(_ref) {
1530
+ var page = _ref.page,
1531
+ total = _ref.total,
1532
+ isLoading = _ref.isLoading,
1533
+ onPrev = _ref.onPrev,
1534
+ onNext = _ref.onNext;
1535
+ var _useTranslation = reactI18next.useTranslation(),
1536
+ t = _useTranslation.t;
1537
+ if (!isLoading && total === 0) {
1538
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
1539
+ className: "border-border bg-background shadow-md rounded-lg border px-3 py-1.5",
1540
+ children: /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
1541
+ className: "text-muted-foreground",
1542
+ variant: "body3",
1543
+ children: t("neetoPdf.pdfDocuments.editor.preview.noSubmissions")
1544
+ })
1545
+ });
1546
+ }
1547
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1548
+ className: "border-border bg-background shadow-md rounded-lg flex items-center gap-1 border px-1",
1549
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
1550
+ disabled: page <= 1 || isLoading,
1551
+ icon: Left,
1552
+ size: "small",
1553
+ variant: "ghost",
1554
+ onClick: onPrev
1555
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Typography, {
1556
+ className: "px-1 whitespace-nowrap",
1557
+ variant: "body3",
1558
+ children: t("neetoPdf.pdfDocuments.editor.preview.counter", {
1559
+ page: page,
1560
+ total: total
1561
+ })
1562
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
1563
+ disabled: page >= total || isLoading,
1564
+ icon: Right,
1565
+ size: "small",
1566
+ variant: "ghost",
1567
+ onClick: onNext
1568
+ })]
1569
+ });
1570
+ };
1571
+
1572
+ var _coerceToText = function coerceToText(value) {
1573
+ if (value === null || value === undefined) return "";
1574
+ if (Array.isArray(value)) {
1575
+ return value.map(_coerceToText).filter(Boolean).join(", ");
1576
+ }
1577
+ if (_typeof(value) === "object") {
1578
+ if ("value" in value) return _coerceToText(value.value);
1579
+ if ("label" in value) return _coerceToText(value.label);
1580
+ return "";
1581
+ }
1582
+ return String(value);
1583
+ };
1584
+
1585
+ // Resolve the text shown for a placement in "Preview with data" mode. Returns
1586
+ // "" (rendered blank) when the current submission has no answer for the field.
1587
+ var resolvePreviewValue = function resolvePreviewValue(_ref) {
1588
+ var mapping = _ref.mapping,
1589
+ _ref$responsesBySlug = _ref.responsesBySlug,
1590
+ responsesBySlug = _ref$responsesBySlug === void 0 ? {} : _ref$responsesBySlug,
1591
+ form = _ref.form,
1592
+ submission = _ref.submission;
1593
+ if (mapping.source === FIELD_SOURCES.SYSTEM) {
1594
+ switch (mapping.fieldSlug) {
1595
+ case SYSTEM_FIELD_KEYS.FORM_NAME:
1596
+ return (form === null || form === void 0 ? void 0 : form.title) || (form === null || form === void 0 ? void 0 : form.name) || "";
1597
+ case SYSTEM_FIELD_KEYS.SUBMISSION_ID:
1598
+ return (submission === null || submission === void 0 ? void 0 : submission.id) || "";
1599
+ case SYSTEM_FIELD_KEYS.SUBMISSION_DATE:
1600
+ return submission !== null && submission !== void 0 && submission.createdAt ? utils.dateFormat.dateTime(submission.createdAt) : "";
1601
+ default:
1602
+ return "";
1603
+ }
1604
+ }
1605
+ return _coerceToText(responsesBySlug[mapping.fieldSlug]);
1606
+ };
1607
+
1608
+ // Build a slug -> value lookup from a single submission's responses array.
1609
+ var buildResponsesBySlug = function buildResponsesBySlug() {
1610
+ var responses = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1611
+ return responses.reduce(function (acc, response) {
1612
+ if ((response === null || response === void 0 ? void 0 : response.slug) !== undefined) acc[response.slug] = response.value;
1613
+ return acc;
1614
+ }, {});
1615
+ };
1616
+
1617
+ var TopBar = function TopBar(_ref) {
1618
+ var name = _ref.name,
1619
+ onRename = _ref.onRename,
1620
+ canManage = _ref.canManage,
1621
+ homeUrl = _ref.homeUrl,
1622
+ isPreview = _ref.isPreview,
1623
+ zoom = _ref.zoom,
1624
+ onZoomIn = _ref.onZoomIn,
1625
+ onZoomOut = _ref.onZoomOut,
1626
+ onDownload = _ref.onDownload,
1627
+ isDownloading = _ref.isDownloading,
1628
+ canDownload = _ref.canDownload,
1629
+ onSave = _ref.onSave,
1630
+ isSaving = _ref.isSaving,
1631
+ isDirty = _ref.isDirty,
1632
+ onBack = _ref.onBack,
1633
+ onModeChange = _ref.onModeChange;
1634
+ var _useTranslation = reactI18next.useTranslation(),
1635
+ t = _useTranslation.t;
1636
+ var headerLinks = [{
1637
+ key: EDITOR_MODES.MAP,
1638
+ label: t("neetoPdf.pdfDocuments.editor.mapFields"),
1639
+ to: "#map",
1640
+ isActive: function isActive() {
1641
+ return !isPreview;
1642
+ },
1643
+ onClick: function onClick(event) {
1644
+ event.preventDefault();
1645
+ onModeChange(EDITOR_MODES.MAP);
1646
+ }
1647
+ }, {
1648
+ key: EDITOR_MODES.PREVIEW,
1649
+ label: t("neetoPdf.pdfDocuments.editor.previewWithData"),
1650
+ to: "#preview",
1651
+ isActive: function isActive() {
1652
+ return isPreview;
1653
+ },
1654
+ onClick: function onClick(event) {
1655
+ event.preventDefault();
1656
+ onModeChange(EDITOR_MODES.PREVIEW);
1657
+ }
1658
+ }];
1659
+ var rightActionBlock = /*#__PURE__*/jsxRuntime.jsxs("div", {
1660
+ className: "flex w-full items-center justify-end gap-3",
1661
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1662
+ className: "flex items-center gap-1",
1663
+ children: [/*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
1664
+ disabled: zoom <= ZOOM.MIN,
1665
+ icon: Minus,
1666
+ size: "small",
1667
+ variant: "ghost",
1668
+ onClick: onZoomOut
1669
+ }), /*#__PURE__*/jsxRuntime.jsxs(neetoAtoms.Typography, {
1670
+ className: "w-10 text-center",
1671
+ variant: "body3",
1672
+ children: [Math.round(zoom * 100), "%"]
1673
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
1674
+ disabled: zoom >= ZOOM.MAX,
1675
+ icon: Plus,
1676
+ size: "small",
1677
+ variant: "ghost",
1678
+ onClick: onZoomIn
1679
+ })]
1680
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
1681
+ disabled: !canDownload,
1682
+ icon: Download,
1683
+ label: t("neetoPdf.pdfDocuments.editor.downloadPdf"),
1684
+ loading: isDownloading,
1685
+ variant: "secondary",
1686
+ tooltipProps: {
1687
+ content: canDownload ? t("neetoPdf.pdfDocuments.editor.downloadTooltip") : t("neetoPdf.pdfDocuments.editor.downloadHint")
1688
+ },
1689
+ onClick: onDownload
1690
+ }), /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Button, {
1691
+ disabled: !isDirty,
1692
+ label: t("neetoPdf.common.save"),
1693
+ loading: isSaving,
1694
+ onClick: onSave
1695
+ })]
1696
+ });
1697
+ return /*#__PURE__*/jsxRuntime.jsx(NavigationHeader, {
1698
+ rightActionBlock: rightActionBlock,
1699
+ leftActionBlock: /*#__PURE__*/jsxRuntime.jsx(NavigationHeader.LeftActionBlock, {
1700
+ homeUrl: homeUrl || "#",
1701
+ homeButtonProps: {
1702
+ icon: /*#__PURE__*/jsxRuntime.jsx(LeftArrow, {}),
1703
+ tooltip: {
1704
+ content: t("neetoPdf.pdfDocuments.editor.back"),
1705
+ position: "bottom"
1706
+ },
1707
+ onClick: onBack
1708
+ },
1709
+ renameProps: {
1710
+ value: name,
1711
+ disabled: !canManage,
1712
+ placeholder: t("neetoPdf.pdfDocuments.rename.placeholder"),
1713
+ onRename: onRename
1714
+ }
1715
+ }),
1716
+ navigationLinks: /*#__PURE__*/jsxRuntime.jsx(NavigationHeader.NavigationLinks, {
1717
+ headerLinks: headerLinks,
1718
+ maxVisibleLinks: 2
1719
+ })
1720
+ });
1721
+ };
1722
+
1723
+ var FullScreenSpinner = function FullScreenSpinner() {
1724
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
1725
+ className: "bg-background fixed inset-0 z-50 flex items-center justify-center",
1726
+ children: /*#__PURE__*/jsxRuntime.jsx(neetoAtoms.Spinner, {})
1727
+ });
1728
+ };
1729
+ var PdfEditorPage = function PdfEditorPage(_ref) {
1730
+ var apiBaseUrl = _ref.apiBaseUrl,
1731
+ ownerId = _ref.ownerId,
1732
+ documentId = _ref.documentId,
1733
+ _ref$canManage = _ref.canManage,
1734
+ canManage = _ref$canManage === void 0 ? true : _ref$canManage,
1735
+ _ref$fields = _ref.fields,
1736
+ fields = _ref$fields === void 0 ? [] : _ref$fields,
1737
+ _ref$ownerRecord = _ref.ownerRecord,
1738
+ ownerRecord = _ref$ownerRecord === void 0 ? {} : _ref$ownerRecord,
1739
+ previewRecord = _ref.previewRecord,
1740
+ _ref$previewTotal = _ref.previewTotal,
1741
+ previewTotal = _ref$previewTotal === void 0 ? 0 : _ref$previewTotal,
1742
+ _ref$previewPage = _ref.previewPage,
1743
+ previewPage = _ref$previewPage === void 0 ? 1 : _ref$previewPage,
1744
+ _ref$isPreviewLoading = _ref.isPreviewLoading,
1745
+ isPreviewLoading = _ref$isPreviewLoading === void 0 ? false : _ref$isPreviewLoading,
1746
+ controlledMode = _ref.mode,
1747
+ homeUrl = _ref.homeUrl,
1748
+ onBack = _ref.onBack,
1749
+ onModeChange = _ref.onModeChange,
1750
+ onPreviewPageChange = _ref.onPreviewPageChange;
1751
+ var _useTranslation = reactI18next.useTranslation(),
1752
+ t = _useTranslation.t;
1753
+ var _useState = react.useState(ZOOM.DEFAULT),
1754
+ _useState2 = _slicedToArray(_useState, 2),
1755
+ zoom = _useState2[0],
1756
+ setZoom = _useState2[1];
1757
+ var _usePdfEditorDocument = usePdfEditorDocument({
1758
+ apiBaseUrl: apiBaseUrl,
1759
+ documentId: documentId,
1760
+ ownerId: ownerId,
1761
+ t: t
1762
+ }),
1763
+ documentName = _usePdfEditorDocument.documentName,
1764
+ isDocumentLoading = _usePdfEditorDocument.isDocumentLoading,
1765
+ isSaving = _usePdfEditorDocument.isSaving,
1766
+ pdfDocument = _usePdfEditorDocument.pdfDocument,
1767
+ renamePdfDocument = _usePdfEditorDocument.renamePdfDocument,
1768
+ saveDocumentMappings = _usePdfEditorDocument.saveDocumentMappings,
1769
+ templateUrl = _usePdfEditorDocument.templateUrl;
1770
+ var _usePdfMappingsState = usePdfMappingsState({
1771
+ documentId: documentId,
1772
+ pdfDocument: pdfDocument
1773
+ }),
1774
+ handleAddField = _usePdfMappingsState.handleAddField,
1775
+ handleChangeMapping = _usePdfMappingsState.handleChangeMapping,
1776
+ handleDragEndField = _usePdfMappingsState.handleDragEndField,
1777
+ handleDragStartField = _usePdfMappingsState.handleDragStartField,
1778
+ handleDropField = _usePdfMappingsState.handleDropField,
1779
+ handlePageScaleChange = _usePdfMappingsState.handlePageScaleChange,
1780
+ handleRemoveMapping = _usePdfMappingsState.handleRemoveMapping,
1781
+ isDirty = _usePdfMappingsState.isDirty,
1782
+ mappings = _usePdfMappingsState.mappings,
1783
+ selectedId = _usePdfMappingsState.selectedId,
1784
+ selectedMapping = _usePdfMappingsState.selectedMapping,
1785
+ setIsDirty = _usePdfMappingsState.setIsDirty,
1786
+ setSelectedId = _usePdfMappingsState.setSelectedId;
1787
+ var _usePreviewPagination = usePreviewPagination({
1788
+ controlledMode: controlledMode,
1789
+ onModeChange: onModeChange,
1790
+ onPreviewPageChange: onPreviewPageChange,
1791
+ previewPage: previewPage,
1792
+ setSelectedId: setSelectedId
1793
+ }),
1794
+ currentPreviewPage = _usePreviewPagination.currentPreviewPage,
1795
+ handleModeChange = _usePreviewPagination.handleModeChange,
1796
+ isPreview = _usePreviewPagination.isPreview,
1797
+ mode = _usePreviewPagination.mode,
1798
+ setPreviewPage = _usePreviewPagination.setPreviewPage;
1799
+ var answerFields = react.useMemo(function () {
1800
+ return buildAnswerFields(fields);
1801
+ }, [fields]);
1802
+ var systemFields = react.useMemo(function () {
1803
+ return SYSTEM_FIELDS.map(function (_ref2) {
1804
+ var key = _ref2.key,
1805
+ labelKey = _ref2.labelKey,
1806
+ icon = _ref2.icon;
1807
+ return {
1808
+ source: FIELD_SOURCES.SYSTEM,
1809
+ key: key,
1810
+ label: t(labelKey),
1811
+ typeLabel: t("neetoPdf.pdfDocuments.editor.system"),
1812
+ kind: key,
1813
+ icon: icon
1814
+ };
1815
+ });
1816
+ }, [t]);
1817
+ var responsesBySlug = react.useMemo(function () {
1818
+ return buildResponsesBySlug(previewRecord === null || previewRecord === void 0 ? void 0 : previewRecord.responses);
1819
+ }, [previewRecord]);
1820
+ var resolveValue = function resolveValue(mapping) {
1821
+ return resolvePreviewValue({
1822
+ mapping: mapping,
1823
+ responsesBySlug: responsesBySlug,
1824
+ form: ownerRecord,
1825
+ submission: previewRecord
1826
+ });
1827
+ };
1828
+ var _usePdfDownload = usePdfDownload({
1829
+ mappings: mappings,
1830
+ pdfDocument: pdfDocument,
1831
+ previewRecord: previewRecord,
1832
+ resolveValue: resolveValue,
1833
+ t: t
1834
+ }),
1835
+ downloadPdf = _usePdfDownload.downloadPdf,
1836
+ isDownloading = _usePdfDownload.isDownloading;
1837
+ var handleSave = function handleSave() {
1838
+ return saveDocumentMappings({
1839
+ mappings: mappings,
1840
+ onSuccess: function onSuccess() {
1841
+ return setIsDirty(false);
1842
+ }
1843
+ });
1844
+ };
1845
+ if (isDocumentLoading) return /*#__PURE__*/jsxRuntime.jsx(FullScreenSpinner, {});
1846
+ return /*#__PURE__*/reactDom.createPortal(/*#__PURE__*/jsxRuntime.jsxs("div", {
1847
+ className: "bg-background fixed inset-0 z-50 flex flex-col",
1848
+ children: [/*#__PURE__*/jsxRuntime.jsx(TopBar, {
1849
+ canManage: canManage,
1850
+ documentId: documentId,
1851
+ homeUrl: homeUrl,
1852
+ isDirty: isDirty,
1853
+ isDownloading: isDownloading,
1854
+ isPreview: isPreview,
1855
+ isSaving: isSaving,
1856
+ mode: mode,
1857
+ onBack: onBack,
1858
+ zoom: zoom,
1859
+ canDownload: isPreview && Boolean(previewRecord),
1860
+ name: documentName,
1861
+ onDownload: downloadPdf,
1862
+ onModeChange: handleModeChange,
1863
+ onRename: renamePdfDocument,
1864
+ onSave: handleSave,
1865
+ onZoomIn: function onZoomIn() {
1866
+ return setZoom(function (value) {
1867
+ return clamp(value + ZOOM.STEP, ZOOM.MIN, ZOOM.MAX);
1868
+ });
1869
+ },
1870
+ onZoomOut: function onZoomOut() {
1871
+ return setZoom(function (value) {
1872
+ return clamp(value - ZOOM.STEP, ZOOM.MIN, ZOOM.MAX);
1873
+ });
1874
+ }
1875
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1876
+ className: "flex min-h-0 grow overflow-hidden",
1877
+ children: [!isPreview && /*#__PURE__*/jsxRuntime.jsx(FieldsPanel, {
1878
+ answerFields: answerFields,
1879
+ systemFields: systemFields,
1880
+ onDragEndField: handleDragEndField,
1881
+ onDragStartField: handleDragStartField,
1882
+ onPlace: handleAddField
1883
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1884
+ className: "relative h-full min-w-0 flex-1 overflow-hidden",
1885
+ children: [isPreview && /*#__PURE__*/jsxRuntime.jsx("div", {
1886
+ className: "absolute top-4 left-1/2 z-10 -translate-x-1/2",
1887
+ children: /*#__PURE__*/jsxRuntime.jsx(PreviewPager, {
1888
+ isLoading: isPreviewLoading,
1889
+ page: currentPreviewPage,
1890
+ total: previewTotal,
1891
+ onNext: function onNext() {
1892
+ return setPreviewPage(Math.min(currentPreviewPage + 1, previewTotal));
1893
+ },
1894
+ onPrev: function onPrev() {
1895
+ return setPreviewPage(Math.max(currentPreviewPage - 1, 1));
1896
+ }
1897
+ })
1898
+ }), /*#__PURE__*/jsxRuntime.jsx(Canvas, {
1899
+ mappings: mappings,
1900
+ mode: mode,
1901
+ resolveValue: resolveValue,
1902
+ selectedId: selectedId,
1903
+ templateUrl: templateUrl,
1904
+ zoom: zoom,
1905
+ onChange: handleChangeMapping,
1906
+ onDropField: handleDropField,
1907
+ onPageScaleChange: handlePageScaleChange,
1908
+ onSelect: setSelectedId
1909
+ })]
1910
+ }), !isPreview && /*#__PURE__*/jsxRuntime.jsx(FieldPanel, {
1911
+ mapping: selectedMapping,
1912
+ onChange: handleChangeMapping,
1913
+ onRemove: handleRemoveMapping
1914
+ })]
1915
+ })]
1916
+ }), window.document.body);
1917
+ };
1918
+
1919
+ module.exports = PdfEditorPage;
1920
+ //# sourceMappingURL=PdfEditorPage.js.map