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