@pdfme/schemas 4.1.1 → 4.2.1-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/dist/cjs/src/constants.js +1 -1
- package/dist/cjs/src/constants.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/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/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/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/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/text/uiRender.ts +150 -118
@@ -0,0 +1,161 @@
|
|
1
|
+
import { UIRenderProps } from '@pdfme/common';
|
2
|
+
import { MultiVariableTextSchema } from './types';
|
3
|
+
import {
|
4
|
+
uiRender as parentUiRender,
|
5
|
+
buildStyledTextContainer,
|
6
|
+
makeElementPlainTextContentEditable
|
7
|
+
} from '../text/uiRender';
|
8
|
+
import { isEditable } from '../utils';
|
9
|
+
import { substituteVariables } from './helper';
|
10
|
+
|
11
|
+
export const uiRender = async (arg: UIRenderProps<MultiVariableTextSchema>) => {
|
12
|
+
const { value, schema, rootElement, mode, onChange, ...rest } = arg;
|
13
|
+
|
14
|
+
let text = schema.text;
|
15
|
+
let numVariables = schema.variables.length;
|
16
|
+
|
17
|
+
if (mode === 'form' && numVariables > 0) {
|
18
|
+
await formUiRender(arg);
|
19
|
+
return;
|
20
|
+
}
|
21
|
+
|
22
|
+
await parentUiRender({
|
23
|
+
value: isEditable(mode, schema) ? text : substituteVariables(text, value),
|
24
|
+
schema,
|
25
|
+
mode: mode == 'form' ? 'viewer' : mode, // if no variables for form it's just a viewer
|
26
|
+
rootElement,
|
27
|
+
onChange: (arg: { key: string; value: any; } | { key: string; value: any; }[]) => {
|
28
|
+
if (!Array.isArray(arg)) {
|
29
|
+
onChange && onChange({key: 'text', value: arg.value});
|
30
|
+
} else {
|
31
|
+
throw new Error('onChange is not an array, the parent text plugin has changed...');
|
32
|
+
}
|
33
|
+
},
|
34
|
+
...rest,
|
35
|
+
});
|
36
|
+
|
37
|
+
const textBlock = rootElement.querySelector('#text-' + schema.id) as HTMLDivElement;
|
38
|
+
if (!textBlock) {
|
39
|
+
throw new Error('Text block not found. Ensure the text block has an id of "text-" + schema.id');
|
40
|
+
}
|
41
|
+
|
42
|
+
if (mode === 'designer') {
|
43
|
+
textBlock.addEventListener('keyup', (event: KeyboardEvent) => {
|
44
|
+
text = textBlock.textContent || '';
|
45
|
+
if (keyPressShouldBeChecked(event)) {
|
46
|
+
const newNumVariables = countUniqueVariableNames(text);
|
47
|
+
if (numVariables !== newNumVariables) {
|
48
|
+
// If variables were modified during this keypress, we trigger a change
|
49
|
+
if (onChange) {
|
50
|
+
onChange({key: 'text', value: text});
|
51
|
+
}
|
52
|
+
numVariables = newNumVariables;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
});
|
56
|
+
}
|
57
|
+
};
|
58
|
+
|
59
|
+
const formUiRender = async (arg: UIRenderProps<MultiVariableTextSchema>) => {
|
60
|
+
const {
|
61
|
+
value,
|
62
|
+
schema,
|
63
|
+
rootElement,
|
64
|
+
onChange,
|
65
|
+
stopEditing,
|
66
|
+
theme,
|
67
|
+
} = arg;
|
68
|
+
const rawText = schema.text;
|
69
|
+
|
70
|
+
if (rootElement.parentElement) {
|
71
|
+
// remove the outline for the whole schema, we'll apply outlines on each individual variable field instead
|
72
|
+
rootElement.parentElement.style.outline = '';
|
73
|
+
}
|
74
|
+
|
75
|
+
const variables: Record<string, string> = JSON.parse(value) || {}
|
76
|
+
const variableIndices = getVariableIndices(rawText);
|
77
|
+
const substitutedText = substituteVariables(rawText, variables);
|
78
|
+
|
79
|
+
const textBlock = await buildStyledTextContainer(arg, substitutedText);
|
80
|
+
|
81
|
+
// Construct content-editable spans for each variable within the string
|
82
|
+
let inVarString = false;
|
83
|
+
|
84
|
+
for (let i = 0; i < rawText.length; i++) {
|
85
|
+
if (variableIndices[i]) {
|
86
|
+
inVarString = true;
|
87
|
+
let span = document.createElement('span');
|
88
|
+
span.style.outline = `${theme.colorPrimary} dashed 1px`;
|
89
|
+
makeElementPlainTextContentEditable(span)
|
90
|
+
span.textContent = variables[variableIndices[i]];
|
91
|
+
span.addEventListener('blur', (e: Event) => {
|
92
|
+
const newValue = (e.target as HTMLSpanElement).textContent || '';
|
93
|
+
if (newValue !== variables[variableIndices[i]]) {
|
94
|
+
variables[variableIndices[i]] = newValue;
|
95
|
+
onChange && onChange({ key: 'content', value: JSON.stringify(variables) });
|
96
|
+
stopEditing && stopEditing();
|
97
|
+
}
|
98
|
+
});
|
99
|
+
textBlock.appendChild(span);
|
100
|
+
} else if (inVarString) {
|
101
|
+
if (rawText[i] === '}') {
|
102
|
+
inVarString = false;
|
103
|
+
}
|
104
|
+
} else {
|
105
|
+
let span = document.createElement('span');
|
106
|
+
span.style.letterSpacing = rawText.length === i + 1 ? '0' : 'inherit';
|
107
|
+
span.textContent = rawText[i];
|
108
|
+
textBlock.appendChild(span);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
const getVariableIndices = (content: string) => {
|
114
|
+
const regex = /\{([^}]+)}/g;
|
115
|
+
const indices = [];
|
116
|
+
let match;
|
117
|
+
|
118
|
+
while ((match = regex.exec(content)) !== null) {
|
119
|
+
indices[match.index] = match[1];
|
120
|
+
}
|
121
|
+
|
122
|
+
return indices;
|
123
|
+
};
|
124
|
+
|
125
|
+
const countUniqueVariableNames = (content: string) => {
|
126
|
+
const regex = /\{([^}]+)}/g;
|
127
|
+
const uniqueMatchesSet = new Set();
|
128
|
+
let match;
|
129
|
+
|
130
|
+
while ((match = regex.exec(content)) !== null) {
|
131
|
+
uniqueMatchesSet.add(match[1]);
|
132
|
+
}
|
133
|
+
|
134
|
+
return uniqueMatchesSet.size;
|
135
|
+
};
|
136
|
+
|
137
|
+
/**
|
138
|
+
* An optimisation to try to minimise jank while typing.
|
139
|
+
* Only check whether variables were modified based on certain key presses.
|
140
|
+
* Regex would otherwise be performed on every key press (which isn't terrible, but this code helps).
|
141
|
+
*/
|
142
|
+
const keyPressShouldBeChecked = (event: KeyboardEvent) => {
|
143
|
+
if (event.key == "ArrowUp" || event.key == "ArrowDown" || event.key == "ArrowLeft" || event.key == "ArrowRight") {
|
144
|
+
return false;
|
145
|
+
}
|
146
|
+
|
147
|
+
const selection = window.getSelection();
|
148
|
+
const contenteditable = event.target as HTMLDivElement;
|
149
|
+
|
150
|
+
const isCursorAtEnd = selection?.focusOffset === contenteditable?.textContent?.length;
|
151
|
+
if (isCursorAtEnd) {
|
152
|
+
return event.key === '}' || event.key === 'Backspace' || event.key === 'Delete';
|
153
|
+
}
|
154
|
+
|
155
|
+
const isCursorAtStart = selection?.anchorOffset === 0;
|
156
|
+
if (isCursorAtStart) {
|
157
|
+
return event.key === '{' || event.key === 'Backspace' || event.key === 'Delete';
|
158
|
+
}
|
159
|
+
|
160
|
+
return true;
|
161
|
+
}
|
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).textContent });
|
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
|
};
|