@pdfme/ui 1.1.10 → 1.2.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/dist/index.js +1 -1
- package/dist/index.js.LICENSE.txt +10 -1
- package/dist/index.js.map +1 -1
- package/dist/types/class.d.ts +4 -0
- package/dist/types/components/Designer/Sidebar/index.d.ts +4 -1
- package/dist/types/components/Designer/index.d.ts +9 -1
- package/dist/types/components/Schemas/SchemaUI.d.ts +1 -1
- package/dist/types/components/Schemas/TextSchema.d.ts +4 -0
- package/dist/types/helper.d.ts +4 -0
- package/dist/types/index.d.ts +2 -2
- package/package.json +5 -2
- package/src/components/Designer/Main/Guides.tsx +1 -0
- package/src/components/Designer/Main/index.tsx +17 -3
- package/src/components/Designer/Sidebar/DetailView/ExampleInputEditor.tsx +5 -4
- package/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.tsx +15 -5
- package/src/components/Designer/Sidebar/DetailView/TextPropEditor.tsx +123 -18
- package/src/components/Designer/Sidebar/ListView/index.tsx +1 -0
- package/src/components/Designer/Sidebar/index.tsx +20 -2
- package/src/components/Designer/index.tsx +1 -1
- package/src/components/Preview.tsx +1 -1
- package/src/components/Schemas/SchemaUI.tsx +3 -3
- package/src/components/Schemas/TextSchema.tsx +18 -5
- package/src/helper.ts +17 -19
- package/src/hooks.ts +5 -6
- package/src/i18n.ts +34 -2
- package/src/index.ts +2 -2
- package/tsconfig.json +1 -1
package/dist/types/class.d.ts
CHANGED
@@ -26,6 +26,10 @@ export declare abstract class BaseUIClass {
|
|
26
26
|
fontName?: string | undefined;
|
27
27
|
fontColor?: string | undefined;
|
28
28
|
characterSpacing?: number | undefined;
|
29
|
+
dynamicFontSize?: {
|
30
|
+
max: number;
|
31
|
+
min: number;
|
32
|
+
} | undefined;
|
29
33
|
type: "text";
|
30
34
|
height: number;
|
31
35
|
width: number;
|
@@ -12,7 +12,10 @@ export declare type SidebarProps = {
|
|
12
12
|
onEditEnd: () => void;
|
13
13
|
changeSchemas: (objs: {
|
14
14
|
key: string;
|
15
|
-
value: string | number
|
15
|
+
value: undefined | string | number | {
|
16
|
+
min: number;
|
17
|
+
max: number;
|
18
|
+
};
|
16
19
|
schemaId: string;
|
17
20
|
}[]) => void;
|
18
21
|
addSchema: () => void;
|
@@ -6,7 +6,7 @@ declare const TemplateEditor: ({ template, size, onSaveTemplate, onChangeTemplat
|
|
6
6
|
subset?: boolean | undefined;
|
7
7
|
data: string | ArrayBuffer | Uint8Array;
|
8
8
|
}> | undefined;
|
9
|
-
lang?: "en" | "ja" | undefined;
|
9
|
+
lang?: "en" | "ja" | "ar" | undefined;
|
10
10
|
} | undefined;
|
11
11
|
template: {
|
12
12
|
columns?: string[] | undefined;
|
@@ -20,6 +20,10 @@ declare const TemplateEditor: ({ template, size, onSaveTemplate, onChangeTemplat
|
|
20
20
|
fontName?: string | undefined;
|
21
21
|
fontColor?: string | undefined;
|
22
22
|
characterSpacing?: number | undefined;
|
23
|
+
dynamicFontSize?: {
|
24
|
+
max: number;
|
25
|
+
min: number;
|
26
|
+
} | undefined;
|
23
27
|
type: "text";
|
24
28
|
height: number;
|
25
29
|
width: number;
|
@@ -64,6 +68,10 @@ declare const TemplateEditor: ({ template, size, onSaveTemplate, onChangeTemplat
|
|
64
68
|
fontName?: string | undefined;
|
65
69
|
fontColor?: string | undefined;
|
66
70
|
characterSpacing?: number | undefined;
|
71
|
+
dynamicFontSize?: {
|
72
|
+
max: number;
|
73
|
+
min: number;
|
74
|
+
} | undefined;
|
67
75
|
type: "text";
|
68
76
|
height: number;
|
69
77
|
width: number;
|
@@ -8,7 +8,7 @@ export interface SchemaUIProps {
|
|
8
8
|
placeholder?: string;
|
9
9
|
}
|
10
10
|
declare const _default: React.ForwardRefExoticComponent<SchemaUIProps & {
|
11
|
-
|
11
|
+
outline: string;
|
12
12
|
onChangeHoveringSchemaId?: ((id: string | null) => void) | undefined;
|
13
13
|
} & React.RefAttributes<HTMLTextAreaElement | HTMLInputElement>>;
|
14
14
|
export default _default;
|
@@ -10,6 +10,10 @@ declare const _default: React.ForwardRefExoticComponent<SchemaUIProps & {
|
|
10
10
|
fontName?: string | undefined;
|
11
11
|
fontColor?: string | undefined;
|
12
12
|
characterSpacing?: number | undefined;
|
13
|
+
dynamicFontSize?: {
|
14
|
+
max: number;
|
15
|
+
min: number;
|
16
|
+
} | undefined;
|
13
17
|
type: "text";
|
14
18
|
height: number;
|
15
19
|
width: number;
|
package/dist/types/helper.d.ts
CHANGED
@@ -35,6 +35,10 @@ export declare const templateSchemas2SchemasList: (_template: Template) => Promi
|
|
35
35
|
fontName?: string | undefined;
|
36
36
|
fontColor?: string | undefined;
|
37
37
|
characterSpacing?: number | undefined;
|
38
|
+
dynamicFontSize?: {
|
39
|
+
max: number;
|
40
|
+
min: number;
|
41
|
+
} | undefined;
|
38
42
|
type: "text";
|
39
43
|
data: string;
|
40
44
|
key: string;
|
package/dist/types/index.d.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import Designer from './Designer';
|
2
2
|
import Form from './Form';
|
3
3
|
import Viewer from './Viewer';
|
4
|
-
import { BLANK_PDF,
|
4
|
+
import { BLANK_PDF, DEFAULT_FONT_VALUE, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput } from '@pdfme/common';
|
5
5
|
import type { Lang, Size, Alignment, SchemaType, BarCodeType, TextSchema, ImageSchema, BarcodeSchema, Schema, SchemaForUI, Font, BasePdf, Template, CommonProps, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps } from '@pdfme/common';
|
6
|
-
export { Designer, Viewer, Form, BLANK_PDF,
|
6
|
+
export { Designer, Viewer, Form, BLANK_PDF, DEFAULT_FONT_VALUE, isTextSchema, isImageSchema, isBarcodeSchema, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, validateBarcodeInput, };
|
7
7
|
export type { Lang, Size, Alignment, SchemaType, BarCodeType, TextSchema, ImageSchema, BarcodeSchema, Schema, SchemaForUI, Font, BasePdf, Template, CommonProps, GeneratorOptions, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, };
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@pdfme/ui",
|
3
|
-
"version": "1.1
|
3
|
+
"version": "1.2.1",
|
4
4
|
"sideEffects": false,
|
5
5
|
"author": "hand-dot",
|
6
6
|
"license": "MIT",
|
@@ -41,7 +41,7 @@
|
|
41
41
|
"@dnd-kit/core": "^5.0.1",
|
42
42
|
"@dnd-kit/sortable": "^6.0.0",
|
43
43
|
"@heroicons/react": "^2.0.13",
|
44
|
-
"@pdfme/common": "
|
44
|
+
"@pdfme/common": "file:../common",
|
45
45
|
"@scena/react-guides": "^0.16.0",
|
46
46
|
"hotkeys-js": "^3.8.7",
|
47
47
|
"pdfjs-dist": "^2.12.313",
|
@@ -68,6 +68,9 @@
|
|
68
68
|
"setupFiles": [
|
69
69
|
"jest-canvas-mock"
|
70
70
|
],
|
71
|
+
"setupFilesAfterEnv": [
|
72
|
+
"./__tests__/test-helpers.js"
|
73
|
+
],
|
71
74
|
"moduleNameMapper": {
|
72
75
|
"\\.(png)$": "<rootDir>/../../assetsTransformer.js"
|
73
76
|
},
|
@@ -6,6 +6,7 @@ import React, {
|
|
6
6
|
useEffect,
|
7
7
|
forwardRef,
|
8
8
|
useCallback,
|
9
|
+
useContext,
|
9
10
|
} from 'react';
|
10
11
|
import { OnDrag, OnResize, OnClick } from 'react-moveable';
|
11
12
|
import { SchemaForUI, Size } from '@pdfme/common';
|
@@ -19,6 +20,7 @@ import Selecto from './Selecto';
|
|
19
20
|
import Moveable from './Moveable';
|
20
21
|
import Guides from './Guides';
|
21
22
|
import Mask from './Mask';
|
23
|
+
import { FontContext } from '../../../contexts';
|
22
24
|
|
23
25
|
const DELETE_BTN_ID = uuid();
|
24
26
|
const fmt4Num = (prop: string) => Number(prop.replace('px', ''));
|
@@ -97,6 +99,7 @@ const Main = (props: Props, ref: Ref<HTMLDivElement>) => {
|
|
97
99
|
const verticalGuides = useRef<GuidesInterface[]>([]);
|
98
100
|
const horizontalGuides = useRef<GuidesInterface[]>([]);
|
99
101
|
const moveable = useRef<any>(null);
|
102
|
+
const font = useContext(FontContext);
|
100
103
|
|
101
104
|
const [isPressShiftKey, setIsPressShiftKey] = useState(false);
|
102
105
|
const [editing, setEditing] = useState(false);
|
@@ -162,7 +165,7 @@ const Main = (props: Props, ref: Ref<HTMLDivElement>) => {
|
|
162
165
|
changeSchemas(flatten(arg));
|
163
166
|
};
|
164
167
|
|
165
|
-
const onResizeEnd = ({ target }: { target: HTMLElement | SVGElement }) => {
|
168
|
+
const onResizeEnd = async ({ target }: { target: HTMLElement | SVGElement }) => {
|
166
169
|
const { id, style } = target;
|
167
170
|
const { width, height, top, left } = style;
|
168
171
|
changeSchemas([
|
@@ -171,6 +174,15 @@ const Main = (props: Props, ref: Ref<HTMLDivElement>) => {
|
|
171
174
|
{ key: 'position.y', value: fmt(top), schemaId: id },
|
172
175
|
{ key: 'position.x', value: fmt(left), schemaId: id },
|
173
176
|
]);
|
177
|
+
|
178
|
+
const targetSchema = schemasList[pageCursor].find((schema) => schema.id === id);
|
179
|
+
|
180
|
+
if (!targetSchema) return;
|
181
|
+
|
182
|
+
targetSchema.width = fmt(width);
|
183
|
+
targetSchema.height = fmt(height);
|
184
|
+
targetSchema.position.y = fmt(top);
|
185
|
+
targetSchema.position.x = fmt(left);
|
174
186
|
};
|
175
187
|
|
176
188
|
const onResizeEnds = ({ targets }: { targets: (HTMLElement | SVGElement)[] }) => {
|
@@ -312,8 +324,10 @@ const Main = (props: Props, ref: Ref<HTMLDivElement>) => {
|
|
312
324
|
schema={schema}
|
313
325
|
onChangeHoveringSchemaId={onChangeHoveringSchemaId}
|
314
326
|
editable={editing && activeElements.map((ae) => ae.id).includes(schema.id)}
|
315
|
-
onChange={(value) =>
|
316
|
-
|
327
|
+
onChange={async (value) => {
|
328
|
+
changeSchemas([{ key: 'data', value, schemaId: schema.id }]);
|
329
|
+
}}
|
330
|
+
outline={hoveringSchemaId === schema.id ? '1px solid #18a0fb' : '1px dashed #4af'}
|
317
331
|
ref={inputRef}
|
318
332
|
/>
|
319
333
|
)}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React, { useContext } from 'react';
|
2
2
|
import { SchemaForUI } from '@pdfme/common';
|
3
3
|
import { readFiles } from '../../../../helper';
|
4
|
-
import { I18nContext } from '../../../../contexts';
|
4
|
+
import { FontContext, I18nContext } from '../../../../contexts';
|
5
5
|
import { SidebarProps } from '..';
|
6
6
|
import { XMarkIcon } from '@heroicons/react/24/outline';
|
7
7
|
|
@@ -10,6 +10,7 @@ const ExampleInputEditor = (
|
|
10
10
|
) => {
|
11
11
|
const { changeSchemas, activeSchema } = props;
|
12
12
|
const i18n = useContext(I18nContext);
|
13
|
+
const fontData = useContext(FontContext);
|
13
14
|
|
14
15
|
return (
|
15
16
|
<div>
|
@@ -64,9 +65,9 @@ const ExampleInputEditor = (
|
|
64
65
|
) : (
|
65
66
|
<textarea
|
66
67
|
rows={6}
|
67
|
-
onChange={(e) =>
|
68
|
-
changeSchemas([{ key: 'data', value: e.target.value, schemaId: activeSchema.id }])
|
69
|
-
}
|
68
|
+
onChange={async (e) => {
|
69
|
+
changeSchemas([{ key: 'data', value: e.target.value, schemaId: activeSchema.id }]);
|
70
|
+
}}
|
70
71
|
style={{
|
71
72
|
width: '100%',
|
72
73
|
border: '1px solid #767676',
|
@@ -1,7 +1,8 @@
|
|
1
|
-
import React, { CSSProperties } from 'react';
|
1
|
+
import React, { CSSProperties, useContext } from 'react';
|
2
2
|
import { SchemaForUI } from '@pdfme/common';
|
3
3
|
import { round } from '../../../../helper';
|
4
4
|
import { SidebarProps } from '../index';
|
5
|
+
import { FontContext } from '../../../../contexts';
|
5
6
|
|
6
7
|
const inputSetStyle: CSSProperties = { marginRight: '1rem', display: 'flex', alignItems: 'center' };
|
7
8
|
|
@@ -37,6 +38,7 @@ const PositionAndSizeEditor = (
|
|
37
38
|
activeSchema: SchemaForUI;
|
38
39
|
}
|
39
40
|
) => {
|
41
|
+
const font = useContext(FontContext);
|
40
42
|
const { changeSchemas, schemas, activeSchema, activeElements, pageSize } = props;
|
41
43
|
|
42
44
|
const align = (type: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom') => {
|
@@ -184,7 +186,7 @@ const PositionAndSizeEditor = (
|
|
184
186
|
];
|
185
187
|
|
186
188
|
return (
|
187
|
-
<
|
189
|
+
<section>
|
188
190
|
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '0.5rem' }}>
|
189
191
|
{layoutBtns.map((b) => (
|
190
192
|
<button key={b.id} title={b.id} onClick={b.action} style={buttonStyle}>
|
@@ -228,8 +230,12 @@ const PositionAndSizeEditor = (
|
|
228
230
|
</div>
|
229
231
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
230
232
|
<div style={inputSetStyle}>
|
231
|
-
<label style={{ width: 17 }}>
|
233
|
+
<label htmlFor="input-width" style={{ width: 17 }}>
|
234
|
+
W
|
235
|
+
</label>
|
232
236
|
<input
|
237
|
+
id="input-width"
|
238
|
+
name="input-width"
|
233
239
|
style={inputStyle}
|
234
240
|
type="number"
|
235
241
|
onChange={(e) => {
|
@@ -243,8 +249,12 @@ const PositionAndSizeEditor = (
|
|
243
249
|
<span style={{ fontSize: '0.6rem' }}>mm</span>
|
244
250
|
</div>
|
245
251
|
<div style={inputSetStyle}>
|
246
|
-
<label style={{ width: 17 }}>
|
252
|
+
<label htmlFor="input-height" style={{ width: 17 }}>
|
253
|
+
H
|
254
|
+
</label>
|
247
255
|
<input
|
256
|
+
id="input-height"
|
257
|
+
name="input-height"
|
248
258
|
style={inputStyle}
|
249
259
|
type="number"
|
250
260
|
onChange={(e) => {
|
@@ -258,7 +268,7 @@ const PositionAndSizeEditor = (
|
|
258
268
|
<span style={{ fontSize: '0.6rem' }}>mm</span>
|
259
269
|
</div>
|
260
270
|
</div>
|
261
|
-
</
|
271
|
+
</section>
|
262
272
|
);
|
263
273
|
};
|
264
274
|
|
@@ -24,14 +24,26 @@ const NumberInputSet = (props: {
|
|
24
24
|
width: string;
|
25
25
|
label: string;
|
26
26
|
value: number;
|
27
|
+
minNumber?: number;
|
28
|
+
maxNumber?: number;
|
27
29
|
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
28
30
|
}) => {
|
29
|
-
const { label, value, width, onChange } = props;
|
31
|
+
const { label, value, width, minNumber, maxNumber, onChange } = props;
|
32
|
+
const formattedLabel = label.replace(/\s/g, '');
|
30
33
|
|
31
34
|
return (
|
32
35
|
<div style={{ width }}>
|
33
|
-
<label>{label}</label>
|
34
|
-
<input
|
36
|
+
<label htmlFor={`input-${formattedLabel}`}>{label}</label>
|
37
|
+
<input
|
38
|
+
id={`input-${formattedLabel}`}
|
39
|
+
name={`input-${formattedLabel}`}
|
40
|
+
style={inputStyle}
|
41
|
+
onChange={onChange}
|
42
|
+
value={value}
|
43
|
+
type="number"
|
44
|
+
{...(minNumber && { min: minNumber })}
|
45
|
+
{...(maxNumber && { max: maxNumber })}
|
46
|
+
/>
|
35
47
|
</div>
|
36
48
|
);
|
37
49
|
};
|
@@ -43,12 +55,20 @@ const ColorInputSet = (props: {
|
|
43
55
|
onClear: () => void;
|
44
56
|
}) => {
|
45
57
|
const { label, value, onChange, onClear } = props;
|
58
|
+
const formattedLabel = label.replace(/\s/g, '');
|
46
59
|
|
47
60
|
return (
|
48
61
|
<div style={{ width: '45%' }}>
|
49
|
-
<label>{label}</label>
|
62
|
+
<label htmlFor={`input-${formattedLabel}`}>{label}</label>
|
50
63
|
<div style={{ display: 'flex' }}>
|
51
|
-
<input
|
64
|
+
<input
|
65
|
+
id={`input-${formattedLabel}`}
|
66
|
+
name={`input-${formattedLabel}`}
|
67
|
+
onChange={onChange}
|
68
|
+
value={value || '#ffffff'}
|
69
|
+
type="color"
|
70
|
+
style={inputStyle}
|
71
|
+
/>
|
52
72
|
<button
|
53
73
|
onClick={onClear}
|
54
74
|
style={{
|
@@ -75,11 +95,18 @@ const SelectSet = (props: {
|
|
75
95
|
onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
|
76
96
|
}) => {
|
77
97
|
const { label, value, options, onChange } = props;
|
98
|
+
const formattedLabel = label.replace(/\s/g, '');
|
78
99
|
|
79
100
|
return (
|
80
101
|
<div style={{ width: '45%' }}>
|
81
|
-
<label>{label}:</label>
|
82
|
-
<select
|
102
|
+
<label htmlFor={`select-${formattedLabel}`}>{label}:</label>
|
103
|
+
<select
|
104
|
+
id={`select-${formattedLabel}`}
|
105
|
+
name={`select-${formattedLabel}`}
|
106
|
+
style={selectStyle}
|
107
|
+
onChange={onChange}
|
108
|
+
value={value}
|
109
|
+
>
|
83
110
|
{options.map((o) => (
|
84
111
|
<option key={o} value={o}>
|
85
112
|
{o}
|
@@ -90,6 +117,29 @@ const SelectSet = (props: {
|
|
90
117
|
);
|
91
118
|
};
|
92
119
|
|
120
|
+
const CheckboxSet = (props: {
|
121
|
+
width: string;
|
122
|
+
label: string;
|
123
|
+
onChange: React.ChangeEventHandler<HTMLInputElement>;
|
124
|
+
checked: boolean | undefined;
|
125
|
+
}) => {
|
126
|
+
const { width, label, onChange, checked } = props;
|
127
|
+
|
128
|
+
return (
|
129
|
+
<label
|
130
|
+
style={{
|
131
|
+
display: 'flex',
|
132
|
+
alignItems: 'center',
|
133
|
+
gap: '5px',
|
134
|
+
width: `${width}`,
|
135
|
+
}}
|
136
|
+
>
|
137
|
+
<input type="checkbox" checked={checked} onChange={onChange} />
|
138
|
+
{label}
|
139
|
+
</label>
|
140
|
+
);
|
141
|
+
};
|
142
|
+
|
93
143
|
const TextPropEditor = (
|
94
144
|
props: Pick<SidebarProps, 'changeSchemas'> & { activeSchema: SchemaForUI }
|
95
145
|
) => {
|
@@ -101,7 +151,7 @@ const TextPropEditor = (
|
|
101
151
|
if (activeSchema.type !== 'text') return <></>;
|
102
152
|
|
103
153
|
return (
|
104
|
-
<
|
154
|
+
<section style={{ fontSize: '0.7rem' }}>
|
105
155
|
<div
|
106
156
|
style={{
|
107
157
|
display: 'flex',
|
@@ -115,7 +165,9 @@ const TextPropEditor = (
|
|
115
165
|
value={activeSchema.fontName ?? fallbackFontName}
|
116
166
|
options={Object.keys(font)}
|
117
167
|
onChange={(e) => {
|
118
|
-
changeSchemas([
|
168
|
+
changeSchemas([
|
169
|
+
{ key: 'fontName', value: e.target.value, schemaId: activeSchema.id, },
|
170
|
+
]);
|
119
171
|
}}
|
120
172
|
/>
|
121
173
|
|
@@ -140,11 +192,12 @@ const TextPropEditor = (
|
|
140
192
|
width="30%"
|
141
193
|
label={'FontSize(pt)'}
|
142
194
|
value={activeSchema.fontSize ?? DEFAULT_FONT_SIZE}
|
143
|
-
onChange={(e) =>
|
195
|
+
onChange={(e) => {
|
196
|
+
const currentFontSize = Number(e.target.value);
|
144
197
|
changeSchemas([
|
145
|
-
{ key: 'fontSize', value:
|
146
|
-
])
|
147
|
-
}
|
198
|
+
{ key: 'fontSize', value: currentFontSize, schemaId: activeSchema.id, },
|
199
|
+
]);
|
200
|
+
}}
|
148
201
|
/>
|
149
202
|
<NumberInputSet
|
150
203
|
width="30%"
|
@@ -161,12 +214,64 @@ const TextPropEditor = (
|
|
161
214
|
width="40%"
|
162
215
|
label={'CharacterSpacing(pt)'}
|
163
216
|
value={activeSchema.characterSpacing ?? DEFAULT_CHARACTER_SPACING}
|
164
|
-
onChange={(e) =>
|
217
|
+
onChange={async (e) => {
|
218
|
+
const currentCharacterSpacing = Number(e.target.value);
|
165
219
|
changeSchemas([
|
166
|
-
{ key: 'characterSpacing', value:
|
167
|
-
])
|
168
|
-
}
|
220
|
+
{ key: 'characterSpacing', value: currentCharacterSpacing, schemaId: activeSchema.id, },
|
221
|
+
]);
|
222
|
+
}}
|
223
|
+
/>
|
224
|
+
</div>
|
225
|
+
<div
|
226
|
+
style={{
|
227
|
+
display: 'flex',
|
228
|
+
alignItems: 'center',
|
229
|
+
justifyContent: 'space-between',
|
230
|
+
flexWrap: 'wrap',
|
231
|
+
marginBottom: '0.25rem',
|
232
|
+
}}
|
233
|
+
>
|
234
|
+
<CheckboxSet
|
235
|
+
width="100%"
|
236
|
+
label="Use dynamic font size"
|
237
|
+
checked={Boolean(activeSchema.dynamicFontSize)}
|
238
|
+
onChange={(e) => {
|
239
|
+
changeSchemas([
|
240
|
+
{
|
241
|
+
key: 'dynamicFontSize', value: e.target.checked ? {
|
242
|
+
min: activeSchema.fontSize || DEFAULT_FONT_SIZE,
|
243
|
+
max: activeSchema.fontSize || DEFAULT_FONT_SIZE,
|
244
|
+
} : undefined, schemaId: activeSchema.id,
|
245
|
+
},
|
246
|
+
]);
|
247
|
+
}}
|
169
248
|
/>
|
249
|
+
|
250
|
+
{activeSchema.dynamicFontSize && (
|
251
|
+
<>
|
252
|
+
<NumberInputSet
|
253
|
+
width="45%"
|
254
|
+
label={'FontSize Min(pt)'}
|
255
|
+
value={activeSchema.dynamicFontSize.min ?? Number(activeSchema.fontSize)}
|
256
|
+
minNumber={0}
|
257
|
+
maxNumber={activeSchema.fontSize}
|
258
|
+
onChange={(e) => {
|
259
|
+
changeSchemas([{ key: 'dynamicFontSize.min', value: Number(e.target.value), schemaId: activeSchema.id }])
|
260
|
+
|
261
|
+
}}
|
262
|
+
/>
|
263
|
+
|
264
|
+
<NumberInputSet
|
265
|
+
width="45%"
|
266
|
+
label={'FontSize Max(pt)'}
|
267
|
+
value={activeSchema.dynamicFontSize.max ?? Number(activeSchema.fontSize)}
|
268
|
+
minNumber={activeSchema.fontSize}
|
269
|
+
onChange={(e) => {
|
270
|
+
changeSchemas([{ key: 'dynamicFontSize.max', value: Number(e.target.value), schemaId: activeSchema.id }])
|
271
|
+
}}
|
272
|
+
/>
|
273
|
+
</>
|
274
|
+
)}
|
170
275
|
</div>
|
171
276
|
<div
|
172
277
|
style={{
|
@@ -202,7 +307,7 @@ const TextPropEditor = (
|
|
202
307
|
}
|
203
308
|
/>
|
204
309
|
</div>
|
205
|
-
</
|
310
|
+
</section>
|
206
311
|
);
|
207
312
|
};
|
208
313
|
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import React, { useState, useContext } from 'react';
|
2
2
|
import { SchemaForUI, Size } from '@pdfme/common';
|
3
3
|
import { RULER_HEIGHT, SIDEBAR_WIDTH } from '../../../constants';
|
4
|
-
import { I18nContext } from '../../../contexts';
|
4
|
+
import { I18nContext, FontContext } from '../../../contexts';
|
5
5
|
import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
|
6
6
|
import ListView from './ListView/index';
|
7
7
|
import DetailView from './DetailView/index';
|
8
|
+
import { getFallbackFontName } from '@pdfme/common';
|
8
9
|
|
9
10
|
export type SidebarProps = {
|
10
11
|
height: number;
|
@@ -17,7 +18,14 @@ export type SidebarProps = {
|
|
17
18
|
onSortEnd: (sortedSchemas: SchemaForUI[]) => void;
|
18
19
|
onEdit: (id: string) => void;
|
19
20
|
onEditEnd: () => void;
|
20
|
-
changeSchemas: (
|
21
|
+
changeSchemas: (
|
22
|
+
objs: {
|
23
|
+
key: string; value: undefined | string | number | {
|
24
|
+
min: number;
|
25
|
+
max: number;
|
26
|
+
}; schemaId: string
|
27
|
+
}[]
|
28
|
+
) => void;
|
21
29
|
addSchema: () => void;
|
22
30
|
};
|
23
31
|
|
@@ -25,10 +33,20 @@ const Sidebar = (props: SidebarProps) => {
|
|
25
33
|
const { height, size, activeElements, schemas, addSchema } = props;
|
26
34
|
|
27
35
|
const i18n = useContext(I18nContext);
|
36
|
+
const fonts = useContext(FontContext);
|
37
|
+
const fallbackFont = getFallbackFontName(fonts);
|
28
38
|
const [open, setOpen] = useState(true);
|
29
39
|
|
30
40
|
const getActiveSchemas = () => {
|
31
41
|
const ids = activeElements.map((ae) => ae.id);
|
42
|
+
const activeSchema = schemas.find((s) => ids.includes(s.id));
|
43
|
+
|
44
|
+
if (activeSchema?.type === 'text') {
|
45
|
+
if (!activeSchema.fontName) {
|
46
|
+
activeSchema.fontName = fallbackFont;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
32
50
|
return schemas.filter((s) => ids.includes(s.id));
|
33
51
|
};
|
34
52
|
|
@@ -90,7 +90,7 @@ const TemplateEditor = ({
|
|
90
90
|
);
|
91
91
|
|
92
92
|
const changeSchemas = useCallback(
|
93
|
-
(objs: { key: string; value: string | number; schemaId: string }[]) => {
|
93
|
+
(objs: { key: string; value: undefined | string | number | { min: number, max: number }; schemaId: string }[]) => {
|
94
94
|
const newSchemas = objs.reduce((acc, { key, value, schemaId }) => {
|
95
95
|
const tgt = acc.find((s) => s.id === schemaId)!;
|
96
96
|
// Assign to reference
|
@@ -103,7 +103,7 @@ const Preview = ({ template, inputs, size, onChangeInput }: PreviewReactProps) =
|
|
103
103
|
placeholder={template.sampledata ? template.sampledata[0][key] : ''}
|
104
104
|
tabIndex={index + 100}
|
105
105
|
onChange={(value) => handleChangeInput({ key, value })}
|
106
|
-
|
106
|
+
outline={editable ? '1px dashed #4af' : 'transparent'}
|
107
107
|
/>
|
108
108
|
);
|
109
109
|
}}
|
@@ -14,13 +14,13 @@ export interface SchemaUIProps {
|
|
14
14
|
}
|
15
15
|
|
16
16
|
type Props = SchemaUIProps & {
|
17
|
-
|
17
|
+
outline: string;
|
18
18
|
onChangeHoveringSchemaId?: (id: string | null) => void;
|
19
19
|
};
|
20
20
|
|
21
21
|
const Wrapper = ({
|
22
22
|
children,
|
23
|
-
|
23
|
+
outline,
|
24
24
|
onChangeHoveringSchemaId,
|
25
25
|
schema,
|
26
26
|
}: Props & { children: ReactNode }) => (
|
@@ -37,7 +37,7 @@ const Wrapper = ({
|
|
37
37
|
width: schema.width * ZOOM,
|
38
38
|
top: schema.position.y * ZOOM,
|
39
39
|
left: schema.position.x * ZOOM,
|
40
|
-
|
40
|
+
outline,
|
41
41
|
}}
|
42
42
|
>
|
43
43
|
{children}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { forwardRef, Ref } from 'react';
|
1
|
+
import React, { useContext, forwardRef, Ref, useState, useEffect } from 'react';
|
2
2
|
import {
|
3
3
|
DEFAULT_FONT_SIZE,
|
4
4
|
DEFAULT_ALIGNMENT,
|
@@ -6,9 +6,12 @@ import {
|
|
6
6
|
DEFAULT_CHARACTER_SPACING,
|
7
7
|
DEFAULT_FONT_COLOR,
|
8
8
|
TextSchema,
|
9
|
+
calculateDynamicFontSize,
|
9
10
|
} from '@pdfme/common';
|
10
11
|
import { SchemaUIProps } from './SchemaUI';
|
11
12
|
import { ZOOM } from '../../constants';
|
13
|
+
import { FontContext } from '../../contexts';
|
14
|
+
|
12
15
|
|
13
16
|
type Props = SchemaUIProps & { schema: TextSchema };
|
14
17
|
|
@@ -16,20 +19,30 @@ const TextSchemaUI = (
|
|
16
19
|
{ schema, editable, placeholder, tabIndex, onChange }: Props,
|
17
20
|
ref: Ref<HTMLTextAreaElement>
|
18
21
|
) => {
|
22
|
+
const font = useContext(FontContext);
|
23
|
+
|
24
|
+
|
25
|
+
const [dynamicFontSize, setDynamicFontSize] = useState<number | undefined>(undefined);
|
26
|
+
|
27
|
+
useEffect(() => {
|
28
|
+
if (schema.dynamicFontSize && schema.data) {
|
29
|
+
calculateDynamicFontSize({ textSchema: schema, font, input: schema.data }).then(setDynamicFontSize)
|
30
|
+
}
|
31
|
+
}, [schema.data, schema.width, schema.fontName, schema.dynamicFontSize, schema.dynamicFontSize?.max, schema.dynamicFontSize?.min, schema.characterSpacing, font]);
|
32
|
+
|
19
33
|
const style: React.CSSProperties = {
|
20
34
|
padding: 0,
|
21
35
|
resize: 'none',
|
22
36
|
position: 'absolute',
|
23
37
|
fontFamily: schema.fontName ? `'${schema.fontName}'` : 'inherit',
|
24
38
|
height: schema.height * ZOOM,
|
25
|
-
|
26
|
-
width: (schema.width + (schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING) * 0.75) * ZOOM,
|
39
|
+
width: schema.width * ZOOM,
|
27
40
|
textAlign: schema.alignment ?? DEFAULT_ALIGNMENT,
|
28
|
-
fontSize: `${schema.fontSize ?? DEFAULT_FONT_SIZE}pt`,
|
41
|
+
fontSize: `${dynamicFontSize ?? schema.fontSize ?? DEFAULT_FONT_SIZE}pt`,
|
29
42
|
letterSpacing: `${schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING}pt`,
|
30
43
|
lineHeight: `${schema.lineHeight ?? DEFAULT_LINE_HEIGHT}em`,
|
31
44
|
whiteSpace: 'pre-line',
|
32
|
-
wordBreak: 'break-
|
45
|
+
wordBreak: 'break-word',
|
33
46
|
border: 'none',
|
34
47
|
color: schema.fontColor ? schema.fontColor : DEFAULT_FONT_COLOR,
|
35
48
|
backgroundColor:
|