@pdfme/ui 5.3.8-dev.57 → 5.3.8-dev.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.es.js +33115 -31437
- package/dist/index.umd.js +427 -387
- package/dist/types/src/components/Designer/LeftSidebar.d.ts +1 -1
- package/dist/types/src/components/Designer/PluginIcon.d.ts +1 -1
- package/package.json +2 -2
- package/src/Designer.tsx +4 -4
- package/src/Form.tsx +1 -3
- package/src/Viewer.tsx +1 -1
- package/src/components/AppContextProvider.tsx +1 -1
- package/src/components/CtlBar.tsx +1 -1
- package/src/components/Designer/Canvas/Guides.tsx +1 -1
- package/src/components/Designer/Canvas/Moveable.tsx +2 -2
- package/src/components/Designer/Canvas/Padding.tsx +10 -8
- package/src/components/Designer/Canvas/index.tsx +27 -14
- package/src/components/Designer/LeftSidebar.tsx +57 -49
- package/src/components/Designer/PluginIcon.tsx +21 -8
- package/src/components/Designer/RightSidebar/DetailView/AlignWidget.tsx +44 -44
- package/src/components/Designer/RightSidebar/DetailView/ButtonGroupWidget.tsx +3 -3
- package/src/components/Designer/RightSidebar/DetailView/index.tsx +51 -23
- package/src/components/Designer/RightSidebar/ListView/Item.tsx +4 -4
- package/src/components/Designer/RightSidebar/ListView/SelectableSortableContainer.tsx +56 -47
- package/src/components/Designer/RightSidebar/ListView/SelectableSortableItem.tsx +2 -3
- package/src/components/Designer/RightSidebar/ListView/index.tsx +10 -3
- package/src/components/Designer/index.tsx +41 -19
- package/src/components/Preview.tsx +25 -14
- package/src/components/Renderer.tsx +35 -22
- package/src/components/Root.tsx +1 -1
- package/src/components/Spinner.tsx +1 -1
- package/src/components/StaticSchema.tsx +39 -21
- package/src/constants.ts +1 -1
- package/src/helper.ts +7 -7
- package/src/hooks.ts +3 -3
- package/src/types/react-guides.d.ts +1 -1
@@ -1,6 +1,12 @@
|
|
1
1
|
import { useForm } from 'form-render';
|
2
2
|
import React, { useRef, useContext, useState, useEffect } from 'react';
|
3
|
-
import type {
|
3
|
+
import type {
|
4
|
+
ChangeSchemaItem,
|
5
|
+
Dict,
|
6
|
+
SchemaForUI,
|
7
|
+
PropPanelWidgetProps,
|
8
|
+
PropPanelSchema,
|
9
|
+
} from '@pdfme/common';
|
4
10
|
import type { SidebarProps } from '../../../../types.js';
|
5
11
|
import { Menu } from 'lucide-react';
|
6
12
|
import { I18nContext, PluginsRegistry, OptionsContext } from '../../../../contexts.js';
|
@@ -9,15 +15,22 @@ import { theme, Typography, Button, Divider } from 'antd';
|
|
9
15
|
import AlignWidget from './AlignWidget.js';
|
10
16
|
import WidgetRenderer from './WidgetRenderer.js';
|
11
17
|
import ButtonGroupWidget from './ButtonGroupWidget.js';
|
12
|
-
import { InternalNamePath, ValidateErrorEntity } from
|
18
|
+
import { InternalNamePath, ValidateErrorEntity } from 'rc-field-form/es/interface.js';
|
13
19
|
|
14
20
|
// Import FormRender as a default import
|
15
21
|
import FormRenderComponent from 'form-render';
|
16
22
|
|
17
23
|
const { Text } = Typography;
|
18
24
|
|
19
|
-
type DetailViewProps = Pick<
|
20
|
-
|
25
|
+
type DetailViewProps = Pick<
|
26
|
+
SidebarProps,
|
27
|
+
| 'size'
|
28
|
+
| 'schemas'
|
29
|
+
| 'schemasList'
|
30
|
+
| 'pageSize'
|
31
|
+
| 'changeSchemas'
|
32
|
+
| 'activeElements'
|
33
|
+
| 'deselectSchema'
|
21
34
|
> & {
|
22
35
|
activeSchema: SchemaForUI;
|
23
36
|
};
|
@@ -64,11 +77,11 @@ const DetailView = (props: DetailViewProps) => {
|
|
64
77
|
|
65
78
|
useEffect(() => {
|
66
79
|
const values: any = { ...activeSchema };
|
67
|
-
values.editable = !
|
80
|
+
values.editable = !values.readOnly;
|
68
81
|
form.setValues(values);
|
69
82
|
}, [activeSchema, form]);
|
70
83
|
|
71
|
-
useEffect(() => form.resetFields(), [activeSchema.id])
|
84
|
+
useEffect(() => form.resetFields(), [activeSchema.id]);
|
72
85
|
|
73
86
|
useEffect(() => {
|
74
87
|
uniqueSchemaName.current = (value: string): boolean => {
|
@@ -85,7 +98,8 @@ const DetailView = (props: DetailViewProps) => {
|
|
85
98
|
|
86
99
|
const uniqueSchemaName = useRef((value: string): boolean => true);
|
87
100
|
|
88
|
-
const validateUniqueSchemaName = (_: any, value: string): boolean =>
|
101
|
+
const validateUniqueSchemaName = (_: any, value: string): boolean =>
|
102
|
+
uniqueSchemaName.current(value);
|
89
103
|
|
90
104
|
const handleWatch = debounce((formSchema: any) => {
|
91
105
|
const formAndSchemaValuesDiffer = (formValue: any, schemaValue: any): boolean => {
|
@@ -93,7 +107,7 @@ const DetailView = (props: DetailViewProps) => {
|
|
93
107
|
return JSON.stringify(formValue) !== JSON.stringify(schemaValue);
|
94
108
|
}
|
95
109
|
return formValue !== schemaValue;
|
96
|
-
}
|
110
|
+
};
|
97
111
|
|
98
112
|
let changes: ChangeSchemaItem[] = [];
|
99
113
|
for (const key in formSchema) {
|
@@ -121,15 +135,17 @@ const DetailView = (props: DetailViewProps) => {
|
|
121
135
|
|
122
136
|
if (changes.length) {
|
123
137
|
// Only commit these schema changes if they have passed form validation
|
124
|
-
form
|
138
|
+
form
|
139
|
+
.validateFields()
|
125
140
|
.then(() => changeSchemas(changes))
|
126
141
|
.catch((reason: ValidateErrorEntity) => {
|
127
142
|
if (reason.errorFields.length) {
|
128
|
-
changes = changes.filter(
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
143
|
+
changes = changes.filter(
|
144
|
+
(change: ChangeSchemaItem) =>
|
145
|
+
!reason.errorFields.find((field: { name: InternalNamePath; errors: string[] }) =>
|
146
|
+
field.name.includes(change.key),
|
147
|
+
),
|
148
|
+
);
|
133
149
|
}
|
134
150
|
if (changes.length) {
|
135
151
|
changeSchemas(changes);
|
@@ -139,7 +155,7 @@ const DetailView = (props: DetailViewProps) => {
|
|
139
155
|
}, 100);
|
140
156
|
|
141
157
|
const activePlugin = Object.values(pluginsRegistry).find(
|
142
|
-
(plugin) => plugin?.propPanel.defaultSchema.type === activeSchema.type
|
158
|
+
(plugin) => plugin?.propPanel.defaultSchema.type === activeSchema.type,
|
143
159
|
)!;
|
144
160
|
|
145
161
|
const activePropPanelSchema = activePlugin?.propPanel.schema;
|
@@ -171,14 +187,26 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
|
|
171
187
|
type: 'string',
|
172
188
|
required: true,
|
173
189
|
span: 12,
|
174
|
-
rules: [
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
190
|
+
rules: [
|
191
|
+
{
|
192
|
+
validator: validateUniqueSchemaName,
|
193
|
+
message: i18n('validation.uniqueName'),
|
194
|
+
},
|
195
|
+
],
|
196
|
+
props: { autoComplete: 'off' },
|
197
|
+
},
|
198
|
+
editable: {
|
199
|
+
title: i18n('editable'),
|
200
|
+
type: 'boolean',
|
201
|
+
span: 8,
|
202
|
+
hidden: defaultSchema?.readOnly !== undefined,
|
203
|
+
},
|
204
|
+
required: {
|
205
|
+
title: i18n('required'),
|
206
|
+
type: 'boolean',
|
207
|
+
span: 16,
|
208
|
+
hidden: '{{!formData.editable}}',
|
179
209
|
},
|
180
|
-
editable: { title: i18n('editable'), type: 'boolean', span: 8, hidden: defaultSchema?.readOnly !== undefined },
|
181
|
-
required: { title: i18n('required'), type: 'boolean', span: 16, hidden: "{{!formData.editable}}" },
|
182
210
|
'-': { type: 'void', widget: 'Divider' },
|
183
211
|
align: { title: i18n('align'), type: 'void', widget: 'AlignWidget' },
|
184
212
|
position: {
|
@@ -187,7 +215,7 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
|
|
187
215
|
properties: {
|
188
216
|
x: { title: 'X', type: 'number', widget: 'inputNumber', required: true, span: 8, min: 0 },
|
189
217
|
y: { title: 'Y', type: 'number', widget: 'inputNumber', required: true, span: 8, min: 0 },
|
190
|
-
}
|
218
|
+
},
|
191
219
|
},
|
192
220
|
width: {
|
193
221
|
title: i18n('width'),
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React, { useEffect, useContext } from 'react';
|
2
2
|
import { DraggableSyntheticListeners } from '@dnd-kit/core';
|
3
3
|
import { I18nContext } from '../../../../contexts.js';
|
4
|
-
import { GripVertical, CircleAlert, Lock } from 'lucide-react'
|
4
|
+
import { GripVertical, CircleAlert, Lock } from 'lucide-react';
|
5
5
|
import { Button, Typography } from 'antd';
|
6
6
|
|
7
7
|
const { Text } = Typography;
|
@@ -48,7 +48,7 @@ const Item = React.memo(
|
|
48
48
|
transform,
|
49
49
|
...props
|
50
50
|
},
|
51
|
-
ref
|
51
|
+
ref,
|
52
52
|
) => {
|
53
53
|
const i18n = useContext(I18nContext);
|
54
54
|
|
@@ -125,8 +125,8 @@ const Item = React.memo(
|
|
125
125
|
</div>
|
126
126
|
</li>
|
127
127
|
);
|
128
|
-
}
|
129
|
-
)
|
128
|
+
},
|
129
|
+
),
|
130
130
|
);
|
131
131
|
|
132
132
|
export default Item;
|
@@ -21,13 +21,13 @@ import { PluginsRegistry } from '../../../../contexts.js';
|
|
21
21
|
import Item from './Item.js';
|
22
22
|
import SelectableSortableItem from './SelectableSortableItem.js';
|
23
23
|
import { theme } from 'antd';
|
24
|
-
import PluginIcon from
|
24
|
+
import PluginIcon from '../../PluginIcon.js';
|
25
25
|
|
26
26
|
const SelectableSortableContainer = (
|
27
27
|
props: Pick<
|
28
28
|
SidebarProps,
|
29
29
|
'schemas' | 'onEdit' | 'onSortEnd' | 'hoveringSchemaId' | 'onChangeHoveringSchemaId'
|
30
|
-
|
30
|
+
>,
|
31
31
|
) => {
|
32
32
|
const { token } = theme.useToken();
|
33
33
|
const { schemas, onEdit, onSortEnd, hoveringSchemaId, onChangeHoveringSchemaId } = props;
|
@@ -37,7 +37,7 @@ const SelectableSortableContainer = (
|
|
37
37
|
const pluginsRegistry = useContext(PluginsRegistry);
|
38
38
|
const sensors = useSensors(
|
39
39
|
useSensor(PointerSensor, { activationConstraint: { distance: 15 } }),
|
40
|
-
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
40
|
+
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
|
41
41
|
);
|
42
42
|
|
43
43
|
const isItemSelected = (itemId: string): boolean =>
|
@@ -59,17 +59,25 @@ const SelectableSortableContainer = (
|
|
59
59
|
};
|
60
60
|
|
61
61
|
const getPluginIcon = (inSchema: string | SchemaForUI): ReactNode => {
|
62
|
-
const thisSchema =
|
62
|
+
const thisSchema =
|
63
|
+
typeof inSchema === 'string' ? schemas.find((schema) => schema.id === inSchema) : inSchema;
|
63
64
|
|
64
65
|
const [pluginLabel, activePlugin] = Object.entries(pluginsRegistry).find(
|
65
|
-
([label, plugin]) => plugin?.propPanel.defaultSchema.type === thisSchema?.type
|
66
|
+
([label, plugin]) => plugin?.propPanel.defaultSchema.type === thisSchema?.type,
|
66
67
|
)!;
|
67
68
|
|
68
69
|
if (!activePlugin) {
|
69
|
-
return
|
70
|
+
return <></>;
|
70
71
|
}
|
71
72
|
|
72
|
-
return
|
73
|
+
return (
|
74
|
+
<PluginIcon
|
75
|
+
plugin={activePlugin}
|
76
|
+
label={pluginLabel}
|
77
|
+
size={20}
|
78
|
+
styles={{ marginRight: '0.5rem' }}
|
79
|
+
/>
|
80
|
+
);
|
73
81
|
};
|
74
82
|
|
75
83
|
return (
|
@@ -90,7 +98,7 @@ const SelectableSortableContainer = (
|
|
90
98
|
return ret;
|
91
99
|
}
|
92
100
|
return ret.filter((schema) => schema !== selectedItem);
|
93
|
-
}, schemas)
|
101
|
+
}, schemas),
|
94
102
|
);
|
95
103
|
}
|
96
104
|
}}
|
@@ -106,7 +114,7 @@ const SelectableSortableContainer = (
|
|
106
114
|
newSchemas.splice(
|
107
115
|
overIndex + 1,
|
108
116
|
0,
|
109
|
-
...selectedSchemas.filter((item) => item.id !== activeId)
|
117
|
+
...selectedSchemas.filter((item) => item.id !== activeId),
|
110
118
|
);
|
111
119
|
onSortEnd(newSchemas);
|
112
120
|
setSelectedSchemas([]);
|
@@ -133,8 +141,9 @@ const SelectableSortableContainer = (
|
|
133
141
|
<SelectableSortableItem
|
134
142
|
key={schema.id}
|
135
143
|
style={{
|
136
|
-
border: `1px solid ${
|
137
|
-
|
144
|
+
border: `1px solid ${
|
145
|
+
schema.id === hoveringSchemaId ? token.colorPrimary : 'transparent'
|
146
|
+
}`,
|
138
147
|
}}
|
139
148
|
schema={schema}
|
140
149
|
schemas={schemas}
|
@@ -150,43 +159,43 @@ const SelectableSortableContainer = (
|
|
150
159
|
</div>
|
151
160
|
{createPortal(
|
152
161
|
<DragOverlay adjustScale>
|
153
|
-
{activeId
|
154
|
-
(() => {
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
162
|
+
{activeId
|
163
|
+
? (() => {
|
164
|
+
const activeSchema = schemas.find((schema) => schema.id === activeId);
|
165
|
+
if (!activeSchema) return null;
|
166
|
+
return (
|
167
|
+
<>
|
168
|
+
<ul style={{ margin: 0, padding: 0, listStyle: 'none' }}>
|
169
|
+
<Item
|
170
|
+
icon={getPluginIcon(activeId)}
|
171
|
+
value={activeSchema.name}
|
172
|
+
required={activeSchema.required}
|
173
|
+
readOnly={activeSchema.readOnly}
|
174
|
+
style={{ background: token.colorPrimary }}
|
175
|
+
dragOverlay
|
176
|
+
/>
|
177
|
+
</ul>
|
178
|
+
<ul style={{ margin: 0, padding: 0, listStyle: 'none' }}>
|
179
|
+
{selectedSchemas
|
180
|
+
.filter((item) => item.id !== activeId)
|
181
|
+
.map((item) => (
|
182
|
+
<Item
|
183
|
+
icon={getPluginIcon(item)}
|
184
|
+
key={item.id}
|
185
|
+
value={item.name}
|
186
|
+
required={item.required}
|
187
|
+
readOnly={item.readOnly}
|
188
|
+
style={{ background: token.colorPrimary }}
|
189
|
+
dragOverlay
|
190
|
+
/>
|
191
|
+
))}
|
192
|
+
</ul>
|
193
|
+
</>
|
194
|
+
);
|
195
|
+
})()
|
196
|
+
: null}
|
188
197
|
</DragOverlay>,
|
189
|
-
document.body
|
198
|
+
document.body,
|
190
199
|
)}
|
191
200
|
</>
|
192
201
|
</DndContext>
|
@@ -5,7 +5,7 @@ import { PluginsRegistry, I18nContext } from '../../../../contexts.js';
|
|
5
5
|
import Item from './Item.js';
|
6
6
|
import { useMountStatus } from '../../../../hooks.js';
|
7
7
|
import { theme } from 'antd';
|
8
|
-
import PluginIcon from
|
8
|
+
import PluginIcon from '../../PluginIcon.js';
|
9
9
|
|
10
10
|
interface Props {
|
11
11
|
isSelected: boolean;
|
@@ -43,10 +43,9 @@ const SelectableSortableItem = ({
|
|
43
43
|
};
|
44
44
|
|
45
45
|
const [pluginLabel, thisPlugin] = Object.entries(pluginsRegistry).find(
|
46
|
-
([label, plugin]) => plugin?.propPanel.defaultSchema.type === schema.type
|
46
|
+
([label, plugin]) => plugin?.propPanel.defaultSchema.type === schema.type,
|
47
47
|
)!;
|
48
48
|
|
49
|
-
|
50
49
|
let status: undefined | 'is-warning' | 'is-danger';
|
51
50
|
if (!schema.name) {
|
52
51
|
status = 'is-warning';
|
@@ -21,7 +21,7 @@ const ListView = (
|
|
21
21
|
| 'hoveringSchemaId'
|
22
22
|
| 'onChangeHoveringSchemaId'
|
23
23
|
| 'changeSchemas'
|
24
|
-
|
24
|
+
>,
|
25
25
|
) => {
|
26
26
|
const {
|
27
27
|
schemas,
|
@@ -48,7 +48,7 @@ const ListView = (
|
|
48
48
|
key: 'name',
|
49
49
|
value,
|
50
50
|
schemaId: schemas[index].id,
|
51
|
-
}))
|
51
|
+
})),
|
52
52
|
);
|
53
53
|
setIsBulkUpdateFieldNamesMode(false);
|
54
54
|
}
|
@@ -89,7 +89,14 @@ const ListView = (
|
|
89
89
|
onEdit={onEdit}
|
90
90
|
/>
|
91
91
|
)}
|
92
|
-
<div
|
92
|
+
<div
|
93
|
+
style={{
|
94
|
+
paddingTop: '0.5rem',
|
95
|
+
display: 'flex',
|
96
|
+
alignItems: 'center',
|
97
|
+
justifyContent: 'flex-end',
|
98
|
+
}}
|
99
|
+
>
|
93
100
|
{isBulkUpdateFieldNamesMode ? (
|
94
101
|
<>
|
95
102
|
<Button size="small" type="text" onClick={commitBulk}>
|
@@ -40,7 +40,7 @@ const scaleDragPosAdjustment = (adjustment: number, scale: number): number => {
|
|
40
40
|
if (scale > 1) return adjustment * (scale - 1);
|
41
41
|
if (scale < 1) return adjustment * -(1 - scale);
|
42
42
|
return 0;
|
43
|
-
}
|
43
|
+
};
|
44
44
|
|
45
45
|
const TemplateEditor = ({
|
46
46
|
template,
|
@@ -53,8 +53,8 @@ const TemplateEditor = ({
|
|
53
53
|
onSaveTemplate: (t: Template) => void;
|
54
54
|
onChangeTemplate: (t: Template) => void;
|
55
55
|
} & {
|
56
|
-
onChangeTemplate: (t: Template) => void
|
57
|
-
onPageCursorChange: (newPageCursor: number) => void
|
56
|
+
onChangeTemplate: (t: Template) => void;
|
57
|
+
onPageCursorChange: (newPageCursor: number) => void;
|
58
58
|
}) => {
|
59
59
|
const past = useRef<SchemaForUI[][]>([]);
|
60
60
|
const future = useRef<SchemaForUI[][]>([]);
|
@@ -74,8 +74,12 @@ const TemplateEditor = ({
|
|
74
74
|
const [sidebarOpen, setSidebarOpen] = useState(true);
|
75
75
|
const [prevTemplate, setPrevTemplate] = useState<Template | null>(null);
|
76
76
|
|
77
|
-
const { backgrounds, pageSizes, scale, error, refresh } =
|
78
|
-
|
77
|
+
const { backgrounds, pageSizes, scale, error, refresh } = useUIPreProcessor({
|
78
|
+
template,
|
79
|
+
size,
|
80
|
+
zoomLevel,
|
81
|
+
maxZoom,
|
82
|
+
});
|
79
83
|
|
80
84
|
const onEdit = (targets: HTMLElement[]) => {
|
81
85
|
setActiveElements(targets);
|
@@ -94,7 +98,7 @@ const TemplateEditor = ({
|
|
94
98
|
pageCursor,
|
95
99
|
onChangePageCursor: (p) => {
|
96
100
|
setPageCursor(p);
|
97
|
-
onPageCursorChange(p)
|
101
|
+
onPageCursorChange(p);
|
98
102
|
onEditEnd();
|
99
103
|
},
|
100
104
|
});
|
@@ -108,7 +112,7 @@ const TemplateEditor = ({
|
|
108
112
|
setSchemasList(_schemasList);
|
109
113
|
onChangeTemplate(schemasList2template(_schemasList, template.basePdf));
|
110
114
|
},
|
111
|
-
[template, schemasList, pageCursor, onChangeTemplate]
|
115
|
+
[template, schemasList, pageCursor, onChangeTemplate],
|
112
116
|
);
|
113
117
|
|
114
118
|
const removeSchemas = useCallback(
|
@@ -116,7 +120,7 @@ const TemplateEditor = ({
|
|
116
120
|
commitSchemas(schemasList[pageCursor].filter((schema) => !ids.includes(schema.id)));
|
117
121
|
onEditEnd();
|
118
122
|
},
|
119
|
-
[schemasList, pageCursor, commitSchemas]
|
123
|
+
[schemasList, pageCursor, commitSchemas],
|
120
124
|
);
|
121
125
|
|
122
126
|
const changeSchemas: ChangeSchemas = useCallback(
|
@@ -130,7 +134,7 @@ const TemplateEditor = ({
|
|
130
134
|
commitSchemas,
|
131
135
|
});
|
132
136
|
},
|
133
|
-
[commitSchemas, pageCursor, schemasList, pluginsRegistry, pageSizes, template.basePdf]
|
137
|
+
[commitSchemas, pageCursor, schemasList, pluginsRegistry, pageSizes, template.basePdf],
|
134
138
|
);
|
135
139
|
|
136
140
|
useInitEvents({
|
@@ -161,29 +165,42 @@ const TemplateEditor = ({
|
|
161
165
|
}, []);
|
162
166
|
|
163
167
|
const addSchema = (defaultSchema: Schema) => {
|
164
|
-
const [paddingTop, paddingRight, paddingBottom, paddingLeft] = isBlankPdf(template.basePdf)
|
168
|
+
const [paddingTop, paddingRight, paddingBottom, paddingLeft] = isBlankPdf(template.basePdf)
|
169
|
+
? template.basePdf.padding
|
170
|
+
: [0, 0, 0, 0];
|
165
171
|
const pageSize = pageSizes[pageCursor];
|
166
172
|
|
167
173
|
const newSchemaName = (prefix: string) => {
|
168
174
|
let index = schemasList.reduce((acc, page) => acc + page.length, 1);
|
169
175
|
let newName = prefix + index;
|
170
|
-
while (schemasList.some(page => page.find((s) => s.name === newName))) {
|
176
|
+
while (schemasList.some((page) => page.find((s) => s.name === newName))) {
|
171
177
|
index++;
|
172
178
|
newName = prefix + index;
|
173
179
|
}
|
174
180
|
return newName;
|
175
181
|
};
|
176
|
-
const ensureMiddleValue = (min: number, value: number, max: number) =>
|
182
|
+
const ensureMiddleValue = (min: number, value: number, max: number) =>
|
183
|
+
Math.min(Math.max(min, value), max);
|
177
184
|
|
178
185
|
const s = {
|
179
186
|
id: uuid(),
|
180
187
|
...defaultSchema,
|
181
188
|
name: newSchemaName(i18n('field')),
|
182
189
|
position: {
|
183
|
-
x: ensureMiddleValue(
|
184
|
-
|
190
|
+
x: ensureMiddleValue(
|
191
|
+
paddingLeft,
|
192
|
+
defaultSchema.position.x,
|
193
|
+
pageSize.width - paddingRight - defaultSchema.width,
|
194
|
+
),
|
195
|
+
y: ensureMiddleValue(
|
196
|
+
paddingTop,
|
197
|
+
defaultSchema.position.y,
|
198
|
+
pageSize.height - paddingBottom - defaultSchema.height,
|
199
|
+
),
|
185
200
|
},
|
186
|
-
required: defaultSchema.readOnly
|
201
|
+
required: defaultSchema.readOnly
|
202
|
+
? false
|
203
|
+
: options.requiredByDefault || defaultSchema.required || false,
|
187
204
|
} as SchemaForUI;
|
188
205
|
|
189
206
|
if (defaultSchema.position.y === 0) {
|
@@ -213,7 +230,8 @@ const TemplateEditor = ({
|
|
213
230
|
setTimeout(
|
214
231
|
() =>
|
215
232
|
canvasRef.current &&
|
216
|
-
((canvasRef.current.scrollTop = getPagesScrollTopByIndex(pageSizes, newPageCursor, scale)),
|
233
|
+
((canvasRef.current.scrollTop = getPagesScrollTopByIndex(pageSizes, newPageCursor, scale)),
|
234
|
+
0),
|
217
235
|
);
|
218
236
|
};
|
219
237
|
|
@@ -262,13 +280,17 @@ const TemplateEditor = ({
|
|
262
280
|
const dragStartLeft = active.rect.current.initial?.left || 0;
|
263
281
|
const dragStartTop = active.rect.current.initial?.top || 0;
|
264
282
|
|
265
|
-
const canvasLeftOffsetFromPageCorner =
|
283
|
+
const canvasLeftOffsetFromPageCorner =
|
284
|
+
pageRect.left - dragStartLeft + scaleDragPosAdjustment(20, scale);
|
266
285
|
const canvasTopOffsetFromPageCorner = pageRect.top - dragStartTop;
|
267
286
|
|
268
287
|
const moveY = (event.delta.y - canvasTopOffsetFromPageCorner) / scale;
|
269
288
|
const moveX = (event.delta.x - canvasLeftOffsetFromPageCorner) / scale;
|
270
289
|
|
271
|
-
const position = {
|
290
|
+
const position = {
|
291
|
+
x: round(px2mm(Math.max(0, moveX)), 2),
|
292
|
+
y: round(px2mm(Math.max(0, moveY)), 2),
|
293
|
+
};
|
272
294
|
|
273
295
|
addSchema({ ...(active.data.current as Schema), position });
|
274
296
|
}}
|
@@ -307,7 +329,7 @@ const TemplateEditor = ({
|
|
307
329
|
schemas={schemasList[pageCursor] ?? []}
|
308
330
|
changeSchemas={changeSchemas}
|
309
331
|
onSortEnd={onSortEnd}
|
310
|
-
onEdit={id => {
|
332
|
+
onEdit={(id) => {
|
311
333
|
const editingElem = document.getElementById(id);
|
312
334
|
editingElem && onEdit([editingElem]);
|
313
335
|
}}
|
@@ -1,5 +1,12 @@
|
|
1
1
|
import React, { useRef, useState, useEffect, useContext } from 'react';
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
Template,
|
4
|
+
SchemaForUI,
|
5
|
+
PreviewProps,
|
6
|
+
Size,
|
7
|
+
getDynamicTemplate,
|
8
|
+
replacePlaceholders,
|
9
|
+
} from '@pdfme/common';
|
3
10
|
import { getDynamicHeightsForTable } from '@pdfme/schemas/utils';
|
4
11
|
import UnitPager from './UnitPager.js';
|
5
12
|
import Root from './Root.js';
|
@@ -37,8 +44,12 @@ const Preview = ({
|
|
37
44
|
const [zoomLevel, setZoomLevel] = useState(1);
|
38
45
|
const [schemasList, setSchemasList] = useState<SchemaForUI[][]>([[]] as SchemaForUI[][]);
|
39
46
|
|
40
|
-
const { backgrounds, pageSizes, scale, error, refresh } =
|
41
|
-
|
47
|
+
const { backgrounds, pageSizes, scale, error, refresh } = useUIPreProcessor({
|
48
|
+
template,
|
49
|
+
size,
|
50
|
+
zoomLevel,
|
51
|
+
maxZoom,
|
52
|
+
});
|
42
53
|
|
43
54
|
const isForm = Boolean(onChangeInput);
|
44
55
|
|
@@ -87,7 +98,7 @@ const Preview = ({
|
|
87
98
|
const handleChangeInput = ({ name, value }: { name: string; value: string }) =>
|
88
99
|
onChangeInput && onChangeInput({ index: unitCursor, name, value });
|
89
100
|
|
90
|
-
const handleOnChangeRenderer = (args: { key: string; value: any
|
101
|
+
const handleOnChangeRenderer = (args: { key: string; value: any }[], schema: SchemaForUI) => {
|
91
102
|
let isNeedInit = false;
|
92
103
|
args.forEach(({ key: _key, value }) => {
|
93
104
|
if (_key === 'content') {
|
@@ -98,9 +109,7 @@ const Preview = ({
|
|
98
109
|
// TODO Improve this to allow schema types to determine whether the execution of getDynamicTemplate is required.
|
99
110
|
if (schema.type === 'table') isNeedInit = true;
|
100
111
|
} else {
|
101
|
-
const targetSchema = schemasList[pageCursor].find(
|
102
|
-
(s) => s.id === schema.id
|
103
|
-
) as SchemaForUI;
|
112
|
+
const targetSchema = schemasList[pageCursor].find((s) => s.id === schema.id) as SchemaForUI;
|
104
113
|
if (!targetSchema) return;
|
105
114
|
|
106
115
|
// @ts-ignore
|
@@ -110,8 +119,8 @@ const Preview = ({
|
|
110
119
|
if (isNeedInit) {
|
111
120
|
init(template);
|
112
121
|
}
|
113
|
-
setSchemasList([...schemasList])
|
114
|
-
}
|
122
|
+
setSchemasList([...schemasList]);
|
123
|
+
};
|
115
124
|
|
116
125
|
if (error) {
|
117
126
|
return <ErrorScreen size={size} error={error} />;
|
@@ -146,11 +155,13 @@ const Preview = ({
|
|
146
155
|
pageSizes={pageSizes}
|
147
156
|
backgrounds={backgrounds}
|
148
157
|
renderSchema={({ schema, index }) => {
|
149
|
-
const value = schema.readOnly
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
158
|
+
const value = schema.readOnly
|
159
|
+
? replacePlaceholders({
|
160
|
+
content: schema.content || '',
|
161
|
+
variables: { ...input, totalPages: schemasList.length, currentPage: index + 1 },
|
162
|
+
schemas: schemasList,
|
163
|
+
})
|
164
|
+
: String((input && input[schema.name]) || '');
|
154
165
|
return (
|
155
166
|
<Renderer
|
156
167
|
key={schema.id}
|