@pdfme/ui 2.1.0 → 2.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/README.md +7 -3
- package/dist/index.js +1 -1
- package/dist/index.js.LICENSE.txt +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/builtInRenderer.d.ts +3 -0
- package/dist/types/class.d.ts +10 -1
- package/dist/types/components/CtlBar/Pager.d.ts +3 -2
- package/dist/types/components/CtlBar/Zoom.d.ts +3 -2
- package/dist/types/components/CtlBar/index.d.ts +3 -2
- package/dist/types/components/Designer/Main/Guides.d.ts +2 -2
- package/dist/types/components/Designer/Main/Mask.d.ts +2 -1
- package/dist/types/components/Designer/Main/Moveable.d.ts +1 -1
- package/dist/types/components/Designer/Main/Selecto.d.ts +2 -1
- package/dist/types/components/Designer/Sidebar/DetailView/BarCodePropEditor.d.ts +7 -0
- package/dist/types/components/Designer/Sidebar/DetailView/ExampleInputEditor.d.ts +2 -1
- package/dist/types/components/Designer/Sidebar/DetailView/FormComponents/ColorInputSet.d.ts +9 -0
- package/dist/types/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.d.ts +2 -1
- package/dist/types/components/Designer/Sidebar/DetailView/TextPropEditor.d.ts +2 -1
- package/dist/types/components/Designer/Sidebar/DetailView/TypeAndKeyEditor.d.ts +2 -1
- package/dist/types/components/Designer/Sidebar/DetailView/index.d.ts +3 -2
- package/dist/types/components/Designer/Sidebar/ListView/SelectableSortableContainer.d.ts +2 -1
- package/dist/types/components/Designer/Sidebar/ListView/SelectableSortableItem.d.ts +1 -1
- package/dist/types/components/Designer/Sidebar/ListView/index.d.ts +2 -1
- package/dist/types/components/Designer/Sidebar/index.d.ts +4 -2
- package/dist/types/components/Designer/index.d.ts +11 -2
- package/dist/types/components/Divider.d.ts +2 -1
- package/dist/types/components/Error.d.ts +2 -1
- package/dist/types/components/Paper.d.ts +2 -2
- package/dist/types/components/Preview.d.ts +2 -1
- package/dist/types/components/Renderer.d.ts +4 -0
- package/dist/types/components/Root.d.ts +1 -1
- package/dist/types/components/Spinner.d.ts +2 -1
- package/dist/types/components/UnitPager.d.ts +3 -2
- package/dist/types/contexts.d.ts +3 -1
- package/dist/types/helper.d.ts +5 -0
- package/dist/types/hooks.d.ts +2 -2
- package/dist/types/i18n.d.ts +4 -1
- package/dist/types/renders/barcodes.d.ts +2 -0
- package/dist/types/renders/image.d.ts +2 -0
- package/dist/types/renders/text.d.ts +2 -0
- package/dist/types/types.d.ts +25 -0
- package/package.json +2 -1
- package/src/Designer.tsx +21 -17
- package/src/Form.tsx +18 -14
- package/src/Viewer.tsx +6 -2
- package/src/builtInRenderer.ts +14 -0
- package/src/class.ts +22 -2
- package/src/components/Designer/Main/index.tsx +4 -15
- package/src/components/Designer/Sidebar/DetailView/BarCodePropEditor.tsx +81 -0
- package/src/components/Designer/Sidebar/DetailView/ExampleInputEditor.tsx +1 -2
- package/src/components/Designer/Sidebar/DetailView/FormComponents/ColorInputSet.tsx +50 -0
- package/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.tsx +1 -3
- package/src/components/Designer/Sidebar/DetailView/TextPropEditor.tsx +189 -209
- package/src/components/Designer/Sidebar/DetailView/index.tsx +16 -8
- package/src/components/Designer/Sidebar/index.tsx +3 -2
- package/src/components/Designer/index.tsx +1 -0
- package/src/components/Preview.tsx +6 -6
- package/src/components/Renderer.tsx +80 -0
- package/src/contexts.ts +5 -0
- package/src/helper.ts +8 -0
- package/src/i18n.ts +44 -1
- package/src/renders/barcodes.ts +117 -0
- package/src/renders/image.ts +101 -0
- package/src/renders/text.ts +138 -0
- package/src/types.ts +28 -0
- package/dist/types/components/Schemas/BarcodeSchema.d.ts +0 -15
- package/dist/types/components/Schemas/ImageSchema.d.ts +0 -15
- package/dist/types/components/Schemas/SchemaUI.d.ts +0 -15
- package/dist/types/components/Schemas/TextSchema.d.ts +0 -27
- package/src/components/Schemas/BarcodeSchema.tsx +0 -124
- package/src/components/Schemas/ImageSchema.tsx +0 -87
- package/src/components/Schemas/SchemaUI.tsx +0 -62
- package/src/components/Schemas/TextSchema.tsx +0 -117
package/src/helper.ts
CHANGED
@@ -196,6 +196,14 @@ export const destroyShortCuts = () => {
|
|
196
196
|
hotkeys.unbind(keys.join());
|
197
197
|
};
|
198
198
|
|
199
|
+
export const blobToDataURL = (blob: Blob): Promise<string> => new Promise((resolve, reject) => {
|
200
|
+
const reader = new FileReader();
|
201
|
+
reader.onloadend = () => resolve(reader.result as string);
|
202
|
+
reader.onerror = reject;
|
203
|
+
reader.readAsDataURL(blob);
|
204
|
+
})
|
205
|
+
|
206
|
+
|
199
207
|
const readFile = (file: File | null, type: 'text' | 'dataURL' | 'arrayBuffer') => {
|
200
208
|
return new Promise<string | ArrayBuffer>((r) => {
|
201
209
|
const fileReader = new FileReader();
|
package/src/i18n.ts
CHANGED
@@ -23,6 +23,9 @@ const dictEn = {
|
|
23
23
|
'Cannot commit the change because the number of items has been changed.',
|
24
24
|
commitBulkUpdateFieldName: 'Commit Changes',
|
25
25
|
bulkUpdateFieldName: 'Bulk update field names',
|
26
|
+
barColor: 'Bar Color',
|
27
|
+
textColor: 'Text Color',
|
28
|
+
bgColor: 'Background Color',
|
26
29
|
};
|
27
30
|
|
28
31
|
const dictJa: { [key in keyof DictEn]: string } = {
|
@@ -45,6 +48,9 @@ const dictJa: { [key in keyof DictEn]: string } = {
|
|
45
48
|
errorBulkUpdateFieldName: '項目数が変更されているため変更をコミットできません。',
|
46
49
|
commitBulkUpdateFieldName: '変更を反映',
|
47
50
|
bulkUpdateFieldName: '項目名を一括変更',
|
51
|
+
barColor: 'バーの色',
|
52
|
+
textColor: 'テキストの色',
|
53
|
+
bgColor: '背景色',
|
48
54
|
};
|
49
55
|
|
50
56
|
const dictAr: { [key in keyof DictEn]: string } = {
|
@@ -67,6 +73,9 @@ const dictAr: { [key in keyof DictEn]: string } = {
|
|
67
73
|
errorBulkUpdateFieldName: 'لا يمكن تنفيذ التغيير لأنه تم تغيير عدد العناصر.',
|
68
74
|
commitBulkUpdateFieldName: 'تنفيذ التغييرات',
|
69
75
|
bulkUpdateFieldName: 'تغيير الأسماء',
|
76
|
+
barColor: 'لون الشريط',
|
77
|
+
textColor: 'لون الخط',
|
78
|
+
bgColor: 'لون الخلفية',
|
70
79
|
};
|
71
80
|
|
72
81
|
const dictTh: { [key in keyof DictEn]: string } = {
|
@@ -89,6 +98,34 @@ const dictTh: { [key in keyof DictEn]: string } = {
|
|
89
98
|
errorBulkUpdateFieldName: 'ไม่สามารถยืนยันการแก้ไขได้เนื่องจากจำนวนรายการมีการเปลี่ยนแปลง',
|
90
99
|
commitBulkUpdateFieldName: 'ยืนยันการแก้ไข',
|
91
100
|
bulkUpdateFieldName: 'แก้ไขชื่อฟิลด์เป็นชุด',
|
101
|
+
barColor: 'สีบาร์',
|
102
|
+
textColor: 'สีข้อความ',
|
103
|
+
bgColor: 'สีพื้นหลัง',
|
104
|
+
};
|
105
|
+
|
106
|
+
const dictIt: { [key in keyof DictEn]: string } = {
|
107
|
+
cancel: 'Annulla',
|
108
|
+
field: 'Campo',
|
109
|
+
fieldName: 'Nome',
|
110
|
+
require: 'Richiesto',
|
111
|
+
uniq: 'Univoco',
|
112
|
+
inputExample: 'Testo di esempio',
|
113
|
+
edit: 'Modifica',
|
114
|
+
plsInputName: 'Inserisci il nome per favore',
|
115
|
+
fieldMustUniq: 'Il nome del campo non è univoco',
|
116
|
+
notUniq: '(Nome non univoco)',
|
117
|
+
noKeyName: 'Nessun nome',
|
118
|
+
fieldsList: 'Lista campi',
|
119
|
+
addNewField: 'Aggiungi un campo',
|
120
|
+
editField: 'Modifica campo',
|
121
|
+
type: 'Tipo',
|
122
|
+
errorOccurred: 'Riscontrato errore',
|
123
|
+
errorBulkUpdateFieldName: 'Non è possibile salvare le modifiche perché il numero di elementi è cambiato.',
|
124
|
+
commitBulkUpdateFieldName: 'Salva cambiamenti',
|
125
|
+
bulkUpdateFieldName: 'Modifica nomi campi in blocco',
|
126
|
+
barColor: 'Colore barra',
|
127
|
+
textColor: 'Colore testo',
|
128
|
+
bgColor: 'Colore sfondo',
|
92
129
|
};
|
93
130
|
|
94
131
|
const dictPl: {[key in keyof DictEn]: string} = {
|
@@ -111,7 +148,10 @@ const dictPl: {[key in keyof DictEn]: string} = {
|
|
111
148
|
errorBulkUpdateFieldName:
|
112
149
|
'Nie można wprowadzić zmian ponieważ liczba elementów uległa zmianie.',
|
113
150
|
commitBulkUpdateFieldName: 'Zaakceptuj zmiany',
|
114
|
-
bulkUpdateFieldName: 'Masowo aktualizuj klucze pól',
|
151
|
+
bulkUpdateFieldName: 'Masowo aktualizuj klucze pól',
|
152
|
+
barColor: 'Kolor paska',
|
153
|
+
textColor: 'Kolor tekstu',
|
154
|
+
bgColor: 'Kolor tła',
|
115
155
|
}
|
116
156
|
|
117
157
|
const i18n = (lang: Lang, key: keyof DictEn) => {
|
@@ -127,6 +167,9 @@ const i18n = (lang: Lang, key: keyof DictEn) => {
|
|
127
167
|
case 'ja':
|
128
168
|
return dictJa[key];
|
129
169
|
|
170
|
+
case 'it':
|
171
|
+
return dictIt[key];
|
172
|
+
|
130
173
|
default:
|
131
174
|
return dictEn[key];
|
132
175
|
}
|
@@ -0,0 +1,117 @@
|
|
1
|
+
import type { RenderProps } from "../types"
|
2
|
+
import type * as CSS from 'csstype';
|
3
|
+
import { validateBarcodeInput, BarcodeSchema, createBarCode } from '@pdfme/common';
|
4
|
+
import { blobToDataURL } from '../helper';
|
5
|
+
|
6
|
+
const fullSize = { width: '100%', height: '100%' }
|
7
|
+
|
8
|
+
const createErrorBarcodeElm = () => {
|
9
|
+
const container = document.createElement('div');
|
10
|
+
const containerStyle: CSS.Properties = {
|
11
|
+
display: 'flex',
|
12
|
+
alignItems: 'center',
|
13
|
+
justifyContent: 'center',
|
14
|
+
...fullSize,
|
15
|
+
}
|
16
|
+
Object.assign(container.style, containerStyle);
|
17
|
+
|
18
|
+
const span = document.createElement('span');
|
19
|
+
const spanStyle: CSS.Properties = {
|
20
|
+
color: 'white',
|
21
|
+
background: 'red',
|
22
|
+
padding: '0.25rem',
|
23
|
+
fontSize: '12pt',
|
24
|
+
fontWeight: 'bold',
|
25
|
+
borderRadius: '2px',
|
26
|
+
}
|
27
|
+
Object.assign(span.style, spanStyle);
|
28
|
+
|
29
|
+
span.textContent = 'ERROR';
|
30
|
+
container.appendChild(span);
|
31
|
+
|
32
|
+
return container;
|
33
|
+
};
|
34
|
+
|
35
|
+
const createBarcodeImage = async (schema: BarcodeSchema, value: string) => {
|
36
|
+
const imageBuf = await createBarCode({ ...schema, input: value });
|
37
|
+
const barcodeData = new Blob([new Uint8Array(imageBuf)], { type: 'image/png' });
|
38
|
+
const barcodeDataURL = await blobToDataURL(barcodeData);
|
39
|
+
return barcodeDataURL;
|
40
|
+
}
|
41
|
+
|
42
|
+
const createBarcodeImageElm = async (schema: BarcodeSchema, value: string) => {
|
43
|
+
const barcodeDataURL = await createBarcodeImage(schema, value);
|
44
|
+
const img = document.createElement('img');
|
45
|
+
img.src = barcodeDataURL;
|
46
|
+
const imgStyle: CSS.Properties = { ...fullSize, borderRadius: 0 }
|
47
|
+
Object.assign(img.style, imgStyle)
|
48
|
+
return img;
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
export const renderBarcode = async (arg: RenderProps) => {
|
53
|
+
const {
|
54
|
+
value,
|
55
|
+
rootElement,
|
56
|
+
mode,
|
57
|
+
onChange,
|
58
|
+
stopEditing,
|
59
|
+
tabIndex,
|
60
|
+
placeholder,
|
61
|
+
} = arg;
|
62
|
+
const schema = arg.schema as BarcodeSchema;
|
63
|
+
|
64
|
+
const container = document.createElement('div');
|
65
|
+
const containerStyle: CSS.Properties = {
|
66
|
+
...fullSize,
|
67
|
+
display: 'flex',
|
68
|
+
alignItems: 'center',
|
69
|
+
justifyContent: 'center',
|
70
|
+
fontFamily: "'Open Sans', sans-serif",
|
71
|
+
|
72
|
+
}
|
73
|
+
Object.assign(container.style, containerStyle);
|
74
|
+
rootElement.appendChild(container);
|
75
|
+
const isForm = mode === 'form';
|
76
|
+
if (isForm) {
|
77
|
+
const input = document.createElement('input');
|
78
|
+
const inputStyle: CSS.Properties = {
|
79
|
+
...fullSize,
|
80
|
+
position: 'absolute',
|
81
|
+
textAlign: 'center',
|
82
|
+
fontSize: '1rem',
|
83
|
+
color: '#000',
|
84
|
+
backgroundColor: isForm || value ? 'rgb(242 244 255 / 75%)' : 'none',
|
85
|
+
border: 'none',
|
86
|
+
display: 'flex',
|
87
|
+
alignItems: 'center',
|
88
|
+
justifyContent: 'center',
|
89
|
+
overflow: 'auto',
|
90
|
+
|
91
|
+
};
|
92
|
+
Object.assign(input.style, inputStyle);
|
93
|
+
input.value = value;
|
94
|
+
input.placeholder = placeholder || "";
|
95
|
+
input.tabIndex = tabIndex || 0;
|
96
|
+
input.addEventListener('change', (e: Event) => {
|
97
|
+
onChange && onChange((e.target as HTMLInputElement).value);
|
98
|
+
});
|
99
|
+
input.addEventListener('blur', () => {
|
100
|
+
stopEditing && stopEditing();
|
101
|
+
});
|
102
|
+
container.appendChild(input);
|
103
|
+
input.setSelectionRange(value.length, value.length);
|
104
|
+
input.focus();
|
105
|
+
}
|
106
|
+
|
107
|
+
if (!value) return;
|
108
|
+
try {
|
109
|
+
if (!validateBarcodeInput(schema.type, value)) throw new Error('Invalid barcode input');
|
110
|
+
const imgElm = await createBarcodeImageElm(schema, value)
|
111
|
+
container.appendChild(imgElm);
|
112
|
+
} catch (err) {
|
113
|
+
console.error(err);
|
114
|
+
const errorBarcodeElm = createErrorBarcodeElm();
|
115
|
+
container.appendChild(errorBarcodeElm);
|
116
|
+
}
|
117
|
+
}
|
@@ -0,0 +1,101 @@
|
|
1
|
+
import type { ChangeEvent } from 'react';
|
2
|
+
import type * as CSS from 'csstype';
|
3
|
+
import { ImageSchema } from '@pdfme/common';
|
4
|
+
import type { RenderProps } from "../types"
|
5
|
+
import { ZOOM } from '../constants';
|
6
|
+
import { readFiles } from '../helper';
|
7
|
+
|
8
|
+
const fullSize = { width: '100%', height: '100%' }
|
9
|
+
export const renderImage = async (arg: RenderProps) => {
|
10
|
+
const {
|
11
|
+
value,
|
12
|
+
rootElement,
|
13
|
+
mode,
|
14
|
+
onChange,
|
15
|
+
stopEditing,
|
16
|
+
tabIndex,
|
17
|
+
placeholder,
|
18
|
+
} = arg;
|
19
|
+
const isForm = mode === 'form';
|
20
|
+
|
21
|
+
const schema = arg.schema as ImageSchema;
|
22
|
+
|
23
|
+
const size = { width: schema.width * ZOOM, height: schema.height * ZOOM };
|
24
|
+
|
25
|
+
const container = document.createElement('div');
|
26
|
+
const containerStyle: CSS.Properties = {
|
27
|
+
...fullSize,
|
28
|
+
backgroundImage: value ? 'none' : `url(${placeholder})`,
|
29
|
+
backgroundSize: `${size.width}px ${size.height}px`,
|
30
|
+
}
|
31
|
+
Object.assign(container.style, containerStyle);
|
32
|
+
container.addEventListener('click', (e) => {
|
33
|
+
if (isForm) {
|
34
|
+
e.stopPropagation();
|
35
|
+
}
|
36
|
+
});
|
37
|
+
rootElement.appendChild(container);
|
38
|
+
|
39
|
+
// image tag
|
40
|
+
if (value) {
|
41
|
+
const img = document.createElement('img');
|
42
|
+
const imgStyle: CSS.Properties = { height: '100%', width: '100%', borderRadius: 0 }
|
43
|
+
Object.assign(img.style, imgStyle);
|
44
|
+
img.src = value;
|
45
|
+
container.appendChild(img);
|
46
|
+
}
|
47
|
+
|
48
|
+
// remove button
|
49
|
+
if (value && isForm) {
|
50
|
+
const button = document.createElement('button');
|
51
|
+
button.textContent = 'x';
|
52
|
+
const buttonStyle: CSS.Properties = {
|
53
|
+
position: 'absolute',
|
54
|
+
top: 0,
|
55
|
+
left: 0,
|
56
|
+
zIndex: 1,
|
57
|
+
display: 'flex',
|
58
|
+
justifyContent: 'center',
|
59
|
+
alignItems: 'center',
|
60
|
+
color: '#333',
|
61
|
+
background: '#f2f2f2',
|
62
|
+
borderRadius: '2px',
|
63
|
+
border: '1px solid #767676',
|
64
|
+
cursor: 'pointer',
|
65
|
+
height: '24px',
|
66
|
+
width: '24px',
|
67
|
+
}
|
68
|
+
Object.assign(button.style, buttonStyle);
|
69
|
+
button.addEventListener('click', () => {
|
70
|
+
onChange && onChange('');
|
71
|
+
});
|
72
|
+
container.appendChild(button);
|
73
|
+
}
|
74
|
+
|
75
|
+
// file input
|
76
|
+
const label = document.createElement('label');
|
77
|
+
const labelStyle: CSS.Properties = {
|
78
|
+
...fullSize,
|
79
|
+
display: isForm ? 'flex' : 'none',
|
80
|
+
position: 'absolute',
|
81
|
+
top: 0,
|
82
|
+
backgroundColor: isForm || value ? 'rgb(242 244 255 / 75%)' : 'none',
|
83
|
+
cursor: 'pointer',
|
84
|
+
}
|
85
|
+
Object.assign(label.style, labelStyle);
|
86
|
+
container.appendChild(label);
|
87
|
+
|
88
|
+
|
89
|
+
const input = document.createElement('input');
|
90
|
+
const inputStyle: CSS.Properties = { ...fullSize, position: 'absolute', top: '50%' }
|
91
|
+
Object.assign(input.style, inputStyle);
|
92
|
+
input.tabIndex = tabIndex || 0;
|
93
|
+
input.type = 'file';
|
94
|
+
input.accept = 'image/jpeg, image/png';
|
95
|
+
input.addEventListener('change', (event: Event) => {
|
96
|
+
const changeEvent = event as unknown as ChangeEvent<HTMLInputElement>;
|
97
|
+
readFiles(changeEvent.target.files, 'dataURL').then((result) => onChange && onChange(result as string))
|
98
|
+
});
|
99
|
+
input.addEventListener('blur', () => stopEditing && stopEditing());
|
100
|
+
label.appendChild(input);
|
101
|
+
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
import type * as CSS from 'csstype';
|
2
|
+
import type { RenderProps } from "../types"
|
3
|
+
import {
|
4
|
+
DEFAULT_FONT_SIZE,
|
5
|
+
DEFAULT_ALIGNMENT,
|
6
|
+
VERTICAL_ALIGN_TOP,
|
7
|
+
VERTICAL_ALIGN_MIDDLE,
|
8
|
+
VERTICAL_ALIGN_BOTTOM,
|
9
|
+
DEFAULT_VERTICAL_ALIGNMENT,
|
10
|
+
DEFAULT_LINE_HEIGHT,
|
11
|
+
DEFAULT_CHARACTER_SPACING,
|
12
|
+
DEFAULT_FONT_COLOR,
|
13
|
+
TextSchema,
|
14
|
+
calculateDynamicFontSize,
|
15
|
+
getFontKitFont,
|
16
|
+
getDefaultFont,
|
17
|
+
getBrowserVerticalFontAdjustments,
|
18
|
+
} from '@pdfme/common';
|
19
|
+
|
20
|
+
const mapVerticalAlignToFlex = (verticalAlignmentValue: string | undefined) => {
|
21
|
+
switch (verticalAlignmentValue) {
|
22
|
+
case VERTICAL_ALIGN_TOP:
|
23
|
+
return 'flex-start';
|
24
|
+
case VERTICAL_ALIGN_MIDDLE:
|
25
|
+
return 'center';
|
26
|
+
case VERTICAL_ALIGN_BOTTOM:
|
27
|
+
return 'flex-end';
|
28
|
+
}
|
29
|
+
return 'flex-start';
|
30
|
+
};
|
31
|
+
|
32
|
+
export const renderText = async (arg: RenderProps) => {
|
33
|
+
const {
|
34
|
+
value,
|
35
|
+
rootElement,
|
36
|
+
mode,
|
37
|
+
onChange,
|
38
|
+
stopEditing,
|
39
|
+
tabIndex,
|
40
|
+
placeholder,
|
41
|
+
options,
|
42
|
+
} = arg;
|
43
|
+
|
44
|
+
const schema = arg.schema as TextSchema;
|
45
|
+
|
46
|
+
const font = options?.font || getDefaultFont();
|
47
|
+
|
48
|
+
let dynamicFontSize: undefined | number = undefined;
|
49
|
+
if (schema.dynamicFontSize && value) {
|
50
|
+
dynamicFontSize = await calculateDynamicFontSize({
|
51
|
+
textSchema: schema,
|
52
|
+
font,
|
53
|
+
value,
|
54
|
+
startingFontSize: dynamicFontSize,
|
55
|
+
})
|
56
|
+
}
|
57
|
+
|
58
|
+
|
59
|
+
const fontKitFont = await getFontKitFont(schema, font)
|
60
|
+
// Depending on vertical alignment, we need to move the top or bottom of the font to keep
|
61
|
+
// it within it's defined box and align it with the generated pdf.
|
62
|
+
const { topAdj, bottomAdj } = getBrowserVerticalFontAdjustments(
|
63
|
+
fontKitFont,
|
64
|
+
dynamicFontSize ?? schema.fontSize ?? DEFAULT_FONT_SIZE,
|
65
|
+
schema.lineHeight ?? DEFAULT_LINE_HEIGHT,
|
66
|
+
schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT
|
67
|
+
);
|
68
|
+
|
69
|
+
const topAdjustment = topAdj;
|
70
|
+
const bottomAdjustment = bottomAdj;
|
71
|
+
|
72
|
+
const container = document.createElement('div');
|
73
|
+
const containerStyle: CSS.Properties = {
|
74
|
+
padding: 0,
|
75
|
+
resize: 'none',
|
76
|
+
backgroundColor: value && schema.backgroundColor ? schema.backgroundColor : 'rgb(242 244 255 / 75%)',
|
77
|
+
border: 'none',
|
78
|
+
display: 'flex',
|
79
|
+
flexDirection: 'column',
|
80
|
+
justifyContent: mapVerticalAlignToFlex(schema.verticalAlignment),
|
81
|
+
width: '100%',
|
82
|
+
height: '100%',
|
83
|
+
};
|
84
|
+
Object.assign(container.style, containerStyle);
|
85
|
+
rootElement.innerHTML = '';
|
86
|
+
rootElement.appendChild(container);
|
87
|
+
|
88
|
+
|
89
|
+
const fontStyles: CSS.Properties = {
|
90
|
+
fontFamily: schema.fontName ? `'${schema.fontName}'` : 'inherit',
|
91
|
+
color: schema.fontColor ? schema.fontColor : DEFAULT_FONT_COLOR,
|
92
|
+
fontSize: `${dynamicFontSize ?? schema.fontSize ?? DEFAULT_FONT_SIZE}pt`,
|
93
|
+
letterSpacing: `${schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING}pt`,
|
94
|
+
lineHeight: `${schema.lineHeight ?? DEFAULT_LINE_HEIGHT}em`,
|
95
|
+
textAlign: schema.alignment ?? DEFAULT_ALIGNMENT,
|
96
|
+
whiteSpace: 'pre-wrap',
|
97
|
+
wordBreak: 'break-word',
|
98
|
+
};
|
99
|
+
|
100
|
+
if (mode === 'form') {
|
101
|
+
const textarea = document.createElement('textarea');
|
102
|
+
const textareaStyle: CSS.Properties = {
|
103
|
+
padding: 0,
|
104
|
+
resize: 'none',
|
105
|
+
border: 'none',
|
106
|
+
outline: 'none',
|
107
|
+
paddingTop: topAdjustment + 'px',
|
108
|
+
background: 'none',
|
109
|
+
width: '100%',
|
110
|
+
height: '100%',
|
111
|
+
};
|
112
|
+
Object.assign(textarea.style, textareaStyle, fontStyles);
|
113
|
+
textarea.rows = 1;
|
114
|
+
textarea.placeholder = placeholder || "";
|
115
|
+
textarea.tabIndex = tabIndex || 0;
|
116
|
+
|
117
|
+
textarea.addEventListener('change', (e: Event) => onChange && onChange((e.target as HTMLTextAreaElement).value));
|
118
|
+
textarea.addEventListener('blur', () => stopEditing && stopEditing());
|
119
|
+
textarea.value = value;
|
120
|
+
container.appendChild(textarea);
|
121
|
+
textarea.setSelectionRange(value.length, value.length);
|
122
|
+
textarea.focus();
|
123
|
+
} else {
|
124
|
+
const div = document.createElement('div');
|
125
|
+
const divStyle: CSS.Properties = {
|
126
|
+
...fontStyles,
|
127
|
+
marginBottom: bottomAdjustment + 'px',
|
128
|
+
paddingTop: topAdjustment + 'px',
|
129
|
+
};
|
130
|
+
Object.assign(div.style, divStyle);
|
131
|
+
div.innerHTML = value.split('').map((l: string, i: number) => (
|
132
|
+
`<span style="letter-spacing:${String(value).length === i + 1 ? 0 : 'inherit'};">${l}</span>`
|
133
|
+
)).join('');
|
134
|
+
|
135
|
+
container.appendChild(div);
|
136
|
+
|
137
|
+
}
|
138
|
+
}
|
package/src/types.ts
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
import type { UIOptions, SchemaForUI } from '@pdfme/common';
|
3
|
+
|
4
|
+
interface RenderBaseProps {
|
5
|
+
schema: SchemaForUI;
|
6
|
+
mode: 'viewer' | 'form';
|
7
|
+
tabIndex?: number;
|
8
|
+
placeholder?: string;
|
9
|
+
stopEditing?: () => void;
|
10
|
+
|
11
|
+
}
|
12
|
+
|
13
|
+
export type RendererProps = RenderBaseProps & {
|
14
|
+
onChange: (value: string) => void;
|
15
|
+
outline: string;
|
16
|
+
onChangeHoveringSchemaId?: (id: string | null) => void;
|
17
|
+
}
|
18
|
+
|
19
|
+
export type RenderProps = RenderBaseProps & {
|
20
|
+
onChange?: (value: string) => void;
|
21
|
+
value: string;
|
22
|
+
rootElement: HTMLDivElement,
|
23
|
+
options: UIOptions;
|
24
|
+
}
|
25
|
+
|
26
|
+
export interface Renderer {
|
27
|
+
[key: string]: { render: (arg: RenderProps) => Promise<void> } | undefined;
|
28
|
+
}
|
@@ -1,15 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { SchemaUIProps } from './SchemaUI';
|
3
|
-
declare const _default: React.ForwardRefExoticComponent<SchemaUIProps & {
|
4
|
-
schema: {
|
5
|
-
type: "qrcode" | "japanpost" | "ean13" | "ean8" | "code39" | "code128" | "nw7" | "itf14" | "upca" | "upce" | "gs1datamatrix";
|
6
|
-
height: number;
|
7
|
-
width: number;
|
8
|
-
position: {
|
9
|
-
x: number;
|
10
|
-
y: number;
|
11
|
-
};
|
12
|
-
rotate?: number | undefined;
|
13
|
-
};
|
14
|
-
} & React.RefAttributes<HTMLInputElement>>;
|
15
|
-
export default _default;
|
@@ -1,15 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { SchemaUIProps } from './SchemaUI';
|
3
|
-
declare const _default: React.ForwardRefExoticComponent<SchemaUIProps & {
|
4
|
-
schema: {
|
5
|
-
type: "image";
|
6
|
-
height: number;
|
7
|
-
width: number;
|
8
|
-
position: {
|
9
|
-
x: number;
|
10
|
-
y: number;
|
11
|
-
};
|
12
|
-
rotate?: number | undefined;
|
13
|
-
};
|
14
|
-
} & React.RefAttributes<HTMLInputElement>>;
|
15
|
-
export default _default;
|
@@ -1,15 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { SchemaForUI } from '@pdfme/common';
|
3
|
-
export interface SchemaUIProps {
|
4
|
-
schema: SchemaForUI;
|
5
|
-
editable: boolean;
|
6
|
-
onChange: (value: string) => void;
|
7
|
-
onStopEditing: () => void;
|
8
|
-
tabIndex?: number;
|
9
|
-
placeholder?: string;
|
10
|
-
}
|
11
|
-
declare const _default: React.ForwardRefExoticComponent<SchemaUIProps & {
|
12
|
-
outline: string;
|
13
|
-
onChangeHoveringSchemaId?: ((id: string | null) => void) | undefined;
|
14
|
-
} & React.RefAttributes<HTMLTextAreaElement | HTMLInputElement>>;
|
15
|
-
export default _default;
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { SchemaUIProps } from './SchemaUI';
|
3
|
-
declare const _default: React.ForwardRefExoticComponent<SchemaUIProps & {
|
4
|
-
schema: {
|
5
|
-
type: "text";
|
6
|
-
height: number;
|
7
|
-
width: number;
|
8
|
-
position: {
|
9
|
-
x: number;
|
10
|
-
y: number;
|
11
|
-
};
|
12
|
-
rotate?: number | undefined;
|
13
|
-
alignment?: "center" | "left" | "right" | undefined;
|
14
|
-
fontSize?: number | undefined;
|
15
|
-
fontName?: string | undefined;
|
16
|
-
fontColor?: string | undefined;
|
17
|
-
backgroundColor?: string | undefined;
|
18
|
-
characterSpacing?: number | undefined;
|
19
|
-
lineHeight?: number | undefined;
|
20
|
-
dynamicFontSize?: {
|
21
|
-
max: number;
|
22
|
-
min: number;
|
23
|
-
fit?: string | undefined;
|
24
|
-
} | undefined;
|
25
|
-
};
|
26
|
-
} & React.RefAttributes<HTMLTextAreaElement>>;
|
27
|
-
export default _default;
|