@pdfme/schemas 4.1.0 → 4.1.1-dev.2
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/cjs/src/constants.js +1 -1
- package/dist/cjs/src/constants.js.map +1 -1
- package/dist/cjs/src/graphics/image.js +3 -1
- package/dist/cjs/src/graphics/image.js.map +1 -1
- package/dist/cjs/src/index.js +11 -9
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/multiVariableText/helper.js +19 -0
- package/dist/cjs/src/multiVariableText/helper.js.map +1 -0
- package/dist/cjs/src/multiVariableText/index.js +8 -0
- package/dist/cjs/src/multiVariableText/index.js.map +1 -0
- package/dist/cjs/src/multiVariableText/pdfRender.js +16 -0
- package/dist/cjs/src/multiVariableText/pdfRender.js.map +1 -0
- package/dist/cjs/src/multiVariableText/propPanel.js +128 -0
- package/dist/cjs/src/multiVariableText/propPanel.js.map +1 -0
- package/dist/cjs/src/multiVariableText/types.js +3 -0
- package/dist/cjs/src/multiVariableText/types.js.map +1 -0
- package/dist/cjs/src/multiVariableText/uiRender.js +133 -0
- package/dist/cjs/src/multiVariableText/uiRender.js.map +1 -0
- package/dist/cjs/src/tables/tableHelper.js +2 -2
- package/dist/cjs/src/tables/tableHelper.js.map +1 -1
- package/dist/cjs/src/text/extraFormatter.js +1 -1
- package/dist/cjs/src/text/propPanel.js +1 -1
- package/dist/cjs/src/text/uiRender.js +122 -103
- package/dist/cjs/src/text/uiRender.js.map +1 -1
- package/dist/esm/src/constants.js +1 -1
- package/dist/esm/src/constants.js.map +1 -1
- package/dist/esm/src/graphics/image.js +3 -1
- package/dist/esm/src/graphics/image.js.map +1 -1
- package/dist/esm/src/index.js +2 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/multiVariableText/helper.js +15 -0
- package/dist/esm/src/multiVariableText/helper.js.map +1 -0
- package/dist/esm/src/multiVariableText/index.js +6 -0
- package/dist/esm/src/multiVariableText/index.js.map +1 -0
- package/dist/esm/src/multiVariableText/pdfRender.js +12 -0
- package/dist/esm/src/multiVariableText/pdfRender.js.map +1 -0
- package/dist/esm/src/multiVariableText/propPanel.js +125 -0
- package/dist/esm/src/multiVariableText/propPanel.js.map +1 -0
- package/dist/esm/src/multiVariableText/types.js +2 -0
- package/dist/esm/src/multiVariableText/types.js.map +1 -0
- package/dist/esm/src/multiVariableText/uiRender.js +129 -0
- package/dist/esm/src/multiVariableText/uiRender.js.map +1 -0
- package/dist/esm/src/tables/tableHelper.js +2 -2
- package/dist/esm/src/tables/tableHelper.js.map +1 -1
- package/dist/esm/src/text/extraFormatter.js +1 -1
- package/dist/esm/src/text/propPanel.js +1 -1
- package/dist/esm/src/text/uiRender.js +118 -101
- package/dist/esm/src/text/uiRender.js.map +1 -1
- package/dist/types/src/constants.d.ts +1 -1
- package/dist/types/src/index.d.ts +2 -1
- package/dist/types/src/multiVariableText/helper.d.ts +1 -0
- package/dist/types/src/multiVariableText/index.d.ts +4 -0
- package/dist/types/src/multiVariableText/pdfRender.d.ts +3 -0
- package/dist/types/src/multiVariableText/propPanel.d.ts +3 -0
- package/dist/types/src/multiVariableText/types.d.ts +5 -0
- package/dist/types/src/multiVariableText/uiRender.d.ts +3 -0
- package/dist/types/src/shapes/rectAndEllipse.d.ts +2 -0
- package/dist/types/src/text/uiRender.d.ts +6 -0
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/graphics/image.ts +2 -1
- package/src/index.ts +2 -0
- package/src/multiVariableText/helper.ts +18 -0
- package/src/multiVariableText/index.ts +8 -0
- package/src/multiVariableText/pdfRender.ts +16 -0
- package/src/multiVariableText/propPanel.ts +139 -0
- package/src/multiVariableText/types.ts +6 -0
- package/src/multiVariableText/uiRender.ts +161 -0
- package/src/tables/tableHelper.ts +2 -2
- package/src/text/extraFormatter.ts +1 -1
- package/src/text/propPanel.ts +1 -1
- package/src/text/uiRender.ts +150 -118
package/src/text/uiRender.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import type * as CSS from 'csstype';
|
2
|
-
import { UIRenderProps,
|
2
|
+
import { UIRenderProps, getDefaultFont } from '@pdfme/common';
|
3
3
|
import type { TextSchema } from './types';
|
4
4
|
import {
|
5
5
|
DEFAULT_FONT_SIZE,
|
@@ -21,28 +21,10 @@ import {
|
|
21
21
|
} from './helper.js';
|
22
22
|
import { isEditable } from '../utils.js';
|
23
23
|
|
24
|
-
const mapVerticalAlignToFlex = (verticalAlignmentValue: string | undefined) => {
|
25
|
-
switch (verticalAlignmentValue) {
|
26
|
-
case VERTICAL_ALIGN_TOP:
|
27
|
-
return 'flex-start';
|
28
|
-
case VERTICAL_ALIGN_MIDDLE:
|
29
|
-
return 'center';
|
30
|
-
case VERTICAL_ALIGN_BOTTOM:
|
31
|
-
return 'flex-end';
|
32
|
-
}
|
33
|
-
return 'flex-start';
|
34
|
-
};
|
35
|
-
|
36
|
-
const getBackgroundColor = (value: string, schema: Schema) => {
|
37
|
-
if (!value || !schema.backgroundColor) return 'transparent';
|
38
|
-
return schema.backgroundColor as string;
|
39
|
-
};
|
40
|
-
|
41
24
|
export const uiRender = async (arg: UIRenderProps<TextSchema>) => {
|
42
25
|
const {
|
43
26
|
value,
|
44
27
|
schema,
|
45
|
-
rootElement,
|
46
28
|
mode,
|
47
29
|
onChange,
|
48
30
|
stopEditing,
|
@@ -51,28 +33,120 @@ export const uiRender = async (arg: UIRenderProps<TextSchema>) => {
|
|
51
33
|
options,
|
52
34
|
_cache,
|
53
35
|
} = arg;
|
36
|
+
const usePlaceholder = isEditable(mode, schema) && placeholder && !value;
|
37
|
+
|
38
|
+
const textBlock = await buildStyledTextContainer(arg, usePlaceholder ? placeholder : value);
|
39
|
+
|
40
|
+
if (!isEditable(mode, schema)) {
|
41
|
+
// Read-only mode
|
42
|
+
textBlock.innerHTML = value
|
43
|
+
.split('')
|
44
|
+
.map(
|
45
|
+
(l: string, i: number) =>
|
46
|
+
`<span style="letter-spacing:${
|
47
|
+
String(value).length === i + 1 ? 0 : 'inherit'
|
48
|
+
};">${l}</span>`
|
49
|
+
)
|
50
|
+
.join('');
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
|
54
|
+
makeElementPlainTextContentEditable(textBlock);
|
55
|
+
textBlock.tabIndex = tabIndex || 0;
|
56
|
+
textBlock.innerText = value;
|
57
|
+
textBlock.addEventListener('blur', (e: Event) => {
|
58
|
+
onChange && onChange({ key: 'content', value: (e.target as HTMLDivElement).innerText });
|
59
|
+
stopEditing && stopEditing();
|
60
|
+
});
|
61
|
+
|
62
|
+
if (schema.dynamicFontSize) {
|
63
|
+
let dynamicFontSize: undefined | number = undefined;
|
64
|
+
const font = options?.font || getDefaultFont();
|
65
|
+
const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
|
66
|
+
|
67
|
+
textBlock.addEventListener('keyup', () => {
|
68
|
+
setTimeout(() => {
|
69
|
+
void (async () => {
|
70
|
+
if (!textBlock.textContent) return;
|
71
|
+
dynamicFontSize = await calculateDynamicFontSize({
|
72
|
+
textSchema: schema,
|
73
|
+
font,
|
74
|
+
value: textBlock.textContent,
|
75
|
+
startingFontSize: dynamicFontSize,
|
76
|
+
_cache,
|
77
|
+
});
|
78
|
+
textBlock.style.fontSize = `${dynamicFontSize}pt`;
|
79
|
+
|
80
|
+
const { topAdj: newTopAdj, bottomAdj: newBottomAdj } =
|
81
|
+
getBrowserVerticalFontAdjustments(
|
82
|
+
fontKitFont,
|
83
|
+
dynamicFontSize ?? schema.fontSize ?? DEFAULT_FONT_SIZE,
|
84
|
+
schema.lineHeight ?? DEFAULT_LINE_HEIGHT,
|
85
|
+
schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT
|
86
|
+
);
|
87
|
+
textBlock.style.paddingTop = `${newTopAdj}px`;
|
88
|
+
textBlock.style.marginBottom = `${newBottomAdj}px`;
|
89
|
+
})();
|
90
|
+
}, 0);
|
91
|
+
});
|
92
|
+
}
|
93
|
+
|
94
|
+
if (usePlaceholder) {
|
95
|
+
textBlock.style.color = PLACEHOLDER_FONT_COLOR;
|
96
|
+
textBlock.addEventListener('focus', () => {
|
97
|
+
if (textBlock.innerText === placeholder) {
|
98
|
+
textBlock.innerText = '';
|
99
|
+
textBlock.style.color = schema.fontColor ?? DEFAULT_FONT_COLOR;
|
100
|
+
}
|
101
|
+
});
|
102
|
+
}
|
103
|
+
|
104
|
+
if (mode === 'designer') {
|
105
|
+
setTimeout(() => {
|
106
|
+
textBlock.focus();
|
107
|
+
// Set the focus to the end of the editable element when you focus, as we would for a textarea
|
108
|
+
const selection = window.getSelection();
|
109
|
+
const range = document.createRange();
|
110
|
+
if (selection && range) {
|
111
|
+
range.selectNodeContents(textBlock);
|
112
|
+
range.collapse(false); // Collapse range to the end
|
113
|
+
selection?.removeAllRanges();
|
114
|
+
selection?.addRange(range);
|
115
|
+
}
|
116
|
+
});
|
117
|
+
}
|
118
|
+
};
|
119
|
+
|
120
|
+
export const buildStyledTextContainer = async (arg: UIRenderProps<TextSchema>, value: string) => {
|
121
|
+
const {
|
122
|
+
schema,
|
123
|
+
rootElement,
|
124
|
+
mode,
|
125
|
+
options,
|
126
|
+
_cache,
|
127
|
+
} = arg;
|
54
128
|
const font = options?.font || getDefaultFont();
|
55
129
|
|
56
130
|
let dynamicFontSize: undefined | number = undefined;
|
57
|
-
|
58
|
-
textSchema: schema,
|
59
|
-
font,
|
60
|
-
value: v,
|
61
|
-
startingFontSize: dynamicFontSize,
|
62
|
-
_cache,
|
63
|
-
});
|
131
|
+
|
64
132
|
if (schema.dynamicFontSize && value) {
|
65
|
-
dynamicFontSize = await calculateDynamicFontSize(
|
133
|
+
dynamicFontSize = await calculateDynamicFontSize({
|
134
|
+
textSchema: schema,
|
135
|
+
font,
|
136
|
+
value,
|
137
|
+
startingFontSize: dynamicFontSize,
|
138
|
+
_cache,
|
139
|
+
});
|
66
140
|
}
|
67
141
|
|
68
142
|
const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
|
69
143
|
// Depending on vertical alignment, we need to move the top or bottom of the font to keep
|
70
144
|
// it within it's defined box and align it with the generated pdf.
|
71
145
|
const { topAdj, bottomAdj } = getBrowserVerticalFontAdjustments(
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
146
|
+
fontKitFont,
|
147
|
+
dynamicFontSize ?? schema.fontSize ?? DEFAULT_FONT_SIZE,
|
148
|
+
schema.lineHeight ?? DEFAULT_LINE_HEIGHT,
|
149
|
+
schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT
|
76
150
|
);
|
77
151
|
|
78
152
|
const topAdjustment = topAdj.toString();
|
@@ -120,100 +194,58 @@ export const uiRender = async (arg: UIRenderProps<TextSchema>) => {
|
|
120
194
|
backgroundColor: 'transparent',
|
121
195
|
textDecoration: textDecorations.join(' '),
|
122
196
|
};
|
197
|
+
|
123
198
|
const textBlock = document.createElement('div');
|
199
|
+
textBlock.id = 'text-' + schema.id;
|
124
200
|
Object.assign(textBlock.style, textBlockStyle);
|
125
201
|
|
126
|
-
|
127
|
-
if (!isFirefox()) {
|
128
|
-
textBlock.contentEditable = 'plaintext-only';
|
129
|
-
} else {
|
130
|
-
textBlock.contentEditable = 'true';
|
131
|
-
textBlock.addEventListener('keydown', (e: KeyboardEvent) => {
|
132
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
133
|
-
e.preventDefault();
|
134
|
-
document.execCommand('insertLineBreak', false, undefined);
|
135
|
-
}
|
136
|
-
});
|
137
|
-
|
138
|
-
textBlock.addEventListener('paste', (e: ClipboardEvent) => {
|
139
|
-
e.preventDefault();
|
140
|
-
const paste = e.clipboardData?.getData('text');
|
141
|
-
const selection = window.getSelection();
|
142
|
-
if (!selection?.rangeCount) return;
|
143
|
-
selection.deleteFromDocument();
|
144
|
-
selection.getRangeAt(0).insertNode(document.createTextNode(paste || ''));
|
145
|
-
selection.collapseToEnd();
|
146
|
-
});
|
147
|
-
}
|
148
|
-
textBlock.tabIndex = tabIndex || 0;
|
149
|
-
textBlock.innerText = value;
|
150
|
-
textBlock.addEventListener('blur', (e: Event) => {
|
151
|
-
onChange && onChange({ key: 'content', value: (e.target as HTMLDivElement).innerText });
|
152
|
-
stopEditing && stopEditing();
|
153
|
-
});
|
202
|
+
container.appendChild(textBlock);
|
154
203
|
|
155
|
-
|
156
|
-
|
157
|
-
setTimeout(() => {
|
158
|
-
void (async () => {
|
159
|
-
if (!textBlock.textContent) return;
|
160
|
-
dynamicFontSize = await calculateDynamicFontSize(getCdfArg(textBlock.textContent));
|
161
|
-
textBlock.style.fontSize = `${dynamicFontSize}pt`;
|
162
|
-
|
163
|
-
const { topAdj: newTopAdj, bottomAdj: newBottomAdj } =
|
164
|
-
getBrowserVerticalFontAdjustments(
|
165
|
-
fontKitFont,
|
166
|
-
dynamicFontSize ?? schema.fontSize ?? DEFAULT_FONT_SIZE,
|
167
|
-
schema.lineHeight ?? DEFAULT_LINE_HEIGHT,
|
168
|
-
schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT
|
169
|
-
);
|
170
|
-
textBlock.style.paddingTop = `${newTopAdj}px`;
|
171
|
-
textBlock.style.marginBottom = `${newBottomAdj}px`;
|
172
|
-
})();
|
173
|
-
}, 0);
|
174
|
-
});
|
175
|
-
}
|
204
|
+
return textBlock;
|
205
|
+
};
|
176
206
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
207
|
+
/**
|
208
|
+
* Firefox doesn't support 'plaintext-only' contentEditable mode, which we want to avoid mark-up.
|
209
|
+
* This function adds a workaround for Firefox to make the contentEditable element behave like 'plaintext-only'.
|
210
|
+
*/
|
211
|
+
export const makeElementPlainTextContentEditable = (element: HTMLElement) => {
|
212
|
+
if (!isFirefox()) {
|
213
|
+
element.contentEditable = 'plaintext-only';
|
214
|
+
return;
|
215
|
+
}
|
216
|
+
|
217
|
+
element.contentEditable = 'true';
|
218
|
+
element.addEventListener('keydown', (e: KeyboardEvent) => {
|
219
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
220
|
+
e.preventDefault();
|
221
|
+
document.execCommand('insertLineBreak', false, undefined);
|
190
222
|
}
|
223
|
+
});
|
191
224
|
|
192
|
-
|
225
|
+
element.addEventListener('paste', (e: ClipboardEvent) => {
|
226
|
+
e.preventDefault();
|
227
|
+
const paste = e.clipboardData?.getData('text');
|
228
|
+
const selection = window.getSelection();
|
229
|
+
if (!selection?.rangeCount) return;
|
230
|
+
selection.deleteFromDocument();
|
231
|
+
selection.getRangeAt(0).insertNode(document.createTextNode(paste || ''));
|
232
|
+
selection.collapseToEnd();
|
233
|
+
});
|
234
|
+
}
|
193
235
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
selection?.removeAllRanges();
|
203
|
-
selection?.addRange(range);
|
204
|
-
});
|
205
|
-
}
|
206
|
-
} else {
|
207
|
-
textBlock.innerHTML = value
|
208
|
-
.split('')
|
209
|
-
.map(
|
210
|
-
(l: string, i: number) =>
|
211
|
-
`<span style="letter-spacing:${
|
212
|
-
String(value).length === i + 1 ? 0 : 'inherit'
|
213
|
-
};">${l}</span>`
|
214
|
-
)
|
215
|
-
.join('');
|
216
|
-
|
217
|
-
container.appendChild(textBlock);
|
236
|
+
const mapVerticalAlignToFlex = (verticalAlignmentValue: string | undefined) => {
|
237
|
+
switch (verticalAlignmentValue) {
|
238
|
+
case VERTICAL_ALIGN_TOP:
|
239
|
+
return 'flex-start';
|
240
|
+
case VERTICAL_ALIGN_MIDDLE:
|
241
|
+
return 'center';
|
242
|
+
case VERTICAL_ALIGN_BOTTOM:
|
243
|
+
return 'flex-end';
|
218
244
|
}
|
245
|
+
return 'flex-start';
|
246
|
+
};
|
247
|
+
|
248
|
+
const getBackgroundColor = (value: string, schema: TextSchema) => {
|
249
|
+
if (!value || !schema.backgroundColor) return 'transparent';
|
250
|
+
return schema.backgroundColor as string;
|
219
251
|
};
|