@pdfme/ui 3.0.1 → 3.1.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__mocks__/assetsTransformer.js +7 -0
- package/__mocks__/pdfjs-dist.js +15 -0
- package/dist/__vite-browser-external-jWVCDlBL.js +4 -0
- package/dist/index.js +1115 -3
- package/dist/path2d-polyfill.esm-yIGK7UQJ.js +214 -0
- package/dist/style.css +1 -0
- package/dist/types/class.d.ts +3 -3
- package/dist/types/components/AppContextProvider.d.ts +11 -0
- package/dist/types/components/{CtlBar/index.d.ts → CtlBar.d.ts} +2 -2
- package/dist/types/components/Designer/Canvas/Selecto.d.ts +3 -2
- package/dist/types/components/Designer/Sidebar/DetailView/AlignWidget.d.ts +1 -1
- package/dist/types/components/Designer/Sidebar/ListView/SelectableSortableContainer.d.ts +1 -1
- package/dist/types/components/Renderer.d.ts +1 -1
- package/dist/types/components/UnitPager.d.ts +1 -1
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/contexts.d.ts +46 -4
- package/dist/types/helper.d.ts +2 -1
- package/dist/types/hooks.d.ts +19 -2
- package/dist/types/i18n.d.ts +3 -27
- package/dist/types/theme.d.ts +2 -0
- package/package.json +17 -11
- package/src/Designer.tsx +27 -53
- package/src/Form.tsx +22 -23
- package/src/Viewer.tsx +10 -11
- package/src/class.ts +5 -5
- package/src/components/AppContextProvider.tsx +63 -0
- package/src/components/CtlBar.tsx +125 -0
- package/src/components/Designer/Canvas/Guides.tsx +18 -23
- package/src/components/Designer/Canvas/Mask.tsx +2 -1
- package/src/components/Designer/Canvas/Moveable.tsx +60 -60
- package/src/components/Designer/Canvas/Selecto.tsx +33 -20
- package/src/components/Designer/Canvas/index.tsx +21 -15
- package/src/components/Designer/Sidebar/DetailView/AlignWidget.tsx +53 -89
- package/src/components/Designer/Sidebar/DetailView/index.tsx +41 -30
- package/src/components/Designer/Sidebar/ListView/Item.tsx +30 -19
- package/src/components/Designer/Sidebar/ListView/SelectableSortableContainer.tsx +9 -6
- package/src/components/Designer/Sidebar/ListView/SelectableSortableItem.tsx +4 -1
- package/src/components/Designer/Sidebar/ListView/index.tsx +76 -71
- package/src/components/Designer/Sidebar/index.tsx +25 -49
- package/src/components/Designer/index.tsx +24 -82
- package/src/components/ErrorScreen.tsx +13 -11
- package/src/components/Preview.tsx +5 -2
- package/src/components/Renderer.tsx +10 -6
- package/src/components/Root.tsx +2 -8
- package/src/components/Spinner.tsx +12 -31
- package/src/components/UnitPager.tsx +72 -55
- package/src/constants.ts +2 -0
- package/src/contexts.ts +4 -5
- package/src/helper.ts +8 -5
- package/src/hooks.ts +136 -3
- package/src/i18n.ts +168 -59
- package/src/theme.ts +20 -0
- package/tsconfig.json +35 -13
- package/vite.config.ts +27 -0
- package/dist/index.js.LICENSE.txt +0 -142
- package/dist/index.js.map +0 -1
- package/dist/types/components/CtlBar/Pager.d.ts +0 -8
- package/dist/types/components/CtlBar/Zoom.d.ts +0 -7
- package/dist/types/components/Divider.d.ts +0 -3
- package/src/components/CtlBar/Pager.tsx +0 -53
- package/src/components/CtlBar/Zoom.tsx +0 -56
- package/src/components/CtlBar/index.tsx +0 -46
- package/src/components/Divider.tsx +0 -7
- package/webpack.config.js +0 -40
@@ -1,10 +1,16 @@
|
|
1
1
|
import React, { useContext, useState } from 'react';
|
2
2
|
import type { SidebarProps } from '../../../../types';
|
3
|
-
import {
|
3
|
+
import { SIDEBAR_WIDTH } from '../../../../constants';
|
4
4
|
import { I18nContext } from '../../../../contexts';
|
5
|
-
import
|
5
|
+
import { getSidebarContentHeight } from '../../../../helper';
|
6
|
+
import { theme, Input, Typography, Divider, Button } from 'antd';
|
6
7
|
import SelectableSortableContainer from './SelectableSortableContainer';
|
7
8
|
|
9
|
+
const { Text } = Typography;
|
10
|
+
const { TextArea } = Input;
|
11
|
+
|
12
|
+
const headHeight = 40;
|
13
|
+
|
8
14
|
const ListView = (
|
9
15
|
props: Pick<
|
10
16
|
SidebarProps,
|
@@ -26,89 +32,88 @@ const ListView = (
|
|
26
32
|
onChangeHoveringSchemaId,
|
27
33
|
changeSchemas,
|
28
34
|
} = props;
|
35
|
+
const { token } = theme.useToken();
|
29
36
|
const i18n = useContext(I18nContext);
|
30
37
|
const [isBulkUpdateFieldNamesMode, setIsBulkUpdateFieldNamesMode] = useState(false);
|
31
38
|
const [fieldNamesValue, setFieldNamesValue] = useState('');
|
32
|
-
const height = size.height
|
39
|
+
const height = getSidebarContentHeight(size.height);
|
40
|
+
|
41
|
+
const commitBulk = () => {
|
42
|
+
const names = fieldNamesValue.split('\n');
|
43
|
+
if (names.length !== schemas.length) {
|
44
|
+
alert(i18n('errorBulkUpdateFieldName'));
|
45
|
+
} else {
|
46
|
+
changeSchemas(
|
47
|
+
names.map((value, index) => ({
|
48
|
+
key: 'key',
|
49
|
+
value,
|
50
|
+
schemaId: schemas[index].id,
|
51
|
+
}))
|
52
|
+
);
|
53
|
+
setIsBulkUpdateFieldNamesMode(false);
|
54
|
+
}
|
55
|
+
};
|
56
|
+
|
57
|
+
const startBulk = () => {
|
58
|
+
setFieldNamesValue(schemas.map((s) => s.key).join('\n'));
|
59
|
+
setIsBulkUpdateFieldNamesMode(true);
|
60
|
+
};
|
61
|
+
|
33
62
|
return (
|
34
63
|
<div>
|
35
|
-
<div style={{ height:
|
36
|
-
<
|
64
|
+
<div style={{ height: headHeight, display: 'flex', alignItems: 'center' }}>
|
65
|
+
<Text strong style={{ textAlign: 'center', width: '100%' }}>
|
37
66
|
{i18n('fieldsList')}
|
38
|
-
</
|
67
|
+
</Text>
|
39
68
|
</div>
|
40
|
-
<Divider />
|
41
|
-
{
|
42
|
-
|
43
|
-
<
|
69
|
+
<Divider style={{ marginTop: token.marginXS, marginBottom: token.marginXS }} />
|
70
|
+
<div style={{ height: height - headHeight }}>
|
71
|
+
{isBulkUpdateFieldNamesMode ? (
|
72
|
+
<TextArea
|
44
73
|
wrap="off"
|
45
74
|
value={fieldNamesValue}
|
46
75
|
onChange={(e) => setFieldNamesValue(e.target.value)}
|
47
76
|
style={{
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
lineHeight: '2.
|
52
|
-
background: 'transparent',
|
53
|
-
margin: 0,
|
54
|
-
padding: '1rem',
|
55
|
-
boxSizing: 'border-box',
|
56
|
-
fontFamily: 'inherit',
|
77
|
+
paddingLeft: 30,
|
78
|
+
height: height - headHeight,
|
79
|
+
width: SIDEBAR_WIDTH - 35,
|
80
|
+
lineHeight: '2.75rem',
|
57
81
|
}}
|
58
|
-
|
59
|
-
</div>
|
60
|
-
) : (
|
61
|
-
<SelectableSortableContainer
|
62
|
-
height={height}
|
63
|
-
schemas={schemas}
|
64
|
-
hoveringSchemaId={hoveringSchemaId}
|
65
|
-
onChangeHoveringSchemaId={onChangeHoveringSchemaId}
|
66
|
-
onSortEnd={onSortEnd}
|
67
|
-
onEdit={onEdit}
|
68
|
-
/>
|
69
|
-
)}
|
70
|
-
<div
|
71
|
-
style={{
|
72
|
-
display: 'flex',
|
73
|
-
justifyContent: 'flex-end',
|
74
|
-
cursor: 'pointer',
|
75
|
-
fontSize: '0.75rem',
|
76
|
-
}}
|
77
|
-
>
|
78
|
-
{isBulkUpdateFieldNamesMode ? (
|
79
|
-
<>
|
80
|
-
<u
|
81
|
-
onClick={() => {
|
82
|
-
const names = fieldNamesValue.split('\n');
|
83
|
-
if (names.length !== schemas.length) {
|
84
|
-
alert(i18n('errorBulkUpdateFieldName'));
|
85
|
-
} else {
|
86
|
-
changeSchemas(
|
87
|
-
names.map((value, index) => ({
|
88
|
-
key: 'key',
|
89
|
-
value,
|
90
|
-
schemaId: schemas[index].id,
|
91
|
-
}))
|
92
|
-
);
|
93
|
-
setIsBulkUpdateFieldNamesMode(false);
|
94
|
-
}
|
95
|
-
}}
|
96
|
-
>
|
97
|
-
{i18n('commitBulkUpdateFieldName')}
|
98
|
-
</u>
|
99
|
-
<span style={{ margin: '0 1rem' }}>/</span>
|
100
|
-
<u onClick={() => setIsBulkUpdateFieldNamesMode(false)}>{i18n('cancel')}</u>
|
101
|
-
</>
|
82
|
+
/>
|
102
83
|
) : (
|
103
|
-
<
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
}
|
108
|
-
|
109
|
-
|
110
|
-
</u>
|
84
|
+
<SelectableSortableContainer
|
85
|
+
schemas={schemas}
|
86
|
+
hoveringSchemaId={hoveringSchemaId}
|
87
|
+
onChangeHoveringSchemaId={onChangeHoveringSchemaId}
|
88
|
+
onSortEnd={onSortEnd}
|
89
|
+
onEdit={onEdit}
|
90
|
+
/>
|
111
91
|
)}
|
92
|
+
<div
|
93
|
+
style={{
|
94
|
+
display: 'flex',
|
95
|
+
alignItems: 'center',
|
96
|
+
justifyContent: 'flex-end',
|
97
|
+
height: headHeight,
|
98
|
+
borderBottom: `1px solid ${token.colorSplit}`,
|
99
|
+
}}
|
100
|
+
>
|
101
|
+
{isBulkUpdateFieldNamesMode ? (
|
102
|
+
<>
|
103
|
+
<Button size="small" type="text" onClick={commitBulk}>
|
104
|
+
<u> {i18n('commitBulkUpdateFieldName')}</u>
|
105
|
+
</Button>
|
106
|
+
<span style={{ margin: '0 1rem' }}>/</span>
|
107
|
+
<Button size="small" type="text" onClick={() => setIsBulkUpdateFieldNamesMode(false)}>
|
108
|
+
<u> {i18n('cancel')}</u>
|
109
|
+
</Button>
|
110
|
+
</>
|
111
|
+
) : (
|
112
|
+
<Button size="small" type="text" onClick={startBulk}>
|
113
|
+
<u> {i18n('bulkUpdateFieldName')}</u>
|
114
|
+
</Button>
|
115
|
+
)}
|
116
|
+
</div>
|
112
117
|
</div>
|
113
118
|
</div>
|
114
119
|
);
|
@@ -1,14 +1,16 @@
|
|
1
1
|
import React, { useContext } from 'react';
|
2
|
+
import { theme, Button } from 'antd';
|
2
3
|
import type { SidebarProps } from '../../../types';
|
3
4
|
import { SIDEBAR_WIDTH } from '../../../constants';
|
4
5
|
import { I18nContext } from '../../../contexts';
|
5
|
-
import {
|
6
|
+
import { ArrowLeftOutlined, ArrowRightOutlined } from '@ant-design/icons';
|
6
7
|
import ListView from './ListView/index';
|
7
8
|
import DetailView from './DetailView/index';
|
8
9
|
|
9
10
|
const Sidebar = (props: SidebarProps) => {
|
10
11
|
const { sidebarOpen, setSidebarOpen, activeElements, schemas, addSchema } = props;
|
11
12
|
|
13
|
+
const { token } = theme.useToken();
|
12
14
|
const i18n = useContext(I18nContext);
|
13
15
|
const getActiveSchemas = () =>
|
14
16
|
schemas.filter((s) => activeElements.map((ae) => ae.id).includes(s.id));
|
@@ -25,33 +27,22 @@ const Sidebar = (props: SidebarProps) => {
|
|
25
27
|
zIndex: 1,
|
26
28
|
height: '100%',
|
27
29
|
width: sidebarOpen ? SIDEBAR_WIDTH : 0,
|
28
|
-
fontSize: '1rem',
|
29
30
|
}}
|
30
31
|
>
|
31
32
|
<div>
|
32
|
-
<
|
33
|
-
type="button"
|
33
|
+
<Button
|
34
34
|
style={{
|
35
35
|
position: 'absolute',
|
36
|
-
|
36
|
+
display: 'flex',
|
37
|
+
alignItems: 'center',
|
38
|
+
justifyContent: 'center',
|
39
|
+
top: '1rem',
|
37
40
|
right: '1rem',
|
38
41
|
zIndex: 100,
|
39
|
-
border: 'none',
|
40
|
-
borderRadius: 2,
|
41
|
-
padding: '0.5rem',
|
42
|
-
cursor: 'pointer',
|
43
|
-
background: '#eee',
|
44
|
-
width: 30,
|
45
|
-
height: 30,
|
46
42
|
}}
|
43
|
+
icon={sidebarOpen ? <ArrowRightOutlined /> : <ArrowLeftOutlined />}
|
47
44
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
48
|
-
|
49
|
-
{sidebarOpen ? (
|
50
|
-
<ArrowRightIcon width={15} height={15} />
|
51
|
-
) : (
|
52
|
-
<ArrowLeftIcon width={15} height={15} />
|
53
|
-
)}
|
54
|
-
</button>
|
45
|
+
/>
|
55
46
|
<div
|
56
47
|
style={{
|
57
48
|
width: SIDEBAR_WIDTH,
|
@@ -60,47 +51,32 @@ const Sidebar = (props: SidebarProps) => {
|
|
60
51
|
top: 0,
|
61
52
|
right: 0,
|
62
53
|
position: 'absolute',
|
63
|
-
background: '#fffffffa',
|
64
|
-
color: '#333',
|
65
|
-
border: '1px solid #eee',
|
66
54
|
padding: '0.7rem 1rem',
|
67
55
|
overflowY: 'auto',
|
68
56
|
fontFamily: "'Open Sans', sans-serif",
|
69
|
-
fontWeight: 400,
|
70
|
-
textAlign: 'left',
|
71
57
|
boxSizing: 'border-box',
|
58
|
+
background: token.colorBgLayout,
|
72
59
|
}}
|
73
60
|
>
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
61
|
+
<div>
|
62
|
+
{getActiveSchemas().length === 0 ? (
|
63
|
+
<ListView {...props} />
|
64
|
+
) : (
|
65
|
+
<DetailView {...props} activeSchema={getLastActiveSchema()} />
|
66
|
+
)}
|
67
|
+
</div>
|
79
68
|
<div
|
80
69
|
style={{
|
81
70
|
position: 'absolute',
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
71
|
+
bottom: '1.5rem',
|
72
|
+
marginTop: '1rem',
|
73
|
+
left: '50%',
|
74
|
+
transform: 'translateX(-50%)',
|
86
75
|
}}
|
87
76
|
>
|
88
|
-
<
|
89
|
-
|
90
|
-
|
91
|
-
style={{
|
92
|
-
padding: '0.5rem',
|
93
|
-
background: '#18a0fb',
|
94
|
-
border: 'none',
|
95
|
-
borderRadius: 2,
|
96
|
-
cursor: 'pointer',
|
97
|
-
margin: '0 auto',
|
98
|
-
display: 'block',
|
99
|
-
}}
|
100
|
-
onClick={addSchema}
|
101
|
-
>
|
102
|
-
<strong style={{ color: '#fff' }}>{i18n('addNewField')}</strong>
|
103
|
-
</button>
|
77
|
+
<Button type="primary" style={{ fontWeight: 600 }} onClick={addSchema}>
|
78
|
+
{i18n('addNewField')}
|
79
|
+
</Button>
|
104
80
|
</div>
|
105
81
|
</div>
|
106
82
|
</div>
|
@@ -1,25 +1,30 @@
|
|
1
1
|
import React, { useRef, useState, useEffect, useContext, useCallback } from 'react';
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
ZOOM,
|
4
|
+
Template,
|
5
|
+
Schema,
|
6
|
+
SchemaForUI,
|
7
|
+
ChangeSchemas,
|
8
|
+
DesignerProps,
|
9
|
+
Size,
|
10
|
+
Plugin,
|
11
|
+
} from '@pdfme/common';
|
3
12
|
import Sidebar from './Sidebar/index';
|
4
13
|
import Canvas from './Canvas/index';
|
5
14
|
import { RULER_HEIGHT, SIDEBAR_WIDTH } from '../../constants';
|
6
15
|
import { I18nContext, PluginsRegistry } from '../../contexts';
|
7
16
|
import {
|
17
|
+
fmtTemplate,
|
8
18
|
uuid,
|
9
19
|
set,
|
10
20
|
cloneDeep,
|
11
|
-
initShortCuts,
|
12
|
-
destroyShortCuts,
|
13
21
|
templateSchemas2SchemasList,
|
14
|
-
fmtTemplate,
|
15
|
-
getUniqSchemaKey,
|
16
|
-
moveCommandToChangeSchemasArg,
|
17
22
|
getPagesScrollTopByIndex,
|
18
23
|
} from '../../helper';
|
19
|
-
import { useUIPreProcessor, useScrollPageCursor } from '../../hooks';
|
24
|
+
import { useUIPreProcessor, useScrollPageCursor, useInitEvents } from '../../hooks';
|
20
25
|
import Root from '../Root';
|
21
26
|
import ErrorScreen from '../ErrorScreen';
|
22
|
-
import CtlBar from '../CtlBar
|
27
|
+
import CtlBar from '../CtlBar';
|
23
28
|
|
24
29
|
const TemplateEditor = ({
|
25
30
|
template,
|
@@ -30,7 +35,6 @@ const TemplateEditor = ({
|
|
30
35
|
onSaveTemplate: (t: Template) => void;
|
31
36
|
size: Size;
|
32
37
|
} & { onChangeTemplate: (t: Template) => void }) => {
|
33
|
-
const copiedSchemas = useRef<SchemaForUI[] | null>(null);
|
34
38
|
const past = useRef<SchemaForUI[][]>([]);
|
35
39
|
const future = useRef<SchemaForUI[][]>([]);
|
36
40
|
const mainRef = useRef<HTMLDivElement>(null);
|
@@ -69,8 +73,6 @@ const TemplateEditor = ({
|
|
69
73
|
},
|
70
74
|
});
|
71
75
|
|
72
|
-
const modifiedTemplate = fmtTemplate(template, schemasList);
|
73
|
-
|
74
76
|
const commitSchemas = useCallback(
|
75
77
|
(newSchemas: SchemaForUI[]) => {
|
76
78
|
future.current = [];
|
@@ -119,76 +121,22 @@ const TemplateEditor = ({
|
|
119
121
|
[commitSchemas, pageCursor, schemasList]
|
120
122
|
);
|
121
123
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
return schemasList[pageCursor].filter((s) => ids.includes(s.id));
|
127
|
-
};
|
128
|
-
const timeTravel = (mode: 'undo' | 'redo') => {
|
129
|
-
const isUndo = mode === 'undo';
|
130
|
-
const stack = isUndo ? past : future;
|
131
|
-
if (stack.current.length <= 0) return;
|
132
|
-
(isUndo ? future : past).current.push(cloneDeep(schemasList[pageCursor]));
|
133
|
-
const s = cloneDeep(schemasList);
|
134
|
-
s[pageCursor] = stack.current.pop()!;
|
135
|
-
setSchemasList(s);
|
136
|
-
};
|
137
|
-
initShortCuts({
|
138
|
-
move: (command, isShift) => {
|
139
|
-
const pageSize = pageSizes[pageCursor];
|
140
|
-
const activeSchemas = getActiveSchemas();
|
141
|
-
const arg = moveCommandToChangeSchemasArg({ command, activeSchemas, pageSize, isShift });
|
142
|
-
changeSchemas(arg);
|
143
|
-
},
|
144
|
-
|
145
|
-
copy: () => {
|
146
|
-
const activeSchemas = getActiveSchemas();
|
147
|
-
if (activeSchemas.length === 0) return;
|
148
|
-
copiedSchemas.current = activeSchemas;
|
149
|
-
},
|
150
|
-
paste: () => {
|
151
|
-
if (!copiedSchemas.current || copiedSchemas.current.length === 0) return;
|
152
|
-
const schema = schemasList[pageCursor];
|
153
|
-
const stackUniqSchemaKeys: string[] = [];
|
154
|
-
const pasteSchemas = copiedSchemas.current.map((cs) => {
|
155
|
-
const id = uuid();
|
156
|
-
const key = getUniqSchemaKey({ copiedSchemaKey: cs.key, schema, stackUniqSchemaKeys });
|
157
|
-
const { height, width, position: p } = cs;
|
158
|
-
const ps = pageSizes[pageCursor];
|
159
|
-
const position = {
|
160
|
-
x: p.x + 10 > ps.width - width ? ps.width - width : p.x + 10,
|
161
|
-
y: p.y + 10 > ps.height - height ? ps.height - height : p.y + 10,
|
162
|
-
};
|
163
|
-
|
164
|
-
return Object.assign(cloneDeep(cs), { id, key, position });
|
165
|
-
});
|
166
|
-
commitSchemas(schemasList[pageCursor].concat(pasteSchemas));
|
167
|
-
onEdit(pasteSchemas.map((s) => document.getElementById(s.id)!));
|
168
|
-
copiedSchemas.current = pasteSchemas;
|
169
|
-
},
|
170
|
-
redo: () => timeTravel('redo'),
|
171
|
-
undo: () => timeTravel('undo'),
|
172
|
-
save: () => onSaveTemplate && onSaveTemplate(modifiedTemplate),
|
173
|
-
remove: () => removeSchemas(getActiveSchemas().map((s) => s.id)),
|
174
|
-
esc: onEditEnd,
|
175
|
-
selectAll: () => onEdit(schemasList[pageCursor].map((s) => document.getElementById(s.id)!)),
|
176
|
-
});
|
177
|
-
}, [
|
124
|
+
useInitEvents({
|
125
|
+
pageCursor,
|
126
|
+
pageSizes,
|
178
127
|
activeElements,
|
128
|
+
template,
|
129
|
+
schemasList,
|
179
130
|
changeSchemas,
|
180
131
|
commitSchemas,
|
181
|
-
modifiedTemplate,
|
182
|
-
pageCursor,
|
183
|
-
pageSizes,
|
184
132
|
removeSchemas,
|
185
133
|
onSaveTemplate,
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
}
|
134
|
+
past,
|
135
|
+
future,
|
136
|
+
setSchemasList,
|
137
|
+
onEdit,
|
138
|
+
onEditEnd,
|
139
|
+
});
|
192
140
|
|
193
141
|
const updateTemplate = useCallback(async (newTemplate: Template) => {
|
194
142
|
const sl = await templateSchemas2SchemasList(newTemplate);
|
@@ -204,12 +152,6 @@ const TemplateEditor = ({
|
|
204
152
|
updateTemplate(template);
|
205
153
|
}, [template, updateTemplate]);
|
206
154
|
|
207
|
-
useEffect(() => {
|
208
|
-
initEvents();
|
209
|
-
|
210
|
-
return destroyEvents;
|
211
|
-
}, [initEvents, destroyEvents]);
|
212
|
-
|
213
155
|
const addSchema = () => {
|
214
156
|
const propPanel = (Object.values(pluginsRegistry)[0] as Plugin<Schema>)?.propPanel;
|
215
157
|
|
@@ -1,29 +1,31 @@
|
|
1
1
|
import React, { useContext } from 'react';
|
2
2
|
import { Size } from '@pdfme/common';
|
3
3
|
import { I18nContext } from '../contexts';
|
4
|
+
import { BACKGROUND_COLOR } from '../constants';
|
5
|
+
import { theme, Result } from 'antd';
|
4
6
|
|
5
7
|
const ErrorScreen = ({ size, error }: { size: Size; error: Error }) => {
|
6
8
|
const i18n = useContext(I18nContext);
|
9
|
+
const { token } = theme.useToken();
|
7
10
|
|
8
11
|
return (
|
9
12
|
<div
|
10
13
|
style={{
|
11
|
-
position: 'relative',
|
12
|
-
background: 'rgb(74, 74, 74)',
|
13
|
-
overflow: 'auto',
|
14
14
|
display: 'flex',
|
15
|
-
|
15
|
+
flexDirection: 'column',
|
16
16
|
justifyContent: 'center',
|
17
|
+
background: BACKGROUND_COLOR,
|
17
18
|
...size,
|
18
19
|
}}
|
19
20
|
>
|
20
|
-
<
|
21
|
-
<
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
<div style={{ width: 300, margin: '0 auto', background: token.colorBgLayout }}>
|
22
|
+
<Result
|
23
|
+
icon={null}
|
24
|
+
title="ERROR"
|
25
|
+
subTitle={i18n('errorOccurred')}
|
26
|
+
extra={<span>{error.message}</span>}
|
27
|
+
/>
|
28
|
+
</div>
|
27
29
|
</div>
|
28
30
|
);
|
29
31
|
};
|
@@ -3,11 +3,12 @@ import type { SchemaForUI, PreviewProps, Size } from '@pdfme/common';
|
|
3
3
|
import UnitPager from './UnitPager';
|
4
4
|
import Root from './Root';
|
5
5
|
import ErrorScreen from './ErrorScreen';
|
6
|
-
import CtlBar from './CtlBar
|
6
|
+
import CtlBar from './CtlBar';
|
7
7
|
import Paper from './Paper';
|
8
8
|
import Renderer from './Renderer';
|
9
9
|
import { useUIPreProcessor, useScrollPageCursor } from '../hooks';
|
10
10
|
import { templateSchemas2SchemasList, getPagesScrollTopByIndex } from '../helper';
|
11
|
+
import { theme } from 'antd';
|
11
12
|
|
12
13
|
const Preview = ({
|
13
14
|
template,
|
@@ -18,6 +19,8 @@ const Preview = ({
|
|
18
19
|
onChangeInput?: (args: { index: number; value: string; key: string }) => void;
|
19
20
|
size: Size;
|
20
21
|
}) => {
|
22
|
+
const { token } = theme.useToken();
|
23
|
+
|
21
24
|
const containerRef = useRef<HTMLDivElement>(null);
|
22
25
|
const paperRefs = useRef<HTMLDivElement[]>([]);
|
23
26
|
|
@@ -101,7 +104,7 @@ const Preview = ({
|
|
101
104
|
placeholder={template.sampledata?.[0]?.[key] ?? ''}
|
102
105
|
tabIndex={index + 100}
|
103
106
|
onChange={(value) => handleChangeInput({ key, value })}
|
104
|
-
outline={isForm ?
|
107
|
+
outline={isForm ? `1px dashed ${token.colorPrimary}` : 'transparent'}
|
105
108
|
scale={scale}
|
106
109
|
/>
|
107
110
|
);
|
@@ -1,11 +1,12 @@
|
|
1
1
|
import React, { useEffect, useContext, ReactNode, useRef } from 'react';
|
2
|
-
import { ZOOM, UIRenderProps, SchemaForUI, Schema } from '@pdfme/common';
|
2
|
+
import { Dict, ZOOM, UIRenderProps, SchemaForUI, Schema } from '@pdfme/common';
|
3
|
+
import { theme as antdTheme } from 'antd';
|
3
4
|
import { SELECTABLE_CLASSNAME } from '../constants';
|
4
|
-
import { PluginsRegistry, OptionsContext } from '../contexts';
|
5
|
+
import { PluginsRegistry, OptionsContext, I18nContext } from '../contexts';
|
5
6
|
|
6
7
|
type RendererProps = Omit<
|
7
8
|
UIRenderProps<Schema>,
|
8
|
-
'value' | 'schema' | 'onChange' | 'rootElement' | 'options'
|
9
|
+
'value' | 'schema' | 'onChange' | 'rootElement' | 'options' | 'theme' | 'i18n'
|
9
10
|
> & {
|
10
11
|
schema: SchemaForUI;
|
11
12
|
onChange: (value: string) => void;
|
@@ -44,6 +45,8 @@ const Wrapper = ({
|
|
44
45
|
const Renderer = (props: RendererProps) => {
|
45
46
|
const pluginsRegistry = useContext(PluginsRegistry);
|
46
47
|
const options = useContext(OptionsContext);
|
48
|
+
const i18n = useContext(I18nContext) as (key: keyof Dict | string) => string;
|
49
|
+
const { token: theme } = antdTheme.useToken();
|
47
50
|
|
48
51
|
const { schema, mode, onChange, stopEditing, tabIndex, placeholder, scale } = props;
|
49
52
|
|
@@ -51,10 +54,9 @@ const Renderer = (props: RendererProps) => {
|
|
51
54
|
|
52
55
|
useEffect(() => {
|
53
56
|
if (ref.current && schema.type) {
|
54
|
-
|
55
57
|
const render = Object.values(pluginsRegistry).find(
|
56
58
|
(plugin) => plugin?.propPanel.defaultSchema.type === schema.type
|
57
|
-
)?.ui
|
59
|
+
)?.ui;
|
58
60
|
|
59
61
|
if (!render) {
|
60
62
|
console.error(`[@pdfme/ui] Renderer for type ${schema.type} not found.
|
@@ -76,6 +78,8 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
|
|
76
78
|
tabIndex,
|
77
79
|
placeholder,
|
78
80
|
options,
|
81
|
+
theme,
|
82
|
+
i18n,
|
79
83
|
});
|
80
84
|
}
|
81
85
|
return () => {
|
@@ -83,7 +87,7 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
|
|
83
87
|
ref.current.innerHTML = '';
|
84
88
|
}
|
85
89
|
};
|
86
|
-
}, [JSON.stringify(schema),
|
90
|
+
}, [JSON.stringify(schema), JSON.stringify(options), mode, scale]);
|
87
91
|
|
88
92
|
return (
|
89
93
|
<Wrapper {...props}>
|
package/src/components/Root.tsx
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import React, { useContext, forwardRef, ReactNode, Ref, useEffect } from 'react';
|
2
2
|
import { Size } from '@pdfme/common';
|
3
3
|
import { FontContext } from '../contexts';
|
4
|
+
import { BACKGROUND_COLOR } from '../constants';
|
4
5
|
import Spinner from './Spinner';
|
5
6
|
|
6
7
|
type Props = { size: Size; scale: number; children: ReactNode };
|
@@ -30,14 +31,7 @@ const Root = ({ size, scale, children }: Props, ref: Ref<HTMLDivElement>) => {
|
|
30
31
|
}, [font]);
|
31
32
|
|
32
33
|
return (
|
33
|
-
<div
|
34
|
-
ref={ref}
|
35
|
-
style={{
|
36
|
-
position: 'relative',
|
37
|
-
background: 'rgb(74, 74, 74)',
|
38
|
-
...size,
|
39
|
-
}}
|
40
|
-
>
|
34
|
+
<div ref={ref} style={{ position: 'relative', background: BACKGROUND_COLOR, ...size }}>
|
41
35
|
<div style={{ margin: '0 auto', ...size }}>{scale === 0 ? <Spinner /> : children}</div>
|
42
36
|
</div>
|
43
37
|
);
|
@@ -1,37 +1,18 @@
|
|
1
1
|
import React from 'react';
|
2
|
+
import { LoadingOutlined } from '@ant-design/icons';
|
3
|
+
import { Spin } from 'antd';
|
2
4
|
|
3
5
|
const Spinner = () => (
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
<div
|
15
|
-
style={{
|
16
|
-
width: '100%',
|
17
|
-
height: '100%',
|
18
|
-
display: 'flex',
|
19
|
-
alignItems: 'center',
|
20
|
-
justifyContent: 'center',
|
21
|
-
}}
|
22
|
-
>
|
23
|
-
<div
|
24
|
-
style={{
|
25
|
-
width: 65,
|
26
|
-
height: 65,
|
27
|
-
borderRadius: '50%',
|
28
|
-
border: '4px solid',
|
29
|
-
borderColor: '#4285f4 rgba(0,0,0,0.1) rgba(0,0,0,0.1)',
|
30
|
-
animation: 'spin 1s ease infinite',
|
31
|
-
}}
|
32
|
-
></div>
|
33
|
-
</div>
|
34
|
-
</>
|
6
|
+
<Spin
|
7
|
+
style={{
|
8
|
+
width: '100%',
|
9
|
+
height: '100%',
|
10
|
+
display: 'flex',
|
11
|
+
alignItems: 'center',
|
12
|
+
justifyContent: 'center',
|
13
|
+
}}
|
14
|
+
indicator={<LoadingOutlined style={{ fontSize: 50 }} spin />}
|
15
|
+
/>
|
35
16
|
);
|
36
17
|
|
37
18
|
export default Spinner;
|