@pdfme/ui 3.4.3 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/index.es.js +60294 -59344
  2. package/dist/index.umd.js +116 -117
  3. package/dist/types/class.d.ts +60 -10
  4. package/dist/types/components/AppContextProvider.d.ts +2 -2
  5. package/dist/types/components/CtlBar.d.ts +2 -0
  6. package/dist/types/components/Designer/Canvas/Padding.d.ts +6 -0
  7. package/dist/types/components/Designer/Canvas/index.d.ts +2 -1
  8. package/dist/types/components/Designer/LeftSidebar.d.ts +8 -0
  9. package/dist/types/components/Designer/index.d.ts +2 -1
  10. package/dist/types/components/Preview.d.ts +1 -1
  11. package/dist/types/components/Renderer.d.ts +4 -3
  12. package/dist/types/constants.d.ts +1 -1
  13. package/dist/types/contexts.d.ts +12 -3
  14. package/dist/types/helper.d.ts +21 -33
  15. package/dist/types/hooks.d.ts +1 -0
  16. package/dist/types/types.d.ts +0 -1
  17. package/package.json +1 -1
  18. package/src/Designer.tsx +8 -3
  19. package/src/Form.tsx +6 -3
  20. package/src/Viewer.tsx +0 -1
  21. package/src/class.ts +28 -5
  22. package/src/components/AppContextProvider.tsx +3 -1
  23. package/src/components/CtlBar.tsx +57 -6
  24. package/src/components/Designer/Canvas/Padding.tsx +54 -0
  25. package/src/components/Designer/Canvas/index.tsx +89 -22
  26. package/src/components/Designer/LeftSidebar.tsx +81 -0
  27. package/src/components/Designer/{Sidebar → RightSidebar}/DetailView/index.tsx +8 -13
  28. package/src/components/Designer/{Sidebar → RightSidebar}/ListView/index.tsx +3 -11
  29. package/src/components/Designer/{Sidebar → RightSidebar}/index.tsx +5 -20
  30. package/src/components/Designer/index.tsx +166 -101
  31. package/src/components/Paper.tsx +1 -2
  32. package/src/components/Preview.tsx +72 -22
  33. package/src/components/Renderer.tsx +12 -11
  34. package/src/constants.ts +1 -1
  35. package/src/helper.ts +114 -118
  36. package/src/hooks.ts +46 -14
  37. package/src/i18n.ts +194 -7
  38. package/src/types.ts +0 -1
  39. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/DetailView/AlignWidget.d.ts +0 -0
  40. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/DetailView/WidgetRenderer.d.ts +0 -0
  41. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/DetailView/index.d.ts +0 -0
  42. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/ListView/Item.d.ts +0 -0
  43. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/ListView/SelectableSortableContainer.d.ts +0 -0
  44. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/ListView/SelectableSortableItem.d.ts +0 -0
  45. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/ListView/index.d.ts +0 -0
  46. /package/dist/types/components/Designer/{Sidebar → RightSidebar}/index.d.ts +0 -0
  47. /package/src/components/Designer/{Sidebar → RightSidebar}/DetailView/AlignWidget.tsx +0 -0
  48. /package/src/components/Designer/{Sidebar → RightSidebar}/DetailView/WidgetRenderer.tsx +0 -0
  49. /package/src/components/Designer/{Sidebar → RightSidebar}/ListView/Item.tsx +0 -0
  50. /package/src/components/Designer/{Sidebar → RightSidebar}/ListView/SelectableSortableContainer.tsx +0 -0
  51. /package/src/components/Designer/{Sidebar → RightSidebar}/ListView/SelectableSortableItem.tsx +0 -0
@@ -7,25 +7,39 @@ import {
7
7
  ChangeSchemas,
8
8
  DesignerProps,
9
9
  Size,
10
- Plugin,
10
+ isBlankPdf,
11
+ px2mm,
11
12
  } from '@pdfme/common';
12
- import Sidebar from './Sidebar/index';
13
+ import { DndContext } from '@dnd-kit/core';
14
+ import RightSidebar from './RightSidebar/index';
15
+ import LeftSidebar from './LeftSidebar';
13
16
  import Canvas from './Canvas/index';
14
- import { RULER_HEIGHT, SIDEBAR_WIDTH } from '../../constants';
17
+ import { RULER_HEIGHT, RIGHT_SIDEBAR_WIDTH } from '../../constants';
15
18
  import { I18nContext, PluginsRegistry } from '../../contexts';
16
19
  import {
17
- fmtTemplate,
20
+ schemasList2template,
18
21
  uuid,
19
- set,
20
22
  cloneDeep,
21
- templateSchemas2SchemasList,
23
+ template2SchemasList,
22
24
  getPagesScrollTopByIndex,
25
+ changeSchemas as _changeSchemas,
23
26
  } from '../../helper';
24
27
  import { useUIPreProcessor, useScrollPageCursor, useInitEvents } from '../../hooks';
25
28
  import Root from '../Root';
26
29
  import ErrorScreen from '../ErrorScreen';
27
30
  import CtlBar from '../CtlBar';
28
31
 
32
+ /**
33
+ * When the canvas scales there is a displacement of the starting position of the dragged schema.
34
+ * It moves left or right from the top-left corner of the drag icon depending on the scale.
35
+ * This function calculates the adjustment needed to compensate for this displacement.
36
+ */
37
+ const scaleDragPosAdjustment = (adjustment: number, scale: number): number => {
38
+ if (scale > 1) return adjustment * (scale - 1);
39
+ if (scale < 1) return adjustment * -(1 - scale);
40
+ return 0;
41
+ }
42
+
29
43
  const TemplateEditor = ({
30
44
  template,
31
45
  size,
@@ -33,15 +47,16 @@ const TemplateEditor = ({
33
47
  onChangeTemplate,
34
48
  onPageCursorChange,
35
49
  }: Omit<DesignerProps, 'domContainer'> & {
36
- onSaveTemplate: (t: Template) => void;
37
50
  size: Size;
51
+ onSaveTemplate: (t: Template) => void;
52
+ onChangeTemplate: (t: Template) => void;
38
53
  } & {
39
54
  onChangeTemplate: (t: Template) => void
40
55
  onPageCursorChange: (newPageCursor: number) => void
41
56
  }) => {
42
57
  const past = useRef<SchemaForUI[][]>([]);
43
58
  const future = useRef<SchemaForUI[][]>([]);
44
- const mainRef = useRef<HTMLDivElement>(null);
59
+ const canvasRef = useRef<HTMLDivElement>(null);
45
60
  const paperRefs = useRef<HTMLDivElement[]>([]);
46
61
 
47
62
  const i18n = useContext(I18nContext);
@@ -55,7 +70,8 @@ const TemplateEditor = ({
55
70
  const [sidebarOpen, setSidebarOpen] = useState(true);
56
71
  const [prevTemplate, setPrevTemplate] = useState<Template | null>(null);
57
72
 
58
- const { backgrounds, pageSizes, scale, error } = useUIPreProcessor({ template, size, zoomLevel });
73
+ const { backgrounds, pageSizes, scale, error, refresh } =
74
+ useUIPreProcessor({ template, size, zoomLevel });
59
75
 
60
76
  const onEdit = (targets: HTMLElement[]) => {
61
77
  setActiveElements(targets);
@@ -68,7 +84,7 @@ const TemplateEditor = ({
68
84
  };
69
85
 
70
86
  useScrollPageCursor({
71
- ref: mainRef,
87
+ ref: canvasRef,
72
88
  pageSizes,
73
89
  scale,
74
90
  pageCursor,
@@ -86,7 +102,7 @@ const TemplateEditor = ({
86
102
  const _schemasList = cloneDeep(schemasList);
87
103
  _schemasList[pageCursor] = newSchemas;
88
104
  setSchemasList(_schemasList);
89
- onChangeTemplate(fmtTemplate(template, _schemasList));
105
+ onChangeTemplate(schemasList2template(_schemasList, template.basePdf));
90
106
  },
91
107
  [template, schemasList, pageCursor, onChangeTemplate]
92
108
  );
@@ -101,32 +117,16 @@ const TemplateEditor = ({
101
117
 
102
118
  const changeSchemas: ChangeSchemas = useCallback(
103
119
  (objs) => {
104
- const newSchemas = objs.reduce((acc, { key, value, schemaId }) => {
105
- const tgt = acc.find((s) => s.id === schemaId)! as SchemaForUI;
106
- // Assign to reference
107
- set(tgt, key, value);
108
-
109
- if (key === 'type') {
110
- const keysToKeep = ['id', 'key', 'type', 'position'];
111
- Object.keys(tgt).forEach((key) => {
112
- if (!keysToKeep.includes(key)) {
113
- delete tgt[key as keyof typeof tgt];
114
- }
115
- });
116
- const propPanel = Object.values(pluginsRegistry).find(
117
- (plugin) => plugin?.propPanel.defaultSchema.type === value
118
- )?.propPanel;
119
- set(tgt, 'data', propPanel?.defaultValue || '');
120
- Object.assign(tgt, propPanel?.defaultSchema || {});
121
- } else if (key === 'data' && tgt.readOnly) {
122
- set(tgt, 'readOnlyValue', value);
123
- }
124
-
125
- return acc;
126
- }, cloneDeep(schemasList[pageCursor]));
127
- commitSchemas(newSchemas);
120
+ _changeSchemas({
121
+ objs,
122
+ schemas: schemasList[pageCursor],
123
+ basePdf: template.basePdf,
124
+ pluginsRegistry,
125
+ pageSize: pageSizes[pageCursor],
126
+ commitSchemas,
127
+ });
128
128
  },
129
- [commitSchemas, pageCursor, schemasList]
129
+ [commitSchemas, pageCursor, schemasList, pluginsRegistry, pageSizes, template.basePdf]
130
130
  );
131
131
 
132
132
  useInitEvents({
@@ -147,33 +147,36 @@ const TemplateEditor = ({
147
147
  });
148
148
 
149
149
  const updateTemplate = useCallback(async (newTemplate: Template) => {
150
- const sl = await templateSchemas2SchemasList(newTemplate);
150
+ const sl = await template2SchemasList(newTemplate);
151
151
  setSchemasList(sl);
152
152
  onEditEnd();
153
153
  setPageCursor(0);
154
- if (mainRef.current?.scroll) {
155
- mainRef.current.scroll({ top: 0, behavior: 'smooth' });
154
+ if (canvasRef.current?.scroll) {
155
+ canvasRef.current.scroll({ top: 0, behavior: 'smooth' });
156
156
  }
157
157
  }, []);
158
158
 
159
- const addSchema = () => {
160
- const propPanel = (Object.values(pluginsRegistry)[0] as Plugin<Schema>)?.propPanel;
159
+ const addSchema = (defaultSchema: Schema) => {
160
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = isBlankPdf(template.basePdf) ? template.basePdf.padding : [0, 0, 0, 0];
161
+ const pageSize = pageSizes[pageCursor];
161
162
 
162
- if (!propPanel) {
163
- throw new Error(`[@pdfme/ui] addSchema failed: propPanel is empty.
164
- Check this document: https://pdfme.com/docs/custom-schemas`);
165
- }
163
+ const ensureMiddleValue = (min: number, value: number, max: number) => Math.min(Math.max(min, value), max)
166
164
 
167
165
  const s = {
168
166
  id: uuid(),
169
167
  key: `${i18n('field')}${schemasList[pageCursor].length + 1}`,
170
- data: propPanel.defaultValue || '',
171
- ...propPanel.defaultSchema,
168
+ ...defaultSchema,
169
+ position: {
170
+ x: ensureMiddleValue(paddingLeft, defaultSchema.position.x, pageSize.width - paddingRight - defaultSchema.width),
171
+ y: ensureMiddleValue(paddingTop, defaultSchema.position.y, pageSize.height - paddingBottom - defaultSchema.height),
172
+ },
172
173
  } as SchemaForUI;
173
174
 
174
- const paper = paperRefs.current[pageCursor];
175
- const rectTop = paper ? paper.getBoundingClientRect().top : 0;
176
- s.position.y = rectTop > 0 ? 0 : pageSizes[pageCursor].height / 2;
175
+ if (defaultSchema.position.y === 0) {
176
+ const paper = paperRefs.current[pageCursor];
177
+ const rectTop = paper ? paper.getBoundingClientRect().top : 0;
178
+ s.position.y = rectTop > 0 ? paddingTop : pageSizes[pageCursor].height / 2;
179
+ }
177
180
 
178
181
  commitSchemas(schemasList[pageCursor].concat(s));
179
182
  setTimeout(() => onEdit([document.getElementById(s.id)!]));
@@ -187,73 +190,135 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
187
190
  setHoveringSchemaId(id);
188
191
  };
189
192
 
193
+ const updatePage = async (sl: SchemaForUI[][], newPageCursor: number) => {
194
+ setPageCursor(newPageCursor);
195
+ const newTemplate = schemasList2template(sl, template.basePdf);
196
+ onChangeTemplate(newTemplate);
197
+ await updateTemplate(newTemplate);
198
+ void refresh(newTemplate);
199
+ setTimeout(
200
+ () =>
201
+ canvasRef.current &&
202
+ ((canvasRef.current.scrollTop = getPagesScrollTopByIndex(pageSizes, newPageCursor, scale)), 0)
203
+ );
204
+ };
205
+
206
+ const handleRemovePage = () => {
207
+ if (pageCursor === 0) return;
208
+ if (!window.confirm(i18n('removePageConfirm'))) return;
209
+
210
+ const _schemasList = cloneDeep(schemasList);
211
+ _schemasList.splice(pageCursor, 1);
212
+ void updatePage(_schemasList, pageCursor - 1);
213
+ };
214
+
215
+ const handleAddPageAfter = () => {
216
+ const _schemasList = cloneDeep(schemasList);
217
+ _schemasList.splice(pageCursor + 1, 0, []);
218
+ void updatePage(_schemasList, pageCursor + 1);
219
+ };
220
+
190
221
  if (prevTemplate !== template) {
191
222
  setPrevTemplate(template);
192
223
  void updateTemplate(template);
193
224
  }
194
225
 
195
226
  const sizeExcSidebar = {
196
- width: sidebarOpen ? size.width - SIDEBAR_WIDTH : size.width,
227
+ width: sidebarOpen ? size.width - RIGHT_SIDEBAR_WIDTH : size.width,
197
228
  height: size.height,
198
229
  };
199
230
 
200
231
  if (error) {
201
232
  return <ErrorScreen size={size} error={error} />;
202
233
  }
234
+ const pageManipulation = isBlankPdf(template.basePdf)
235
+ ? { addPageAfter: handleAddPageAfter, removePage: handleRemovePage }
236
+ : {};
203
237
 
204
238
  return (
205
239
  <Root size={size} scale={scale}>
206
- <CtlBar
207
- size={sizeExcSidebar}
208
- pageCursor={pageCursor}
209
- pageNum={schemasList.length}
210
- setPageCursor={(p) => {
211
- if (!mainRef.current) return;
212
- mainRef.current.scrollTop = getPagesScrollTopByIndex(pageSizes, p, scale);
213
- setPageCursor(p);
214
- onEditEnd();
215
- }}
216
- zoomLevel={zoomLevel}
217
- setZoomLevel={setZoomLevel}
218
- />
219
- <Sidebar
220
- hoveringSchemaId={hoveringSchemaId}
221
- onChangeHoveringSchemaId={onChangeHoveringSchemaId}
222
- height={mainRef.current ? mainRef.current.clientHeight : 0}
223
- size={size}
224
- pageSize={pageSizes[pageCursor]}
225
- activeElements={activeElements}
226
- schemas={schemasList[pageCursor]}
227
- changeSchemas={changeSchemas}
228
- onSortEnd={onSortEnd}
229
- onEdit={(id: string) => {
230
- const editingElem = document.getElementById(id);
231
- editingElem && onEdit([editingElem]);
240
+ <DndContext
241
+ onDragEnd={(event) => {
242
+ // Triggered after a schema is dragged & dropped from the left sidebar.
243
+ if (!event.active) return;
244
+ const active = event.active;
245
+ const pageRect = paperRefs.current[pageCursor].getBoundingClientRect();
246
+
247
+ const dragStartLeft = active.rect.current.initial?.left || 0;
248
+ const dragStartTop = active.rect.current.initial?.top || 0;
249
+
250
+ const canvasLeftOffsetFromPageCorner = pageRect.left - dragStartLeft + scaleDragPosAdjustment(20, scale);
251
+ const canvasTopOffsetFromPageCorner = pageRect.top - dragStartTop;
252
+
253
+ const moveY = (event.delta.y - canvasTopOffsetFromPageCorner) / scale;
254
+ const moveX = (event.delta.x - canvasLeftOffsetFromPageCorner) / scale;
255
+
256
+ const position = { x: px2mm(Math.max(0, moveX)), y: px2mm(Math.max(0, moveY)) }
257
+
258
+ addSchema({ ...(active.data.current as Schema), position });
232
259
  }}
233
- onEditEnd={onEditEnd}
234
- addSchema={addSchema}
235
- deselectSchema={onEditEnd}
236
- sidebarOpen={sidebarOpen}
237
- setSidebarOpen={setSidebarOpen}
238
- />
239
- <Canvas
240
- ref={mainRef}
241
- paperRefs={paperRefs}
242
- hoveringSchemaId={hoveringSchemaId}
243
- onChangeHoveringSchemaId={onChangeHoveringSchemaId}
244
- height={size.height - RULER_HEIGHT * ZOOM}
245
- pageCursor={pageCursor}
246
- scale={scale}
247
- size={sizeExcSidebar}
248
- pageSizes={pageSizes}
249
- backgrounds={backgrounds}
250
- activeElements={activeElements}
251
- schemasList={schemasList}
252
- changeSchemas={changeSchemas}
253
- removeSchemas={removeSchemas}
254
- sidebarOpen={sidebarOpen}
255
- onEdit={onEdit}
256
- />
260
+ onDragStart={onEditEnd}
261
+ >
262
+ <CtlBar
263
+ size={sizeExcSidebar}
264
+ pageCursor={pageCursor}
265
+ pageNum={schemasList.length}
266
+ setPageCursor={(p) => {
267
+ if (!canvasRef.current) return;
268
+ canvasRef.current.scrollTop = getPagesScrollTopByIndex(pageSizes, p, scale);
269
+ setPageCursor(p);
270
+ onEditEnd();
271
+ }}
272
+ zoomLevel={zoomLevel}
273
+ setZoomLevel={setZoomLevel}
274
+ {...pageManipulation}
275
+ />
276
+ <LeftSidebar
277
+ height={canvasRef.current ? canvasRef.current.clientHeight : 0}
278
+ scale={scale}
279
+ basePdf={template.basePdf}
280
+ />
281
+
282
+ <RightSidebar
283
+ hoveringSchemaId={hoveringSchemaId}
284
+ onChangeHoveringSchemaId={onChangeHoveringSchemaId}
285
+ height={canvasRef.current ? canvasRef.current.clientHeight : 0}
286
+ size={size}
287
+ pageSize={pageSizes[pageCursor] ?? []}
288
+ activeElements={activeElements}
289
+ schemas={schemasList[pageCursor] ?? []}
290
+ changeSchemas={changeSchemas}
291
+ onSortEnd={onSortEnd}
292
+ onEdit={id => {
293
+ const editingElem = document.getElementById(id);
294
+ editingElem && onEdit([editingElem]);
295
+ }}
296
+ onEditEnd={onEditEnd}
297
+ deselectSchema={onEditEnd}
298
+ sidebarOpen={sidebarOpen}
299
+ setSidebarOpen={setSidebarOpen}
300
+ />
301
+
302
+ <Canvas
303
+ ref={canvasRef}
304
+ paperRefs={paperRefs}
305
+ basePdf={template.basePdf}
306
+ hoveringSchemaId={hoveringSchemaId}
307
+ onChangeHoveringSchemaId={onChangeHoveringSchemaId}
308
+ height={size.height - RULER_HEIGHT * ZOOM}
309
+ pageCursor={pageCursor}
310
+ scale={scale}
311
+ size={sizeExcSidebar}
312
+ pageSizes={pageSizes}
313
+ backgrounds={backgrounds}
314
+ activeElements={activeElements}
315
+ schemasList={schemasList}
316
+ changeSchemas={changeSchemas}
317
+ removeSchemas={removeSchemas}
318
+ sidebarOpen={sidebarOpen}
319
+ onEdit={onEdit}
320
+ />
321
+ </DndContext>
257
322
  </Root>
258
323
  );
259
324
  };
@@ -67,8 +67,7 @@ const Paper = (props: {
67
67
 
68
68
  return (
69
69
  <div
70
- id={`@pdfme/ui-paper${paperIndex}`}
71
- key={paperIndex + JSON.stringify(paperSize)}
70
+ key={String(paperIndex) + JSON.stringify(paperSize)}
72
71
  ref={(e) => {
73
72
  if (e) {
74
73
  paperRefs.current[paperIndex] = e;
@@ -1,5 +1,6 @@
1
- import React, { useCallback, useRef, useState, useEffect } from 'react';
2
- import type { SchemaForUI, PreviewProps, Size } from '@pdfme/common';
1
+ import React, { useRef, useState, useEffect, useContext } from 'react';
2
+ import { Template, SchemaForUI, PreviewProps, Size, getDynamicTemplate } from '@pdfme/common';
3
+ import { modifyTemplateForTable, getDynamicHeightForTable } from '@pdfme/schemas';
3
4
  import UnitPager from './UnitPager';
4
5
  import Root from './Root';
5
6
  import ErrorScreen from './ErrorScreen';
@@ -7,9 +8,12 @@ import CtlBar from './CtlBar';
7
8
  import Paper from './Paper';
8
9
  import Renderer from './Renderer';
9
10
  import { useUIPreProcessor, useScrollPageCursor } from '../hooks';
10
- import { templateSchemas2SchemasList, getPagesScrollTopByIndex } from '../helper';
11
+ import { FontContext } from '../contexts';
12
+ import { template2SchemasList, getPagesScrollTopByIndex } from '../helper';
11
13
  import { theme } from 'antd';
12
14
 
15
+ const _cache = new Map();
16
+
13
17
  const Preview = ({
14
18
  template,
15
19
  inputs,
@@ -21,6 +25,8 @@ const Preview = ({
21
25
  }) => {
22
26
  const { token } = theme.useToken();
23
27
 
28
+ const font = useContext(FontContext);
29
+
24
30
  const containerRef = useRef<HTMLDivElement>(null);
25
31
  const paperRefs = useRef<HTMLDivElement[]>([]);
26
32
 
@@ -29,38 +35,55 @@ const Preview = ({
29
35
  const [zoomLevel, setZoomLevel] = useState(1);
30
36
  const [schemasList, setSchemasList] = useState<SchemaForUI[][]>([[]] as SchemaForUI[][]);
31
37
 
32
- const { backgrounds, pageSizes, scale, error } = useUIPreProcessor({ template, size, zoomLevel });
38
+ const { backgrounds, pageSizes, scale, error, refresh } =
39
+ useUIPreProcessor({ template, size, zoomLevel });
40
+
41
+ const isForm = Boolean(onChangeInput);
42
+
43
+ const input = inputs[unitCursor];
33
44
 
34
- const init = useCallback(async () => {
35
- const sl = await templateSchemas2SchemasList(template);
36
- setSchemasList(sl);
37
- }, [template]);
45
+ const init = (template: Template) => {
46
+ const options = { font };
47
+ getDynamicTemplate({
48
+ template,
49
+ input,
50
+ options,
51
+ _cache,
52
+ modifyTemplate: (arg) => {
53
+ return modifyTemplateForTable(arg);
54
+ },
55
+ getDynamicHeight: (value, args) => {
56
+ if (args.schema.type !== 'table') return Promise.resolve(args.schema.height);
57
+ return getDynamicHeightForTable(value, args);
58
+ },
59
+ })
60
+ .then(async (dynamicTemplate) => {
61
+ const sl = await template2SchemasList(dynamicTemplate);
62
+ setSchemasList(sl);
63
+ await refresh(dynamicTemplate);
64
+ })
65
+ .catch((err) => console.error(`[@pdfme/ui] `, err));
66
+ };
38
67
 
39
68
  useEffect(() => {
40
69
  if (unitCursor > inputs.length - 1) {
41
70
  setUnitCursor(inputs.length - 1);
42
71
  }
43
- }, [inputs]);
44
72
 
45
- useEffect(() => {
46
- init();
47
- }, [init]);
73
+ init(template);
74
+ }, [template, inputs, size]);
48
75
 
49
76
  useScrollPageCursor({
50
77
  ref: containerRef,
51
78
  pageSizes,
52
79
  scale,
53
80
  pageCursor,
54
- onChangePageCursor: (p) => setPageCursor(p),
81
+ onChangePageCursor: setPageCursor,
55
82
  });
56
83
 
57
84
  const handleChangeInput = ({ key, value }: { key: string; value: string }) =>
58
85
  onChangeInput && onChangeInput({ index: unitCursor, key, value });
59
86
 
60
- const isForm = Boolean(onChangeInput);
61
-
62
- const input = inputs[unitCursor];
63
-
64
87
  if (error) {
65
88
  return <ErrorScreen size={size} error={error} />;
66
89
  }
@@ -94,16 +117,43 @@ const Preview = ({
94
117
  pageSizes={pageSizes}
95
118
  backgrounds={backgrounds}
96
119
  renderSchema={({ schema, index }) => {
97
- const { key } = schema;
98
- const data = (input && input[key]) || '';
120
+ const { key, readOnly } = schema;
121
+ const content = readOnly ? String(schema.content) || '' : String(input && input[key] || '');
99
122
  return (
100
123
  <Renderer
101
124
  key={schema.id}
102
- schema={Object.assign(schema, { data })}
125
+ schema={schema}
126
+ basePdf={template.basePdf}
127
+ value={content}
103
128
  mode={isForm ? 'form' : 'viewer'}
104
- placeholder={template.sampledata?.[0]?.[key] ?? ''}
129
+ placeholder={schema.content}
105
130
  tabIndex={index + 100}
106
- onChange={(value) => handleChangeInput({ key, value })}
131
+ onChange={(arg) => {
132
+ const args = Array.isArray(arg) ? arg : [arg];
133
+ let isNeedInit = false;
134
+ args.forEach(({ key: _key, value }) => {
135
+ if (_key === 'content') {
136
+ const newValue = value as string;
137
+ const oldValue = (input?.[key] as string) || '';
138
+ if (newValue === oldValue) return;
139
+ handleChangeInput({ key, value: newValue });
140
+ // TODO Set to true only if the execution of getDynamicTemplate, such as for a table, is required.
141
+ isNeedInit = true;
142
+ } else {
143
+ const targetSchema = schemasList[pageCursor].find(
144
+ (s) => s.id === schema.id
145
+ ) as SchemaForUI;
146
+ if (!targetSchema) return;
147
+
148
+ // @ts-ignore
149
+ targetSchema[_key] = value as string;
150
+ }
151
+ });
152
+ if (isNeedInit) {
153
+ init(template);
154
+ }
155
+ setSchemasList([...schemasList])
156
+ }}
107
157
  outline={
108
158
  isForm && !schema.readOnly ? `1px dashed ${token.colorPrimary}` : 'transparent'
109
159
  }
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useContext, ReactNode, useRef } from 'react';
2
- import { Dict, ZOOM, UIRenderProps, SchemaForUI, Schema } from '@pdfme/common';
2
+ import { Dict, ZOOM, UIRenderProps, SchemaForUI, BasePdf, Schema } from '@pdfme/common';
3
3
  import { theme as antdTheme } from 'antd';
4
4
  import { SELECTABLE_CLASSNAME } from '../constants';
5
5
  import { PluginsRegistry, OptionsContext, I18nContext } from '../contexts';
@@ -7,10 +7,11 @@ import * as pdfJs from 'pdfjs-dist/legacy/build/pdf.js';
7
7
 
8
8
  type RendererProps = Omit<
9
9
  UIRenderProps<Schema>,
10
- 'value' | 'schema' | 'onChange' | 'rootElement' | 'options' | 'theme' | 'i18n' | 'pdfJs' | '_cache'
10
+ 'schema' | 'rootElement' | 'options' | 'theme' | 'i18n' | 'pdfJs' | '_cache'
11
11
  > & {
12
+ basePdf: BasePdf;
12
13
  schema: SchemaForUI;
13
- onChange: (value: string) => void;
14
+ value: string;
14
15
  outline: string;
15
16
  onChangeHoveringSchemaId?: (id: string | null) => void;
16
17
  scale: number;
@@ -50,7 +51,8 @@ const Renderer = (props: RendererProps) => {
50
51
  const i18n = useContext(I18nContext) as (key: keyof Dict | string) => string;
51
52
  const { token: theme } = antdTheme.useToken();
52
53
 
53
- const { schema, mode, onChange, stopEditing, tabIndex, placeholder, scale } = props;
54
+ const { schema, basePdf, value, mode, onChange, stopEditing, tabIndex, placeholder, scale } =
55
+ props;
54
56
 
55
57
  const ref = useRef<HTMLDivElement>(null);
56
58
  const _cache = useRef<Map<any, any>>(new Map());
@@ -69,16 +71,15 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
69
71
 
70
72
  ref.current.innerHTML = '';
71
73
 
72
- const editable = mode === 'form' || mode === 'designer';
73
-
74
- render({
74
+ void render({
75
75
  key: schema.key,
76
- value: schema.readOnly ? schema.readOnlyValue || '' : schema.data,
76
+ value,
77
77
  schema,
78
+ basePdf,
78
79
  rootElement: ref.current,
79
80
  mode,
80
- onChange: editable ? onChange : undefined,
81
- stopEditing: editable ? stopEditing : undefined,
81
+ onChange,
82
+ stopEditing: stopEditing,
82
83
  tabIndex,
83
84
  placeholder,
84
85
  options,
@@ -93,7 +94,7 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
93
94
  ref.current.innerHTML = '';
94
95
  }
95
96
  };
96
- }, [JSON.stringify(schema), JSON.stringify(options), mode, scale]);
97
+ }, [value, JSON.stringify(schema), JSON.stringify(options), mode, scale]);
97
98
 
98
99
  return (
99
100
  <Wrapper {...props}>
package/src/constants.ts CHANGED
@@ -8,6 +8,6 @@ export const RULER_HEIGHT = 30;
8
8
 
9
9
  export const PAGE_GAP = 10;
10
10
 
11
- export const SIDEBAR_WIDTH = 350;
11
+ export const RIGHT_SIDEBAR_WIDTH = 400;
12
12
 
13
13
  export const BACKGROUND_COLOR = 'rgb(74, 74, 74)';