@pdfme/schemas 5.0.0-dev.3 → 5.0.0-dev.5

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.
Files changed (53) hide show
  1. package/dist/cjs/src/date/date.js +55 -0
  2. package/dist/cjs/src/date/date.js.map +1 -0
  3. package/dist/cjs/src/date/dateTime.js +97 -0
  4. package/dist/cjs/src/date/dateTime.js.map +1 -0
  5. package/dist/cjs/src/date/helper.js +208 -0
  6. package/dist/cjs/src/date/helper.js.map +1 -0
  7. package/dist/cjs/src/date/time.js +26 -0
  8. package/dist/cjs/src/date/time.js.map +1 -0
  9. package/dist/cjs/src/date/types.js +3 -0
  10. package/dist/cjs/src/date/types.js.map +1 -0
  11. package/dist/cjs/src/index.js +9 -1
  12. package/dist/cjs/src/index.js.map +1 -1
  13. package/dist/cjs/src/select/index.js +163 -0
  14. package/dist/cjs/src/select/index.js.map +1 -0
  15. package/dist/cjs/src/text/extraFormatter.js.map +1 -1
  16. package/dist/cjs/src/text/uiRender.js +6 -4
  17. package/dist/cjs/src/text/uiRender.js.map +1 -1
  18. package/dist/esm/src/date/date.js +53 -0
  19. package/dist/esm/src/date/date.js.map +1 -0
  20. package/dist/esm/src/date/dateTime.js +95 -0
  21. package/dist/esm/src/date/dateTime.js.map +1 -0
  22. package/dist/esm/src/date/helper.js +201 -0
  23. package/dist/esm/src/date/helper.js.map +1 -0
  24. package/dist/esm/src/date/time.js +24 -0
  25. package/dist/esm/src/date/time.js.map +1 -0
  26. package/dist/esm/src/date/types.js +2 -0
  27. package/dist/esm/src/date/types.js.map +1 -0
  28. package/dist/esm/src/index.js +5 -1
  29. package/dist/esm/src/index.js.map +1 -1
  30. package/dist/esm/src/select/index.js +158 -0
  31. package/dist/esm/src/select/index.js.map +1 -0
  32. package/dist/esm/src/text/extraFormatter.js.map +1 -1
  33. package/dist/esm/src/text/uiRender.js +3 -3
  34. package/dist/esm/src/text/uiRender.js.map +1 -1
  35. package/dist/types/src/date/date.d.ts +2 -0
  36. package/dist/types/src/date/dateTime.d.ts +2 -0
  37. package/dist/types/src/date/helper.d.ts +9 -0
  38. package/dist/types/src/date/time.d.ts +2 -0
  39. package/dist/types/src/date/types.d.ts +12 -0
  40. package/dist/types/src/index.d.ts +5 -1
  41. package/dist/types/src/select/index.d.ts +7 -0
  42. package/dist/types/src/text/extraFormatter.d.ts +7 -2
  43. package/dist/types/src/text/uiRender.d.ts +4 -0
  44. package/package.json +2 -1
  45. package/src/date/date.ts +60 -0
  46. package/src/date/dateTime.ts +102 -0
  47. package/src/date/helper.ts +262 -0
  48. package/src/date/time.ts +31 -0
  49. package/src/date/types.ts +13 -0
  50. package/src/index.ts +8 -0
  51. package/src/select/index.ts +199 -0
  52. package/src/text/extraFormatter.ts +7 -4
  53. package/src/text/uiRender.ts +4 -4
@@ -0,0 +1,262 @@
1
+ import type * as CSS from 'csstype';
2
+ import { format } from 'date-fns';
3
+ import { zhCN, ja, ko, ar, th, pl, it, de, es, fr, Locale } from 'date-fns/locale';
4
+ import {
5
+ Lang,
6
+ Plugin,
7
+ getDefaultFont,
8
+ getFallbackFontName,
9
+ DEFAULT_FONT_NAME,
10
+ PropPanelSchema,
11
+ } from '@pdfme/common';
12
+ import text from '../text';
13
+ import { DEFAULT_OPACITY, HEX_COLOR_PATTERN } from '../constants.js';
14
+ import { mapVerticalAlignToFlex, getBackgroundColor } from '../text/uiRender';
15
+ import { getFontKitFont, getBrowserVerticalFontAdjustments } from '../text/helper.js';
16
+ import {
17
+ DEFAULT_FONT_SIZE,
18
+ DEFAULT_ALIGNMENT,
19
+ DEFAULT_VERTICAL_ALIGNMENT,
20
+ DEFAULT_LINE_HEIGHT,
21
+ DEFAULT_CHARACTER_SPACING,
22
+ DEFAULT_FONT_COLOR,
23
+ } from '../text/constants.js';
24
+ import { DateSchema } from './types';
25
+ import { getExtraFormatterSchema, Formatter } from '../text/extraFormatter';
26
+
27
+ const getLocale = (lang: Lang): Locale | undefined =>
28
+ ({ en: undefined, zh: zhCN, ja, ko, ar, th, pl, it, de, es, fr }[lang]);
29
+
30
+ export const getPlugin = ({
31
+ type,
32
+ defaultFormat,
33
+ icon,
34
+ inputType,
35
+ formatsByLang,
36
+ }: {
37
+ type: 'date' | 'time' | 'dateTime';
38
+ defaultFormat: string;
39
+ icon: string;
40
+ inputType: string;
41
+ formatsByLang: Record<Lang, string[]>;
42
+ }) => {
43
+ const plugin: Plugin<DateSchema> = {
44
+ ui: async (arg) => {
45
+ const { schema, value, onChange, rootElement, mode, options, _cache } = arg;
46
+ rootElement.innerHTML = '';
47
+
48
+ const font = options?.font || getDefaultFont();
49
+ const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
50
+
51
+ const { topAdj, bottomAdj } = getBrowserVerticalFontAdjustments(
52
+ fontKitFont,
53
+ schema.fontSize ?? DEFAULT_FONT_SIZE,
54
+ DEFAULT_LINE_HEIGHT,
55
+ schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT
56
+ );
57
+
58
+ const topAdjustment = topAdj.toString();
59
+ const bottomAdjustment = bottomAdj.toString();
60
+ const textStyle: CSS.Properties = {
61
+ fontFamily: schema.fontName ? `'${schema.fontName}'` : 'inherit',
62
+ color: schema.fontColor ?? DEFAULT_FONT_COLOR,
63
+ fontSize: `${schema.fontSize ?? DEFAULT_FONT_SIZE}pt`,
64
+ letterSpacing: `${schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING}pt`,
65
+ textAlign: schema.alignment ?? DEFAULT_ALIGNMENT,
66
+ backgroundColor: getBackgroundColor(value, schema),
67
+
68
+ margin: '0',
69
+ width: `${schema.width}mm`,
70
+ height: `${schema.height}mm`,
71
+ display: 'flex',
72
+ flexDirection: 'column',
73
+ justifyContent: mapVerticalAlignToFlex(schema.verticalAlignment),
74
+ paddingTop: `${topAdjustment}px`,
75
+ marginBottom: `${bottomAdjustment}px`,
76
+ position: 'relative',
77
+ };
78
+
79
+ const textElement = document.createElement('p');
80
+ Object.assign(textElement.style, textStyle);
81
+ rootElement.appendChild(textElement);
82
+
83
+ textElement.textContent = value
84
+ ? format(
85
+ type === 'time' ? new Date(`2021-01-01T${value}`) : new Date(value),
86
+ schema.format,
87
+ { locale: getLocale(options?.lang || 'en') }
88
+ )
89
+ : '';
90
+
91
+ if (mode !== 'viewer' && !(mode === 'form' && schema.readOnly)) {
92
+ const dateTimeInput = document.createElement('input');
93
+ dateTimeInput.type = inputType;
94
+ dateTimeInput.value = value;
95
+
96
+ const dateTimeInputStyle: CSS.Properties = {
97
+ ...textStyle,
98
+ opacity: '0',
99
+ position: 'absolute',
100
+ top: '0',
101
+ left: '0',
102
+ border: 'none',
103
+ zIndex: '-1',
104
+ };
105
+
106
+ Object.assign(dateTimeInput.style, dateTimeInputStyle);
107
+ rootElement.appendChild(dateTimeInput);
108
+
109
+ textElement.style.cursor = 'pointer';
110
+ textElement.addEventListener('click', () => {
111
+ dateTimeInput.showPicker();
112
+ textElement.style.opacity = '0';
113
+ dateTimeInput.style.opacity = '1';
114
+ dateTimeInput.style.zIndex = '1';
115
+ });
116
+
117
+ dateTimeInput.addEventListener('change', (e) => {
118
+ if (onChange && e.target instanceof HTMLInputElement) {
119
+ onChange({ key: 'content', value: e.target.value });
120
+ }
121
+ });
122
+
123
+ dateTimeInput.addEventListener('blur', () => {
124
+ textElement.style.opacity = '1';
125
+ dateTimeInput.style.opacity = '0';
126
+ dateTimeInput.style.zIndex = '-1';
127
+ });
128
+
129
+ const removeButton = document.createElement('button');
130
+ removeButton.textContent = 'x';
131
+ const buttonWidth = 30;
132
+ const removeButtonStyle: CSS.Properties = {
133
+ position: 'absolute',
134
+ top: '0px',
135
+ right: `-${buttonWidth}px`,
136
+ padding: '5px',
137
+ width: `${buttonWidth}px`,
138
+ height: `${buttonWidth}px`,
139
+ };
140
+ Object.assign(removeButton.style, removeButtonStyle);
141
+ removeButton.addEventListener('click', () => {
142
+ onChange && onChange({ key: 'content', value: '' });
143
+ });
144
+ rootElement.appendChild(removeButton);
145
+ }
146
+ },
147
+ pdf: (arg) => {
148
+ const { schema, value, options } = arg;
149
+ if (!value) return void 0;
150
+ const lang = (options.language || 'en') as Lang;
151
+ const locale = getLocale(lang);
152
+ const date = schema.type === 'time' ? new Date(`2021-01-01T${value}`) : new Date(value);
153
+ const formattedValue = format(date, schema.format, { locale });
154
+ return text.pdf(
155
+ Object.assign(arg, {
156
+ value: formattedValue,
157
+ schema: { ...schema, lineHeight: DEFAULT_LINE_HEIGHT },
158
+ })
159
+ );
160
+ },
161
+ propPanel: {
162
+ schema: ({ options, i18n }) => {
163
+ const font = options.font || { [DEFAULT_FONT_NAME]: { data: '', fallback: true } };
164
+ const lang = options.lang || 'en';
165
+ const locale = getLocale(lang);
166
+
167
+ const fontNames = Object.keys(font);
168
+ const fallbackFontName = getFallbackFontName(font);
169
+
170
+ const formatter = getExtraFormatterSchema(i18n);
171
+ formatter.buttons = formatter.buttons.filter(
172
+ (button) => button.key !== Formatter.STRIKETHROUGH && button.key !== Formatter.UNDERLINE
173
+ );
174
+
175
+ const currentDate = new Date();
176
+
177
+ const dateSchema: Record<string, PropPanelSchema> = {
178
+ format: {
179
+ title: i18n('schemas.date.format'),
180
+ type: 'string',
181
+ widget: 'select',
182
+ props: {
183
+ options: formatsByLang[lang].map((formatString) => ({
184
+ label: `${formatString} (${format(currentDate, formatString, { locale })})`,
185
+ value: formatString,
186
+ })),
187
+ },
188
+ span: 24,
189
+ },
190
+ fontName: {
191
+ title: i18n('schemas.text.fontName'),
192
+ type: 'string',
193
+ widget: 'select',
194
+ default: fallbackFontName,
195
+ props: { options: fontNames.map((name) => ({ label: name, value: name })) },
196
+ span: 12,
197
+ },
198
+ fontSize: {
199
+ title: i18n('schemas.text.size'),
200
+ type: 'number',
201
+ widget: 'inputNumber',
202
+ span: 6,
203
+ props: { min: 0 },
204
+ },
205
+ characterSpacing: {
206
+ title: i18n('schemas.text.spacing'),
207
+ type: 'number',
208
+ widget: 'inputNumber',
209
+ span: 6,
210
+ props: { min: 0 },
211
+ },
212
+ formatter,
213
+ fontColor: {
214
+ title: i18n('schemas.textColor'),
215
+ type: 'string',
216
+ widget: 'color',
217
+ rules: [
218
+ {
219
+ pattern: HEX_COLOR_PATTERN,
220
+ message: i18n('validation.hexColor'),
221
+ },
222
+ ],
223
+ },
224
+ backgroundColor: {
225
+ title: i18n('schemas.bgColor'),
226
+ type: 'string',
227
+ widget: 'color',
228
+ rules: [
229
+ {
230
+ pattern: HEX_COLOR_PATTERN,
231
+ message: i18n('validation.hexColor'),
232
+ },
233
+ ],
234
+ },
235
+ };
236
+
237
+ return dateSchema;
238
+ },
239
+ defaultSchema: {
240
+ name: '',
241
+ format: defaultFormat,
242
+ type,
243
+ content: format(new Date(), defaultFormat),
244
+ position: { x: 0, y: 0 },
245
+ width: 70,
246
+ height: 10,
247
+ rotate: 0,
248
+ alignment: DEFAULT_ALIGNMENT,
249
+ verticalAlignment: DEFAULT_VERTICAL_ALIGNMENT,
250
+ fontSize: DEFAULT_FONT_SIZE,
251
+ characterSpacing: DEFAULT_CHARACTER_SPACING,
252
+ fontColor: DEFAULT_FONT_COLOR,
253
+ fontName: undefined,
254
+ backgroundColor: '',
255
+ opacity: DEFAULT_OPACITY,
256
+ },
257
+ },
258
+ icon,
259
+ };
260
+
261
+ return plugin;
262
+ };
@@ -0,0 +1,31 @@
1
+ import { Lang } from '@pdfme/common';
2
+ import { getPlugin } from './helper';
3
+
4
+ const type = 'time';
5
+
6
+ const inputType = 'time';
7
+
8
+ const defaultFormat = 'HH:mm';
9
+
10
+ const formatsByLang: Record<Lang, string[]> = {
11
+ en: [defaultFormat, 'hh:mm a', 'HH:mm:ss', 'hh:mm:ss a'],
12
+ zh: [defaultFormat, 'HH时mm分', 'HH:mm:ss'],
13
+ ja: [defaultFormat, 'HH時mm分', 'HH:mm:ss'],
14
+ ko: [defaultFormat, 'a h시 mm분', 'HH:mm:ss'],
15
+ ar: [defaultFormat, 'hh:mm a', 'HH:mm:ss'],
16
+ th: [defaultFormat, 'HH.mm', 'HH:mm:ss'],
17
+ pl: [defaultFormat, 'HH:mm:ss'],
18
+ it: [defaultFormat, 'HH.mm', 'HH:mm:ss'],
19
+ de: [defaultFormat, 'HH.mm', 'HH:mm:ss'],
20
+ es: [defaultFormat, 'hh:mm a', 'HH:mm:ss'],
21
+ fr: [defaultFormat, 'HH:mm:ss'],
22
+ };
23
+
24
+ const icon =
25
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" ' +
26
+ 'viewBox="0 0 24 24" fill="none" stroke="currentColor" ' +
27
+ 'stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ' +
28
+ 'class="lucide lucide-clock"><circle cx="12" cy="12" r="10"/>' +
29
+ '<polyline points="12 6 12 12 16 14"/></svg>';
30
+
31
+ export default getPlugin({ type, defaultFormat, icon, inputType, formatsByLang });
@@ -0,0 +1,13 @@
1
+ import { Schema } from '@pdfme/common';
2
+ import { ALIGNMENT, VERTICAL_ALIGNMENT } from '../text/types';
3
+
4
+ export interface DateSchema extends Schema {
5
+ format: string;
6
+ fontName?: string;
7
+ alignment: ALIGNMENT;
8
+ verticalAlignment: VERTICAL_ALIGNMENT;
9
+ fontSize: number;
10
+ characterSpacing: number;
11
+ fontColor: string;
12
+ backgroundColor: string;
13
+ }
package/src/index.ts CHANGED
@@ -6,6 +6,10 @@ import barcodes from './barcodes/index.js';
6
6
  import line from './shapes/line.js';
7
7
  import table from './tables/index.js';
8
8
  import { rectangle, ellipse } from './shapes/rectAndEllipse.js';
9
+ import dateTime from './date/dateTime.js';
10
+ import date from './date/date.js';
11
+ import time from './date/time.js';
12
+ import select from './select/index.js';
9
13
 
10
14
  const builtInPlugins = { Text: text };
11
15
 
@@ -21,4 +25,8 @@ export {
21
25
  line,
22
26
  rectangle,
23
27
  ellipse,
28
+ dateTime,
29
+ date,
30
+ time,
31
+ select,
24
32
  };
@@ -0,0 +1,199 @@
1
+ import type * as CSS from 'csstype';
2
+ import { propPanel as parentPropPanel } from '../text/propPanel';
3
+ import { Plugin, PropPanelWidgetProps, SchemaForUI } from '@pdfme/common';
4
+ import text from '../text';
5
+ import { TextSchema } from '../text/types';
6
+
7
+ const selectIcon =
8
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg>';
9
+
10
+ interface Select extends TextSchema {
11
+ options: string[];
12
+ }
13
+
14
+ const addOptions = (props: PropPanelWidgetProps) => {
15
+ const { rootElement, changeSchemas, activeSchema, i18n } = props;
16
+
17
+ rootElement.innerHTML = '';
18
+
19
+ const selectSchema = activeSchema as SchemaForUI & Select;
20
+ const currentOptions = selectSchema.options ? [...selectSchema.options] : [];
21
+
22
+ const container = document.createElement('div');
23
+
24
+ const inputStyle = {
25
+ flexGrow: '1',
26
+ padding: '8px',
27
+ border: '1px solid #ccc',
28
+ borderRadius: '4px',
29
+ };
30
+
31
+ const buttonStyle = { border: 'none', borderRadius: '4px', cursor: 'pointer' };
32
+
33
+ const updateSchemas = () => {
34
+ changeSchemas([
35
+ { key: 'options', value: currentOptions, schemaId: activeSchema.id },
36
+ { key: 'content', value: currentOptions[0] || '', schemaId: activeSchema.id },
37
+ ]);
38
+ };
39
+
40
+ const formContainer = document.createElement('div');
41
+ Object.assign(formContainer.style, {
42
+ display: 'flex',
43
+ alignItems: 'center',
44
+ marginBottom: '10px',
45
+ });
46
+
47
+ const input = document.createElement('input');
48
+ input.type = 'text';
49
+ input.placeholder = i18n('schemas.select.optionPlaceholder');
50
+ Object.assign(input.style, inputStyle, { marginRight: '10px' });
51
+
52
+ const addButton = document.createElement('button');
53
+ addButton.textContent = '+';
54
+ Object.assign(addButton.style, buttonStyle, {
55
+ width: '25px',
56
+ height: '25px',
57
+ padding: '4px 8px',
58
+ });
59
+
60
+ addButton.addEventListener('click', () => {
61
+ const newValue = input.value.trim();
62
+ if (newValue) {
63
+ currentOptions.push(newValue);
64
+ updateSchemas();
65
+ renderOptions();
66
+ input.value = '';
67
+ }
68
+ });
69
+
70
+ formContainer.appendChild(input);
71
+ formContainer.appendChild(addButton);
72
+
73
+ const optionsList = document.createElement('ul');
74
+ Object.assign(optionsList.style, { listStyle: 'none', padding: '0' });
75
+
76
+ const renderOptions = () => {
77
+ optionsList.innerHTML = '';
78
+ currentOptions.forEach((option, index) => {
79
+ const li = document.createElement('li');
80
+ Object.assign(li.style, { display: 'flex', alignItems: 'center', marginBottom: '5px' });
81
+
82
+ const optionInput = document.createElement('input');
83
+ optionInput.type = 'text';
84
+ optionInput.value = option;
85
+ Object.assign(optionInput.style, inputStyle, { marginRight: '10px' });
86
+
87
+ optionInput.addEventListener('change', () => {
88
+ currentOptions[index] = optionInput.value;
89
+ updateSchemas();
90
+ });
91
+
92
+ const removeButton = document.createElement('button');
93
+ removeButton.textContent = 'x';
94
+ Object.assign(removeButton.style, buttonStyle, { padding: '4px 8px' });
95
+
96
+ removeButton.addEventListener('click', () => {
97
+ currentOptions.splice(index, 1);
98
+ updateSchemas();
99
+ renderOptions();
100
+ });
101
+
102
+ li.appendChild(optionInput);
103
+ li.appendChild(removeButton);
104
+ optionsList.appendChild(li);
105
+ });
106
+ };
107
+
108
+ container.appendChild(formContainer);
109
+ container.appendChild(optionsList);
110
+ rootElement.appendChild(container);
111
+
112
+ renderOptions();
113
+ };
114
+
115
+ const schema: Plugin<Select> = {
116
+ ui: async (arg) => {
117
+ const { schema, value, onChange, rootElement, mode } = arg;
118
+ await text.ui(Object.assign(arg, { mode: 'viewer' }));
119
+
120
+ if (mode !== 'viewer' && !(mode === 'form' && schema.readOnly)) {
121
+ const buttonWidth = 30;
122
+ const selectButton = document.createElement('button');
123
+ selectButton.innerHTML = selectIcon;
124
+ const selectButtonStyle: CSS.Properties = {
125
+ position: 'absolute',
126
+ zIndex: -1,
127
+ right: `-${buttonWidth}px`,
128
+ top: '0',
129
+ padding: '0',
130
+ margin: '0',
131
+ cursor: 'pointer',
132
+ height: `${buttonWidth}px`,
133
+ width: `${buttonWidth}px`,
134
+ };
135
+ Object.assign(selectButton.style, selectButtonStyle);
136
+
137
+ rootElement.appendChild(selectButton);
138
+
139
+ const selectElement = document.createElement('select');
140
+ const selectElementStyle: CSS.Properties = {
141
+ opacity: '0',
142
+ position: 'absolute',
143
+ width: `calc(100% + ${buttonWidth}px)`,
144
+ height: '100%',
145
+ top: '0',
146
+ left: '0',
147
+ appearance: 'initial',
148
+ };
149
+ Object.assign(selectElement.style, selectElementStyle);
150
+ selectElement.value = value;
151
+
152
+ selectElement.addEventListener('change', (e) => {
153
+ if (onChange && e.target instanceof HTMLSelectElement) {
154
+ onChange && onChange({ key: 'content', value: e.target.value });
155
+ }
156
+ });
157
+
158
+ selectElement.innerHTML = schema.options
159
+ .map(
160
+ (option) =>
161
+ `<option value="${option}" ${option === value ? 'selected' : ''}>${option}</option>`
162
+ )
163
+ .join('');
164
+ rootElement.appendChild(selectElement);
165
+ }
166
+ },
167
+ pdf: text.pdf,
168
+ propPanel: {
169
+ ...text.propPanel,
170
+ widgets: { ...parentPropPanel.widgets, addOptions },
171
+ schema: (propPanelProps: Omit<PropPanelWidgetProps, 'rootElement'>) => {
172
+ if (typeof parentPropPanel.schema !== 'function') {
173
+ throw Error('Oops, is text schema no longer a function?');
174
+ }
175
+
176
+ return {
177
+ ...parentPropPanel.schema(propPanelProps),
178
+ '-------': { type: 'void', widget: 'Divider' },
179
+
180
+ optionsContainer: {
181
+ title: (propPanelProps as PropPanelWidgetProps).i18n('schemas.select.options'),
182
+ type: 'string',
183
+ widget: 'Card',
184
+ span: 24,
185
+ properties: { options: { widget: 'addOptions' } },
186
+ },
187
+ };
188
+ },
189
+ defaultSchema: {
190
+ ...text.propPanel.defaultSchema,
191
+ type: 'select',
192
+ content: 'option1',
193
+ options: ['option1', 'option2'],
194
+ },
195
+ },
196
+ icon: selectIcon,
197
+ };
198
+
199
+ export default schema;
@@ -35,14 +35,17 @@ interface GroupButtonString {
35
35
  key: Formatter;
36
36
  icon: string;
37
37
  type: 'select';
38
- value: String;
38
+ value: string;
39
39
  }
40
40
 
41
41
  export type GroupButton = GroupButtonBoolean | GroupButtonString;
42
42
 
43
- export function getExtraFormatterSchema(
44
- i18n: (key: keyof Dict | string) => string
45
- ): Record<string, any> {
43
+ export function getExtraFormatterSchema(i18n: (key: keyof Dict | string) => string): {
44
+ title: string;
45
+ widget: string;
46
+ buttons: GroupButton[];
47
+ span: number;
48
+ } {
46
49
  const buttons: GroupButton[] = [
47
50
  { key: Formatter.STRIKETHROUGH, icon: TextStrikethroughIcon, type: 'boolean' },
48
51
  { key: Formatter.UNDERLINE, icon: TextUnderlineIcon, type: 'boolean' },
@@ -228,7 +228,7 @@ export const buildStyledTextContainer = async (arg: UIRenderProps<TextSchema>, v
228
228
  };
229
229
 
230
230
  const textBlock = document.createElement('div');
231
- textBlock.id = 'text-' + schema.id;
231
+ textBlock.id = 'text-' + String(schema.id);
232
232
  Object.assign(textBlock.style, textBlockStyle);
233
233
 
234
234
  container.appendChild(textBlock);
@@ -265,7 +265,7 @@ export const makeElementPlainTextContentEditable = (element: HTMLElement) => {
265
265
  });
266
266
  };
267
267
 
268
- const mapVerticalAlignToFlex = (verticalAlignmentValue: string | undefined) => {
268
+ export const mapVerticalAlignToFlex = (verticalAlignmentValue: string | undefined) => {
269
269
  switch (verticalAlignmentValue) {
270
270
  case VERTICAL_ALIGN_TOP:
271
271
  return 'flex-start';
@@ -277,7 +277,7 @@ const mapVerticalAlignToFlex = (verticalAlignmentValue: string | undefined) => {
277
277
  return 'flex-start';
278
278
  };
279
279
 
280
- const getBackgroundColor = (value: string, schema: TextSchema) => {
280
+ export const getBackgroundColor = (value: string, schema: { backgroundColor?: string }) => {
281
281
  if (!value || !schema.backgroundColor) return 'transparent';
282
- return schema.backgroundColor as string;
282
+ return schema.backgroundColor;
283
283
  };