@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.
Files changed (64) hide show
  1. package/__mocks__/assetsTransformer.js +7 -0
  2. package/__mocks__/pdfjs-dist.js +15 -0
  3. package/dist/__vite-browser-external-jWVCDlBL.js +4 -0
  4. package/dist/index.js +1115 -3
  5. package/dist/path2d-polyfill.esm-yIGK7UQJ.js +214 -0
  6. package/dist/style.css +1 -0
  7. package/dist/types/class.d.ts +3 -3
  8. package/dist/types/components/AppContextProvider.d.ts +11 -0
  9. package/dist/types/components/{CtlBar/index.d.ts → CtlBar.d.ts} +2 -2
  10. package/dist/types/components/Designer/Canvas/Selecto.d.ts +3 -2
  11. package/dist/types/components/Designer/Sidebar/DetailView/AlignWidget.d.ts +1 -1
  12. package/dist/types/components/Designer/Sidebar/ListView/SelectableSortableContainer.d.ts +1 -1
  13. package/dist/types/components/Renderer.d.ts +1 -1
  14. package/dist/types/components/UnitPager.d.ts +1 -1
  15. package/dist/types/constants.d.ts +1 -0
  16. package/dist/types/contexts.d.ts +46 -4
  17. package/dist/types/helper.d.ts +2 -1
  18. package/dist/types/hooks.d.ts +19 -2
  19. package/dist/types/i18n.d.ts +3 -27
  20. package/dist/types/theme.d.ts +2 -0
  21. package/package.json +17 -11
  22. package/src/Designer.tsx +27 -53
  23. package/src/Form.tsx +22 -23
  24. package/src/Viewer.tsx +10 -11
  25. package/src/class.ts +5 -5
  26. package/src/components/AppContextProvider.tsx +63 -0
  27. package/src/components/CtlBar.tsx +125 -0
  28. package/src/components/Designer/Canvas/Guides.tsx +18 -23
  29. package/src/components/Designer/Canvas/Mask.tsx +2 -1
  30. package/src/components/Designer/Canvas/Moveable.tsx +60 -60
  31. package/src/components/Designer/Canvas/Selecto.tsx +33 -20
  32. package/src/components/Designer/Canvas/index.tsx +21 -15
  33. package/src/components/Designer/Sidebar/DetailView/AlignWidget.tsx +53 -89
  34. package/src/components/Designer/Sidebar/DetailView/index.tsx +41 -30
  35. package/src/components/Designer/Sidebar/ListView/Item.tsx +30 -19
  36. package/src/components/Designer/Sidebar/ListView/SelectableSortableContainer.tsx +9 -6
  37. package/src/components/Designer/Sidebar/ListView/SelectableSortableItem.tsx +4 -1
  38. package/src/components/Designer/Sidebar/ListView/index.tsx +76 -71
  39. package/src/components/Designer/Sidebar/index.tsx +25 -49
  40. package/src/components/Designer/index.tsx +24 -82
  41. package/src/components/ErrorScreen.tsx +13 -11
  42. package/src/components/Preview.tsx +5 -2
  43. package/src/components/Renderer.tsx +10 -6
  44. package/src/components/Root.tsx +2 -8
  45. package/src/components/Spinner.tsx +12 -31
  46. package/src/components/UnitPager.tsx +72 -55
  47. package/src/constants.ts +2 -0
  48. package/src/contexts.ts +4 -5
  49. package/src/helper.ts +8 -5
  50. package/src/hooks.ts +136 -3
  51. package/src/i18n.ts +168 -59
  52. package/src/theme.ts +20 -0
  53. package/tsconfig.json +35 -13
  54. package/vite.config.ts +27 -0
  55. package/dist/index.js.LICENSE.txt +0 -142
  56. package/dist/index.js.map +0 -1
  57. package/dist/types/components/CtlBar/Pager.d.ts +0 -8
  58. package/dist/types/components/CtlBar/Zoom.d.ts +0 -7
  59. package/dist/types/components/Divider.d.ts +0 -3
  60. package/src/components/CtlBar/Pager.tsx +0 -53
  61. package/src/components/CtlBar/Zoom.tsx +0 -56
  62. package/src/components/CtlBar/index.tsx +0 -46
  63. package/src/components/Divider.tsx +0 -7
  64. 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 { RULER_HEIGHT, SIDEBAR_WIDTH } from '../../../../constants';
3
+ import { SIDEBAR_WIDTH } from '../../../../constants';
4
4
  import { I18nContext } from '../../../../contexts';
5
- import Divider from '../../../Divider';
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 - RULER_HEIGHT - RULER_HEIGHT / 2 - 145;
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: 40, display: 'flex', alignItems: 'center' }}>
36
- <span style={{ textAlign: 'center', width: '100%', fontWeight: 'bold' }}>
64
+ <div style={{ height: headHeight, display: 'flex', alignItems: 'center' }}>
65
+ <Text strong style={{ textAlign: 'center', width: '100%' }}>
37
66
  {i18n('fieldsList')}
38
- </span>
67
+ </Text>
39
68
  </div>
40
- <Divider />
41
- {isBulkUpdateFieldNamesMode ? (
42
- <div>
43
- <textarea
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
- height: height - 5,
49
- width: SIDEBAR_WIDTH,
50
- fontSize: '1rem',
51
- lineHeight: '2.5rem',
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
- ></textarea>
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
- <u
104
- onClick={() => {
105
- setFieldNamesValue(schemas.map((s) => s.key).join('\n'));
106
- setIsBulkUpdateFieldNamesMode(true);
107
- }}
108
- >
109
- {i18n('bulkUpdateFieldName')}
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 { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
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
- <button
33
- type="button"
33
+ <Button
34
34
  style={{
35
35
  position: 'absolute',
36
- top: '1.0rem',
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
- {getActiveSchemas().length === 0 ? (
75
- <ListView {...props} />
76
- ) : (
77
- <DetailView {...props} activeSchema={getLastActiveSchema()} />
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
- width: '100%',
83
- left: 0,
84
- bottom: '1rem',
85
- paddingTop: '1rem',
71
+ bottom: '1.5rem',
72
+ marginTop: '1rem',
73
+ left: '50%',
74
+ transform: 'translateX(-50%)',
86
75
  }}
87
76
  >
88
- <div style={{ marginBottom: '1rem', borderBottom: '1px solid #e5e5e5' }} />
89
- <button
90
- type="button"
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 { ZOOM, Template, Schema, SchemaForUI, ChangeSchemas, DesignerProps, Size, Plugin } from '@pdfme/common';
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/index';
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
- const initEvents = useCallback(() => {
123
- const getActiveSchemas = () => {
124
- const ids = activeElements.map((ae) => ae.id);
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
- schemasList,
187
- ]);
188
-
189
- const destroyEvents = useCallback(() => {
190
- destroyShortCuts();
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
- alignItems: 'center',
15
+ flexDirection: 'column',
16
16
  justifyContent: 'center',
17
+ background: BACKGROUND_COLOR,
17
18
  ...size,
18
19
  }}
19
20
  >
20
- <span style={{ color: '#fff', textAlign: 'center' }}>
21
- <span style={{ fontSize: 'large', fontWeight: 'bold', borderBottom: '1px solid #fff' }}>
22
- ERROR: {i18n('errorOccurred')}
23
- </span>
24
- <br />
25
- <span style={{ fontSize: 'small' }}>*{error.message}</span>
26
- </span>
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/index';
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 ? '1px dashed #4af' : 'transparent'}
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), mode, options, scale]);
90
+ }, [JSON.stringify(schema), JSON.stringify(options), mode, scale]);
87
91
 
88
92
  return (
89
93
  <Wrapper {...props}>
@@ -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
- <style>
6
- {`
7
- @keyframes spin {
8
- 0% { transform: rotate(0deg) }
9
-
10
- 100% { transform: rotate(359deg) }
11
- }
12
- `}
13
- </style>
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;