@pdfme/schemas 6.0.3 → 6.0.5-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/barcodes/constants.d.ts +4 -0
- package/dist/barcodes/helper.d.ts +21 -0
- package/dist/barcodes/index.d.ts +4 -0
- package/dist/barcodes/pdfRender.d.ts +3 -0
- package/dist/barcodes/propPanel.d.ts +3 -0
- package/{src/barcodes/types.ts → dist/barcodes/types.d.ts} +5 -7
- package/dist/barcodes/uiRender.d.ts +3 -0
- package/dist/builtins-CgaZ0UX3.js +613 -0
- package/dist/builtins-CgaZ0UX3.js.map +1 -0
- package/dist/builtins.d.ts +4 -0
- package/dist/builtins.js +2 -0
- package/dist/checkbox/index.d.ts +6 -0
- package/dist/constants.d.ts +2 -0
- package/dist/date/date.d.ts +2 -0
- package/dist/date/dateTime.d.ts +2 -0
- package/dist/date/helper.d.ts +20 -0
- package/dist/date/time.d.ts +2 -0
- package/dist/date/types.d.ts +17 -0
- package/dist/dynamicTemplate-D_DHR3-X.js +1128 -0
- package/dist/dynamicTemplate-D_DHR3-X.js.map +1 -0
- package/dist/graphics/image.d.ts +5 -0
- package/dist/graphics/imagehelper.d.ts +4 -0
- package/dist/graphics/signature.d.ts +4 -0
- package/dist/graphics/svg.d.ts +4 -0
- package/{src/index.ts → dist/index.d.ts} +1 -22
- package/dist/index.js +5383 -0
- package/dist/index.js.map +1 -0
- package/dist/multiVariableText/helper.d.ts +3 -0
- package/dist/multiVariableText/index.d.ts +4 -0
- package/dist/multiVariableText/pdfRender.d.ts +3 -0
- package/dist/multiVariableText/propPanel.d.ts +3 -0
- package/{src/multiVariableText/types.ts → dist/multiVariableText/types.d.ts} +2 -3
- package/dist/multiVariableText/uiRender.d.ts +3 -0
- package/dist/multiVariableText/variables.d.ts +10 -0
- package/dist/radioGroup/index.d.ts +7 -0
- package/dist/sanitize.d.ts +1 -0
- package/dist/select/index.d.ts +7 -0
- package/dist/shapes/line.d.ts +6 -0
- package/dist/shapes/rectAndEllipse.d.ts +11 -0
- package/dist/tables/cell.d.ts +4 -0
- package/dist/tables/classes.d.ts +69 -0
- package/dist/tables/dynamicTemplate.d.ts +7 -0
- package/dist/tables/helper.d.ts +265 -0
- package/dist/tables/index.d.ts +4 -0
- package/dist/tables/pdfRender.d.ts +3 -0
- package/dist/tables/propPanel.d.ts +3 -0
- package/dist/tables/tableHelper.d.ts +10 -0
- package/dist/tables/types.d.ts +88 -0
- package/dist/tables/uiRender.d.ts +3 -0
- package/dist/tables.js +2 -0
- package/dist/text/constants.d.ts +23 -0
- package/dist/text/extraFormatter.d.ts +25 -0
- package/dist/text/helper.d.ts +40 -0
- package/dist/text/icons/index.d.ts +9 -0
- package/dist/text/index.d.ts +4 -0
- package/dist/text/pdfRender.d.ts +3 -0
- package/dist/text/propPanel.d.ts +3 -0
- package/dist/text/types.d.ts +28 -0
- package/dist/text/uiRender.d.ts +11 -0
- package/dist/utils.d.ts +40 -0
- package/dist/utils.js +215 -0
- package/dist/utils.js.map +1 -0
- package/package.json +5 -1
- package/src/barcodes/constants.ts +0 -20
- package/src/barcodes/helper.ts +0 -187
- package/src/barcodes/index.ts +0 -23
- package/src/barcodes/pdfRender.ts +0 -37
- package/src/barcodes/propPanel.ts +0 -249
- package/src/barcodes/uiRender.ts +0 -94
- package/src/builtins.ts +0 -8
- package/src/checkbox/index.ts +0 -70
- package/src/constants.ts +0 -2
- package/src/date/date.ts +0 -9
- package/src/date/dateTime.ts +0 -9
- package/src/date/helper.ts +0 -544
- package/src/date/time.ts +0 -9
- package/src/date/types.ts +0 -19
- package/src/graphics/image.ts +0 -201
- package/src/graphics/imagehelper.ts +0 -156
- package/src/graphics/signature.ts +0 -136
- package/src/graphics/svg.ts +0 -121
- package/src/multiVariableText/helper.ts +0 -65
- package/src/multiVariableText/index.ts +0 -16
- package/src/multiVariableText/pdfRender.ts +0 -21
- package/src/multiVariableText/propPanel.ts +0 -169
- package/src/multiVariableText/uiRender.ts +0 -157
- package/src/multiVariableText/variables.ts +0 -63
- package/src/radioGroup/index.ts +0 -115
- package/src/sanitize.ts +0 -50
- package/src/select/index.ts +0 -205
- package/src/shapes/line.ts +0 -94
- package/src/shapes/rectAndEllipse.ts +0 -152
- package/src/tables/cell.ts +0 -152
- package/src/tables/classes.ts +0 -402
- package/src/tables/dynamicTemplate.ts +0 -88
- package/src/tables/helper.ts +0 -216
- package/src/tables/index.ts +0 -15
- package/src/tables/pdfRender.ts +0 -144
- package/src/tables/propPanel.ts +0 -111
- package/src/tables/tableHelper.ts +0 -289
- package/src/tables/types.ts +0 -87
- package/src/tables/uiRender.ts +0 -436
- package/src/text/constants.ts +0 -104
- package/src/text/extraFormatter.ts +0 -83
- package/src/text/helper.ts +0 -573
- package/src/text/icons/index.ts +0 -30
- package/src/text/index.ts +0 -16
- package/src/text/pdfRender.ts +0 -240
- package/src/text/propPanel.ts +0 -184
- package/src/text/types.ts +0 -30
- package/src/text/uiRender.ts +0 -292
- package/src/utils.ts +0 -354
- package/tsconfig.build.json +0 -14
- package/tsconfig.json +0 -16
- package/vite.config.mts +0 -51
- /package/{src/tables.ts → dist/tables.d.ts} +0 -0
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from '@pdfme/common';
|
|
2
|
-
import { pdfRender } from './pdfRender.js';
|
|
3
|
-
import { propPanel } from './propPanel.js';
|
|
4
|
-
import { uiRender } from './uiRender.js';
|
|
5
|
-
import type { MultiVariableTextSchema } from './types.js';
|
|
6
|
-
import { Type } from 'lucide';
|
|
7
|
-
import { createSvgStr } from '../utils.js';
|
|
8
|
-
|
|
9
|
-
const schema: Plugin<MultiVariableTextSchema> = {
|
|
10
|
-
pdf: pdfRender,
|
|
11
|
-
ui: uiRender,
|
|
12
|
-
propPanel,
|
|
13
|
-
icon: createSvgStr(Type),
|
|
14
|
-
uninterruptedEditMode: true,
|
|
15
|
-
};
|
|
16
|
-
export default schema;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { PDFRenderProps } from '@pdfme/common';
|
|
2
|
-
import { MultiVariableTextSchema } from './types.js';
|
|
3
|
-
import { pdfRender as parentPdfRender } from '../text/pdfRender.js';
|
|
4
|
-
import { substituteVariables, validateVariables } from './helper.js';
|
|
5
|
-
|
|
6
|
-
export const pdfRender = async (arg: PDFRenderProps<MultiVariableTextSchema>) => {
|
|
7
|
-
const { value, schema, ...rest } = arg;
|
|
8
|
-
|
|
9
|
-
if (!validateVariables(value, schema)) {
|
|
10
|
-
// Don't render if a required variable is missing
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const renderArgs = {
|
|
15
|
-
value: substituteVariables(schema.text || '', value),
|
|
16
|
-
schema,
|
|
17
|
-
...rest,
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
await parentPdfRender(renderArgs);
|
|
21
|
-
};
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { propPanel as parentPropPanel } from '../text/propPanel.js';
|
|
2
|
-
import { PropPanel, PropPanelWidgetProps } from '@pdfme/common';
|
|
3
|
-
import { MultiVariableTextSchema } from './types.js';
|
|
4
|
-
import { getVariableNames } from './variables.js';
|
|
5
|
-
|
|
6
|
-
const mapDynamicVariables = (props: PropPanelWidgetProps) => {
|
|
7
|
-
const { rootElement, changeSchemas, activeSchema, i18n, options } = props;
|
|
8
|
-
|
|
9
|
-
const mvtSchema = activeSchema as unknown as MultiVariableTextSchema;
|
|
10
|
-
const text = mvtSchema.text || '';
|
|
11
|
-
let variables: Record<string, string> = {};
|
|
12
|
-
try {
|
|
13
|
-
const parsed = JSON.parse(mvtSchema.content || '{}');
|
|
14
|
-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
15
|
-
variables = parsed as Record<string, string>;
|
|
16
|
-
}
|
|
17
|
-
} catch {
|
|
18
|
-
// content is not valid JSON (e.g. a plain string value) — start fresh
|
|
19
|
-
}
|
|
20
|
-
const variablesChanged = updateVariablesFromText(text, variables);
|
|
21
|
-
const varNames = Object.keys(variables);
|
|
22
|
-
|
|
23
|
-
if (variablesChanged) {
|
|
24
|
-
changeSchemas([
|
|
25
|
-
{ key: 'content', value: JSON.stringify(variables), schemaId: activeSchema.id },
|
|
26
|
-
{ key: 'variables', value: varNames, schemaId: activeSchema.id },
|
|
27
|
-
{ key: 'readOnly', value: varNames.length === 0, schemaId: activeSchema.id },
|
|
28
|
-
]);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const placeholderRowEl = document
|
|
32
|
-
.getElementById('placeholder-dynamic-var')
|
|
33
|
-
?.closest('.ant-form-item') as HTMLElement;
|
|
34
|
-
if (!placeholderRowEl) {
|
|
35
|
-
throw new Error('Failed to find Ant form placeholder row to create dynamic variables inputs.');
|
|
36
|
-
}
|
|
37
|
-
placeholderRowEl.style.display = 'none';
|
|
38
|
-
|
|
39
|
-
// The wrapping form element has a display:flex which limits the width of the form fields, removing.
|
|
40
|
-
(rootElement.parentElement as HTMLElement).style.display = 'block';
|
|
41
|
-
|
|
42
|
-
if (varNames.length > 0) {
|
|
43
|
-
for (let variableName of varNames) {
|
|
44
|
-
const varRow = placeholderRowEl.cloneNode(true) as HTMLElement;
|
|
45
|
-
|
|
46
|
-
const textarea = varRow.querySelector('textarea') as HTMLTextAreaElement;
|
|
47
|
-
textarea.id = 'dynamic-var-' + variableName;
|
|
48
|
-
textarea.value = variables[variableName];
|
|
49
|
-
textarea.addEventListener('change', (e: Event) => {
|
|
50
|
-
if (variableName in variables) {
|
|
51
|
-
variables[variableName] = (e.target as HTMLTextAreaElement).value;
|
|
52
|
-
changeSchemas([
|
|
53
|
-
{ key: 'content', value: JSON.stringify(variables), schemaId: activeSchema.id },
|
|
54
|
-
]);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const label = varRow.querySelector('label') as HTMLLabelElement;
|
|
59
|
-
label.innerText = variableName;
|
|
60
|
-
|
|
61
|
-
varRow.style.display = 'block';
|
|
62
|
-
rootElement.appendChild(varRow);
|
|
63
|
-
}
|
|
64
|
-
} else {
|
|
65
|
-
const para = document.createElement('p');
|
|
66
|
-
// Extract color value to avoid unsafe property access
|
|
67
|
-
const colorValue = options?.theme?.token?.colorPrimary || '#168fe3';
|
|
68
|
-
const isValidColor =
|
|
69
|
-
/^#[0-9A-F]{6}$/i.test(colorValue) ||
|
|
70
|
-
/^(rgb|hsl)a?\(\s*([+-]?\d+%?\s*,\s*){2,3}[+-]?\d+%?\s*\)$/i.test(colorValue);
|
|
71
|
-
const safeColorValue = isValidColor ? colorValue : '#168fe3';
|
|
72
|
-
|
|
73
|
-
const typingInstructions = i18n('schemas.mvt.typingInstructions');
|
|
74
|
-
const sampleField = i18n('schemas.mvt.sampleField');
|
|
75
|
-
para.appendChild(document.createTextNode(typingInstructions + ' '));
|
|
76
|
-
const codeEl = document.createElement('code');
|
|
77
|
-
codeEl.style.color = safeColorValue;
|
|
78
|
-
codeEl.style.fontWeight = 'bold';
|
|
79
|
-
codeEl.textContent = `{${sampleField}}`;
|
|
80
|
-
para.appendChild(codeEl);
|
|
81
|
-
rootElement.appendChild(para);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export const propPanel: PropPanel<MultiVariableTextSchema> = {
|
|
86
|
-
schema: (propPanelProps: Omit<PropPanelWidgetProps, 'rootElement'>) => {
|
|
87
|
-
if (typeof parentPropPanel.schema !== 'function') {
|
|
88
|
-
throw new Error('Oops, is text schema no longer a function?');
|
|
89
|
-
}
|
|
90
|
-
// Safely call schema function with proper type handling
|
|
91
|
-
const parentSchema =
|
|
92
|
-
typeof parentPropPanel.schema === 'function' ? parentPropPanel.schema(propPanelProps) : {};
|
|
93
|
-
return {
|
|
94
|
-
...parentSchema,
|
|
95
|
-
'-------': { type: 'void', widget: 'Divider' },
|
|
96
|
-
dynamicVarContainer: {
|
|
97
|
-
title: 'Variables Sample Data',
|
|
98
|
-
type: 'string',
|
|
99
|
-
widget: 'Card',
|
|
100
|
-
span: 24,
|
|
101
|
-
properties: {
|
|
102
|
-
dynamicVariables: {
|
|
103
|
-
type: 'object',
|
|
104
|
-
widget: 'mapDynamicVariables',
|
|
105
|
-
bind: false,
|
|
106
|
-
span: 24,
|
|
107
|
-
},
|
|
108
|
-
placeholderDynamicVar: {
|
|
109
|
-
title: 'Placeholder Dynamic Variable',
|
|
110
|
-
type: 'string',
|
|
111
|
-
format: 'textarea',
|
|
112
|
-
props: {
|
|
113
|
-
id: 'placeholder-dynamic-var',
|
|
114
|
-
autoSize: {
|
|
115
|
-
minRows: 2,
|
|
116
|
-
maxRows: 5,
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
span: 24,
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
},
|
|
125
|
-
widgets: { ...parentPropPanel.widgets, mapDynamicVariables },
|
|
126
|
-
defaultSchema: {
|
|
127
|
-
...parentPropPanel.defaultSchema,
|
|
128
|
-
readOnly: false,
|
|
129
|
-
type: 'multiVariableText',
|
|
130
|
-
text: 'Add text here using {} for variables ',
|
|
131
|
-
width: 50,
|
|
132
|
-
height: 15,
|
|
133
|
-
content: '{}',
|
|
134
|
-
variables: [],
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const updateVariablesFromText = (text: string, variables: Record<string, string>): boolean => {
|
|
139
|
-
const matches = getVariableNames(text);
|
|
140
|
-
let changed = false;
|
|
141
|
-
|
|
142
|
-
if (matches.length > 0) {
|
|
143
|
-
const uniqueMatches = new Set(matches);
|
|
144
|
-
|
|
145
|
-
// Add any new variables
|
|
146
|
-
for (const variableName of uniqueMatches) {
|
|
147
|
-
if (!(variableName in variables)) {
|
|
148
|
-
// NOTE: We upper case the variable name as the default value
|
|
149
|
-
variables[variableName] = variableName.toUpperCase();
|
|
150
|
-
changed = true;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// Remove any that no longer exist
|
|
154
|
-
Object.keys(variables).forEach((variableName) => {
|
|
155
|
-
if (!uniqueMatches.has(variableName)) {
|
|
156
|
-
delete variables[variableName];
|
|
157
|
-
changed = true;
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
} else {
|
|
161
|
-
// No matches at all, so clear all variables
|
|
162
|
-
Object.keys(variables).forEach((variableName) => {
|
|
163
|
-
delete variables[variableName];
|
|
164
|
-
changed = true;
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return changed;
|
|
169
|
-
};
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { getDefaultFont, UIRenderProps } from '@pdfme/common';
|
|
2
|
-
import { MultiVariableTextSchema } from './types.js';
|
|
3
|
-
import {
|
|
4
|
-
uiRender as parentUiRender,
|
|
5
|
-
buildStyledTextContainer,
|
|
6
|
-
makeElementPlainTextContentEditable,
|
|
7
|
-
} from '../text/uiRender.js';
|
|
8
|
-
import { isEditable } from '../utils.js';
|
|
9
|
-
import { getFontKitFont } from '../text/helper.js';
|
|
10
|
-
import { substituteVariables } from './helper.js';
|
|
11
|
-
import { countUniqueVariableNames, getVariableIndices } from './variables.js';
|
|
12
|
-
|
|
13
|
-
export const uiRender = async (arg: UIRenderProps<MultiVariableTextSchema>) => {
|
|
14
|
-
const { value, schema, rootElement, mode, onChange, ...rest } = arg;
|
|
15
|
-
|
|
16
|
-
let text = schema.text;
|
|
17
|
-
let numVariables = schema.variables.length;
|
|
18
|
-
|
|
19
|
-
if (mode === 'form' && numVariables > 0) {
|
|
20
|
-
await formUiRender(arg);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
await parentUiRender({
|
|
25
|
-
value: isEditable(mode, schema) ? text : substituteVariables(text, value),
|
|
26
|
-
schema,
|
|
27
|
-
mode: mode === 'form' ? 'viewer' : mode, // if no variables for form it's just a viewer
|
|
28
|
-
rootElement,
|
|
29
|
-
onChange: (arg: { key: string; value: unknown } | { key: string; value: unknown }[]) => {
|
|
30
|
-
if (!Array.isArray(arg)) {
|
|
31
|
-
if (onChange) {
|
|
32
|
-
onChange({ key: 'text', value: arg.value });
|
|
33
|
-
}
|
|
34
|
-
} else {
|
|
35
|
-
throw new Error('onChange is not an array, the parent text plugin has changed...');
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
...rest,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const textBlock = rootElement.querySelector('#text-' + String(schema.id)) as HTMLDivElement;
|
|
42
|
-
if (!textBlock) {
|
|
43
|
-
throw new Error('Text block not found. Ensure the text block has an id of "text-" + schema.id');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (mode === 'designer') {
|
|
47
|
-
textBlock.addEventListener('keyup', (event: KeyboardEvent) => {
|
|
48
|
-
text = textBlock.textContent || '';
|
|
49
|
-
if (keyPressShouldBeChecked(event)) {
|
|
50
|
-
const newNumVariables = countUniqueVariableNames(text);
|
|
51
|
-
if (numVariables !== newNumVariables) {
|
|
52
|
-
// If variables were modified during this keypress, we trigger a change
|
|
53
|
-
if (onChange) {
|
|
54
|
-
onChange({ key: 'text', value: text });
|
|
55
|
-
}
|
|
56
|
-
numVariables = newNumVariables;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const formUiRender = async (arg: UIRenderProps<MultiVariableTextSchema>) => {
|
|
64
|
-
const { value, schema, rootElement, onChange, stopEditing, theme, _cache, options } = arg;
|
|
65
|
-
const rawText = schema.text;
|
|
66
|
-
|
|
67
|
-
if (rootElement.parentElement) {
|
|
68
|
-
// remove the outline for the whole schema, we'll apply outlines on each individual variable field instead
|
|
69
|
-
rootElement.parentElement.style.outline = '';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
let variables: Record<string, string> = {};
|
|
73
|
-
if (value) {
|
|
74
|
-
try {
|
|
75
|
-
const parsed = JSON.parse(value);
|
|
76
|
-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
77
|
-
variables = parsed as Record<string, string>;
|
|
78
|
-
}
|
|
79
|
-
} catch {
|
|
80
|
-
// value is not valid JSON — use empty variables
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
const variableIndices = getVariableIndices(rawText);
|
|
84
|
-
const substitutedText = substituteVariables(rawText, variables);
|
|
85
|
-
const font = options?.font || getDefaultFont();
|
|
86
|
-
const fontKitFont = await getFontKitFont(
|
|
87
|
-
schema.fontName,
|
|
88
|
-
font,
|
|
89
|
-
_cache as Map<string, import('fontkit').Font>,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
const textBlock = buildStyledTextContainer(arg, fontKitFont, substitutedText);
|
|
93
|
-
|
|
94
|
-
// Construct content-editable spans for each variable within the string
|
|
95
|
-
let inVarString = false;
|
|
96
|
-
|
|
97
|
-
for (let i = 0; i < rawText.length; i++) {
|
|
98
|
-
const variableName = variableIndices.get(i);
|
|
99
|
-
|
|
100
|
-
if (variableName) {
|
|
101
|
-
inVarString = true;
|
|
102
|
-
let span = document.createElement('span');
|
|
103
|
-
span.style.outline = `${theme.colorPrimary} dashed 1px`;
|
|
104
|
-
makeElementPlainTextContentEditable(span);
|
|
105
|
-
span.textContent = variables[variableName];
|
|
106
|
-
span.addEventListener('blur', (e: Event) => {
|
|
107
|
-
const newValue = (e.target as HTMLSpanElement).textContent || '';
|
|
108
|
-
if (newValue !== variables[variableName]) {
|
|
109
|
-
variables[variableName] = newValue;
|
|
110
|
-
if (onChange) onChange({ key: 'content', value: JSON.stringify(variables) });
|
|
111
|
-
if (stopEditing) stopEditing();
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
textBlock.appendChild(span);
|
|
115
|
-
} else if (inVarString) {
|
|
116
|
-
if (rawText[i] === '}') {
|
|
117
|
-
inVarString = false;
|
|
118
|
-
}
|
|
119
|
-
} else {
|
|
120
|
-
let span = document.createElement('span');
|
|
121
|
-
span.style.letterSpacing = rawText.length === i + 1 ? '0' : 'inherit';
|
|
122
|
-
span.textContent = rawText[i];
|
|
123
|
-
textBlock.appendChild(span);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* An optimisation to try to minimise jank while typing.
|
|
130
|
-
* Only check whether variables were modified based on certain key presses.
|
|
131
|
-
* Regex would otherwise be performed on every key press (which isn't terrible, but this code helps).
|
|
132
|
-
*/
|
|
133
|
-
const keyPressShouldBeChecked = (event: KeyboardEvent) => {
|
|
134
|
-
if (
|
|
135
|
-
event.key === 'ArrowUp' ||
|
|
136
|
-
event.key === 'ArrowDown' ||
|
|
137
|
-
event.key === 'ArrowLeft' ||
|
|
138
|
-
event.key === 'ArrowRight'
|
|
139
|
-
) {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const selection = window.getSelection();
|
|
144
|
-
const contenteditable = event.target as HTMLDivElement;
|
|
145
|
-
|
|
146
|
-
const isCursorAtEnd = selection?.focusOffset === contenteditable?.textContent?.length;
|
|
147
|
-
if (isCursorAtEnd) {
|
|
148
|
-
return event.key === '}' || event.key === 'Backspace' || event.key === 'Delete';
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const isCursorAtStart = selection?.anchorOffset === 0;
|
|
152
|
-
if (isCursorAtStart) {
|
|
153
|
-
return event.key === '{' || event.key === 'Backspace' || event.key === 'Delete';
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return true;
|
|
157
|
-
};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export type VariableMatch = {
|
|
2
|
-
name: string;
|
|
3
|
-
startIndex: number;
|
|
4
|
-
endIndex: number;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export type VariableIndices = Map<number, string>;
|
|
8
|
-
|
|
9
|
-
export const visitVariables = (
|
|
10
|
-
content: string,
|
|
11
|
-
visitor: (match: VariableMatch) => void,
|
|
12
|
-
): void => {
|
|
13
|
-
let startIndex = -1;
|
|
14
|
-
|
|
15
|
-
for (let i = 0; i < content.length; i++) {
|
|
16
|
-
const char = content[i];
|
|
17
|
-
|
|
18
|
-
if (char === '{') {
|
|
19
|
-
// Restart from the latest opener so malformed input behaves like /{([^{}]+)}/g
|
|
20
|
-
// without requiring backtracking.
|
|
21
|
-
startIndex = i;
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (char === '}' && startIndex !== -1) {
|
|
26
|
-
const name = content.slice(startIndex + 1, i);
|
|
27
|
-
if (name.length > 0) {
|
|
28
|
-
visitor({ name, startIndex, endIndex: i });
|
|
29
|
-
}
|
|
30
|
-
startIndex = -1;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const getVariableIndices = (content: string): VariableIndices => {
|
|
36
|
-
const indices: VariableIndices = new Map();
|
|
37
|
-
|
|
38
|
-
visitVariables(content, ({ name, startIndex }) => {
|
|
39
|
-
indices.set(startIndex, name);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return indices;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const countUniqueVariableNames = (content: string): number => {
|
|
46
|
-
const variableNames = new Set<string>();
|
|
47
|
-
|
|
48
|
-
visitVariables(content, ({ name }) => {
|
|
49
|
-
variableNames.add(name);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
return variableNames.size;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export const getVariableNames = (content: string): string[] => {
|
|
56
|
-
const variableNames: string[] = [];
|
|
57
|
-
|
|
58
|
-
visitVariables(content, ({ name }) => {
|
|
59
|
-
variableNames.push(name);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return variableNames;
|
|
63
|
-
};
|
package/src/radioGroup/index.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { Plugin, Schema } from '@pdfme/common';
|
|
2
|
-
import { Circle, CircleDot } from 'lucide';
|
|
3
|
-
import svg from '../graphics/svg.js';
|
|
4
|
-
import { isEditable, createSvgStr } from '../utils.js';
|
|
5
|
-
import { HEX_COLOR_PATTERN } from '../constants.js';
|
|
6
|
-
|
|
7
|
-
const defaultStroke = 'currentColor';
|
|
8
|
-
|
|
9
|
-
const getCheckedIcon = (stroke = defaultStroke) => createSvgStr(CircleDot, { stroke });
|
|
10
|
-
const getUncheckedIcon = (stroke = defaultStroke) => createSvgStr(Circle, { stroke });
|
|
11
|
-
|
|
12
|
-
interface RadioGroup extends Schema {
|
|
13
|
-
group: string;
|
|
14
|
-
color: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const getIcon = ({ value, color }: { value: string; color: string }) =>
|
|
18
|
-
value === 'true' ? getCheckedIcon(color) : getUncheckedIcon(color);
|
|
19
|
-
|
|
20
|
-
const eventEmitter = new EventTarget();
|
|
21
|
-
|
|
22
|
-
interface RadioButtonState {
|
|
23
|
-
value: string;
|
|
24
|
-
onChange: (arg: { key: string; value: string }) => void;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const radioButtonStates = new Map<string, RadioButtonState>();
|
|
28
|
-
const eventListeners = new Map<string, EventListener>();
|
|
29
|
-
|
|
30
|
-
const schema: Plugin<RadioGroup> = {
|
|
31
|
-
ui: (arg) => {
|
|
32
|
-
const { schema, value, onChange, rootElement, mode } = arg;
|
|
33
|
-
const container = document.createElement('div');
|
|
34
|
-
container.style.width = '100%';
|
|
35
|
-
container.style.height = '100%';
|
|
36
|
-
|
|
37
|
-
if (onChange) {
|
|
38
|
-
radioButtonStates.set(schema.name, { value, onChange });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const oldListener = eventListeners.get(schema.name);
|
|
42
|
-
if (oldListener) {
|
|
43
|
-
eventEmitter.removeEventListener(`group-${schema.group}`, oldListener);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const handleGroupEvent = (event: Event) => {
|
|
47
|
-
const customEvent = event as CustomEvent<string>;
|
|
48
|
-
const selectedSchemaName = customEvent.detail;
|
|
49
|
-
if (selectedSchemaName !== schema.name) {
|
|
50
|
-
const radioButtonState = radioButtonStates.get(schema.name);
|
|
51
|
-
if (!radioButtonState) return;
|
|
52
|
-
if (radioButtonState.value === 'true') {
|
|
53
|
-
radioButtonState.onChange({ key: 'content', value: 'false' });
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
eventListeners.set(schema.name, handleGroupEvent);
|
|
59
|
-
eventEmitter.addEventListener(`group-${schema.group}`, handleGroupEvent);
|
|
60
|
-
|
|
61
|
-
if (isEditable(mode, schema)) {
|
|
62
|
-
container.addEventListener('click', () => {
|
|
63
|
-
if (value !== 'true' && onChange) {
|
|
64
|
-
onChange({ key: 'content', value: 'true' });
|
|
65
|
-
radioButtonStates.set(schema.name, { value: 'true', onChange });
|
|
66
|
-
eventEmitter.dispatchEvent(
|
|
67
|
-
new CustomEvent(`group-${schema.group}`, { detail: schema.name }),
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
void svg.ui({
|
|
74
|
-
...arg,
|
|
75
|
-
rootElement: container,
|
|
76
|
-
mode: 'viewer',
|
|
77
|
-
value: getIcon({ value, color: schema.color }),
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
rootElement.appendChild(container);
|
|
81
|
-
},
|
|
82
|
-
pdf: (arg) =>
|
|
83
|
-
svg.pdf(Object.assign(arg, { value: getIcon({ value: arg.value, color: arg.schema.color }) })),
|
|
84
|
-
propPanel: {
|
|
85
|
-
schema: ({ i18n }) => ({
|
|
86
|
-
color: {
|
|
87
|
-
title: i18n('schemas.color'),
|
|
88
|
-
type: 'string',
|
|
89
|
-
widget: 'color',
|
|
90
|
-
props: {
|
|
91
|
-
disabledAlpha: true,
|
|
92
|
-
},
|
|
93
|
-
required: true,
|
|
94
|
-
rules: [{ pattern: HEX_COLOR_PATTERN, message: i18n('validation.hexColor') }],
|
|
95
|
-
},
|
|
96
|
-
group: {
|
|
97
|
-
title: i18n('schemas.radioGroup.groupName'),
|
|
98
|
-
type: 'string',
|
|
99
|
-
},
|
|
100
|
-
}),
|
|
101
|
-
defaultSchema: {
|
|
102
|
-
name: '',
|
|
103
|
-
type: 'radioGroup',
|
|
104
|
-
content: 'false',
|
|
105
|
-
position: { x: 0, y: 0 },
|
|
106
|
-
width: 8,
|
|
107
|
-
height: 8,
|
|
108
|
-
group: 'MyGroup',
|
|
109
|
-
color: '#000000',
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
icon: getCheckedIcon(),
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
export default schema;
|
package/src/sanitize.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import DOMPurify from 'dompurify';
|
|
2
|
-
|
|
3
|
-
export const sanitizeSVG = (svgString: string): string => {
|
|
4
|
-
return DOMPurify.sanitize(svgString, {
|
|
5
|
-
USE_PROFILES: { svg: true, svgFilters: true },
|
|
6
|
-
FORBID_TAGS: [
|
|
7
|
-
'script',
|
|
8
|
-
'foreignObject',
|
|
9
|
-
'use',
|
|
10
|
-
'embed',
|
|
11
|
-
'iframe',
|
|
12
|
-
'object',
|
|
13
|
-
'link',
|
|
14
|
-
'style',
|
|
15
|
-
'animate',
|
|
16
|
-
'animateMotion',
|
|
17
|
-
'animateTransform',
|
|
18
|
-
'set',
|
|
19
|
-
],
|
|
20
|
-
FORBID_ATTR: [
|
|
21
|
-
'onload',
|
|
22
|
-
'onerror',
|
|
23
|
-
'onclick',
|
|
24
|
-
'onmouseover',
|
|
25
|
-
'onmouseout',
|
|
26
|
-
'onmousedown',
|
|
27
|
-
'onmouseup',
|
|
28
|
-
'onfocus',
|
|
29
|
-
'onblur',
|
|
30
|
-
'onchange',
|
|
31
|
-
'onsubmit',
|
|
32
|
-
'onreset',
|
|
33
|
-
'onselect',
|
|
34
|
-
'onabort',
|
|
35
|
-
'oninput',
|
|
36
|
-
'onkeydown',
|
|
37
|
-
'onkeypress',
|
|
38
|
-
'onkeyup',
|
|
39
|
-
'onbegin',
|
|
40
|
-
'onend',
|
|
41
|
-
'onrepeat',
|
|
42
|
-
'href',
|
|
43
|
-
'xlink:href',
|
|
44
|
-
'src',
|
|
45
|
-
'action',
|
|
46
|
-
'formaction',
|
|
47
|
-
],
|
|
48
|
-
KEEP_CONTENT: false,
|
|
49
|
-
});
|
|
50
|
-
};
|