@pdfme/schemas 5.1.0 → 5.1.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.
@@ -1,6 +1,19 @@
1
1
  import type * as CSS from 'csstype';
2
+ import AirDatepicker, { AirDatepickerLocale } from 'air-datepicker';
3
+ import localeEn from 'air-datepicker/locale/en';
4
+ import localeZh from 'air-datepicker/locale/zh';
5
+ import localeJa from 'air-datepicker/locale/ja';
6
+ import localeKo from 'air-datepicker/locale/ko';
7
+ import localeAr from 'air-datepicker/locale/ar';
8
+ import localeTh from 'air-datepicker/locale/th';
9
+ import localePl from 'air-datepicker/locale/pl';
10
+ import localeIt from 'air-datepicker/locale/it';
11
+ import localeDe from 'air-datepicker/locale/de';
12
+ import localeEs from 'air-datepicker/locale/es';
13
+ import localeFr from 'air-datepicker/locale/fr';
14
+ import 'air-datepicker/air-datepicker.css';
2
15
  import { format } from 'date-fns';
3
- import { zhCN, ja, ko, ar, th, pl, it, de, es, fr, Locale } from 'date-fns/locale';
16
+ import { enUS, zhCN, ja, ko, ar, th, pl, it, de, es, fr, Locale } from 'date-fns/locale';
4
17
  import {
5
18
  Lang,
6
19
  Plugin,
@@ -16,34 +29,50 @@ import { getFontKitFont, getBrowserVerticalFontAdjustments } from '../text/helpe
16
29
  import {
17
30
  DEFAULT_FONT_SIZE,
18
31
  DEFAULT_ALIGNMENT,
19
- DEFAULT_VERTICAL_ALIGNMENT,
32
+ VERTICAL_ALIGN_MIDDLE,
20
33
  DEFAULT_LINE_HEIGHT,
21
34
  DEFAULT_CHARACTER_SPACING,
22
35
  DEFAULT_FONT_COLOR,
23
36
  } from '../text/constants.js';
24
37
  import { DateSchema } from './types';
25
38
  import { getExtraFormatterSchema, Formatter } from '../text/extraFormatter';
39
+ import { isEditable } from '../utils';
26
40
 
27
- const getLocale = (lang: Lang): Locale | undefined =>
28
- ({ en: undefined, zh: zhCN, ja, ko, ar, th, pl, it, de, es, fr }[lang]);
41
+ const getDateFnsLocale = (lang: Lang): Locale | undefined =>
42
+ ({ en: enUS, zh: zhCN, ja, ko, ar, th, pl, it, de, es, fr }[lang]);
43
+
44
+ const getAirDatepickerLocale = (lang: Lang): AirDatepickerLocale | undefined =>
45
+ ({
46
+ en: localeEn,
47
+ zh: localeZh,
48
+ ja: localeJa,
49
+ ko: localeKo,
50
+ ar: localeAr,
51
+ th: localeTh,
52
+ pl: localePl,
53
+ it: localeIt,
54
+ de: localeDe,
55
+ es: localeEs,
56
+ fr: localeFr,
57
+ }[lang]);
29
58
 
30
59
  export const getPlugin = ({
31
60
  type,
32
61
  defaultFormat,
33
62
  icon,
34
- inputType,
35
63
  formatsByLang,
36
64
  }: {
37
65
  type: 'date' | 'time' | 'dateTime';
38
66
  defaultFormat: string;
39
67
  icon: string;
40
- inputType: string;
41
68
  formatsByLang: Record<Lang, string[]>;
42
69
  }) => {
43
70
  const plugin: Plugin<DateSchema> = {
44
71
  ui: async (arg) => {
45
- const { schema, value, onChange, rootElement, mode, options, _cache } = arg;
46
- rootElement.innerHTML = '';
72
+ const { schema, value, onChange, rootElement, mode, options, i18n, _cache } = arg;
73
+
74
+ const beforeRemoveEvent = new Event('beforeRemove');
75
+ rootElement.dispatchEvent(beforeRemoveEvent);
47
76
 
48
77
  const font = options?.font || getDefaultFont();
49
78
  const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
@@ -52,7 +81,7 @@ export const getPlugin = ({
52
81
  fontKitFont,
53
82
  schema.fontSize ?? DEFAULT_FONT_SIZE,
54
83
  DEFAULT_LINE_HEIGHT,
55
- schema.verticalAlignment ?? DEFAULT_VERTICAL_ALIGNMENT
84
+ VERTICAL_ALIGN_MIDDLE
56
85
  );
57
86
 
58
87
  const topAdjustment = topAdj.toString();
@@ -66,95 +95,86 @@ export const getPlugin = ({
66
95
  backgroundColor: getBackgroundColor(value, schema),
67
96
 
68
97
  margin: '0',
98
+ padding: '0',
99
+ border: 'none',
100
+ outline: 'none',
69
101
  width: `${schema.width}mm`,
70
102
  height: `${schema.height}mm`,
71
103
  display: 'flex',
72
104
  flexDirection: 'column',
73
- justifyContent: mapVerticalAlignToFlex(schema.verticalAlignment),
105
+ justifyContent: mapVerticalAlignToFlex(VERTICAL_ALIGN_MIDDLE),
74
106
  paddingTop: `${topAdjustment}px`,
75
107
  marginBottom: `${bottomAdjustment}px`,
76
108
  position: 'relative',
77
109
  };
78
110
 
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
- };
111
+ const input = document.createElement('input');
105
112
 
106
- Object.assign(dateTimeInput.style, dateTimeInputStyle);
107
- rootElement.appendChild(dateTimeInput);
113
+ Object.assign(input.style, textStyle);
108
114
 
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
- });
115
+ const commitChange = ({ datepicker }: { datepicker: AirDatepicker<HTMLInputElement> }) => {
116
+ if (onChange) {
117
+ const date = datepicker.selectedDates;
118
+ const fmt =
119
+ type === 'time' ? 'HH:mm' : type === 'date' ? 'yyyy/MM/dd' : 'yyyy/MM/dd HH:mm';
120
+ const d = Array.isArray(date) ? date[0] : date || '';
121
+ const value = d ? format(d, fmt) : '';
122
+ onChange({ key: 'content', value });
123
+ }
124
+ };
116
125
 
117
- dateTimeInput.addEventListener('change', (e) => {
118
- if (onChange && e.target instanceof HTMLInputElement) {
119
- onChange({ key: 'content', value: e.target.value });
120
- }
121
- });
126
+ const airDatepicker = new AirDatepicker(input, {
127
+ locale: getAirDatepickerLocale(options.lang || 'en'),
128
+ selectedDates: [schema.type === 'time' ? new Date(`2021-01-01T${value}`) : new Date(value)],
129
+ dateFormat: (date) => (schema.format ? format(date, schema.format) : ''),
130
+ timepicker: type !== 'date',
131
+ onlyTimepicker: type === 'time',
132
+ buttons: [
133
+ 'clear',
134
+ {
135
+ content: i18n('close'),
136
+ onClick: (datepicker) => {
137
+ datepicker.hide();
138
+ commitChange({ datepicker });
139
+ },
140
+ },
141
+ ],
142
+ onSelect: ({ datepicker }) => {
143
+ mode !== 'designer' && commitChange({ datepicker });
144
+ },
145
+ onShow: () => {
146
+ input.disabled = !isEditable(mode, schema);
147
+ },
148
+ });
122
149
 
123
- dateTimeInput.addEventListener('blur', () => {
124
- textElement.style.opacity = '1';
125
- dateTimeInput.style.opacity = '0';
126
- dateTimeInput.style.zIndex = '-1';
127
- });
150
+ rootElement.addEventListener('beforeRemove', () => {
151
+ if (mode === 'designer') {
152
+ airDatepicker.destroy();
153
+ }
154
+ });
155
+ input.addEventListener('click', () => {
156
+ if (mode === 'designer') {
157
+ airDatepicker.show();
158
+ }
159
+ });
128
160
 
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
- }
161
+ rootElement.appendChild(input);
146
162
  },
147
163
  pdf: (arg) => {
148
164
  const { schema, value, options } = arg;
149
165
  if (!value) return void 0;
150
- const lang = (options.language || 'en') as Lang;
151
- const locale = getLocale(lang);
166
+ const lang = (options.lang || 'en') as Lang;
167
+ const locale = getDateFnsLocale(lang);
152
168
  const date = schema.type === 'time' ? new Date(`2021-01-01T${value}`) : new Date(value);
153
169
  const formattedValue = format(date, schema.format, { locale });
154
170
  return text.pdf(
155
171
  Object.assign(arg, {
156
172
  value: formattedValue,
157
- schema: { ...schema, lineHeight: DEFAULT_LINE_HEIGHT },
173
+ schema: {
174
+ ...schema,
175
+ verticalAlignment: VERTICAL_ALIGN_MIDDLE,
176
+ lineHeight: DEFAULT_LINE_HEIGHT,
177
+ },
158
178
  })
159
179
  );
160
180
  },
@@ -162,14 +182,14 @@ export const getPlugin = ({
162
182
  schema: ({ options, i18n }) => {
163
183
  const font = options.font || { [DEFAULT_FONT_NAME]: { data: '', fallback: true } };
164
184
  const lang = options.lang || 'en';
165
- const locale = getLocale(lang);
185
+ const locale = getDateFnsLocale(lang);
166
186
 
167
187
  const fontNames = Object.keys(font);
168
188
  const fallbackFontName = getFallbackFontName(font);
169
189
 
170
190
  const formatter = getExtraFormatterSchema(i18n);
171
191
  formatter.buttons = formatter.buttons.filter(
172
- (button) => button.key !== Formatter.STRIKETHROUGH && button.key !== Formatter.UNDERLINE
192
+ (button) => button.key === Formatter.ALIGNMENT
173
193
  );
174
194
 
175
195
  const currentDate = new Date();
@@ -246,7 +266,6 @@ export const getPlugin = ({
246
266
  height: 10,
247
267
  rotate: 0,
248
268
  alignment: DEFAULT_ALIGNMENT,
249
- verticalAlignment: DEFAULT_VERTICAL_ALIGNMENT,
250
269
  fontSize: DEFAULT_FONT_SIZE,
251
270
  characterSpacing: DEFAULT_CHARACTER_SPACING,
252
271
  fontColor: DEFAULT_FONT_COLOR,
package/src/date/time.ts CHANGED
@@ -3,8 +3,6 @@ import { getPlugin } from './helper';
3
3
 
4
4
  const type = 'time';
5
5
 
6
- const inputType = 'time';
7
-
8
6
  const defaultFormat = 'HH:mm';
9
7
 
10
8
  const formatsByLang: Record<Lang, string[]> = {
@@ -28,4 +26,4 @@ const icon =
28
26
  'class="lucide lucide-clock"><circle cx="12" cy="12" r="10"/>' +
29
27
  '<polyline points="12 6 12 12 16 14"/></svg>';
30
28
 
31
- export default getPlugin({ type, defaultFormat, icon, inputType, formatsByLang });
29
+ export default getPlugin({ type, defaultFormat, icon, formatsByLang });
package/src/date/types.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  import { Schema } from '@pdfme/common';
2
- import { ALIGNMENT, VERTICAL_ALIGNMENT } from '../text/types';
2
+ import { ALIGNMENT } from '../text/types';
3
3
 
4
4
  export interface DateSchema extends Schema {
5
5
  format: string;
6
6
  fontName?: string;
7
7
  alignment: ALIGNMENT;
8
- verticalAlignment: VERTICAL_ALIGNMENT;
9
8
  fontSize: number;
10
9
  characterSpacing: number;
11
10
  fontColor: string;
@@ -14,16 +14,14 @@ interface Select extends TextSchema {
14
14
  const addOptions = (props: PropPanelWidgetProps) => {
15
15
  const { rootElement, changeSchemas, activeSchema, i18n } = props;
16
16
 
17
- rootElement.innerHTML = '';
17
+ rootElement.style.width = '100%';
18
18
 
19
19
  const selectSchema = activeSchema as SchemaForUI & Select;
20
20
  const currentOptions = selectSchema.options ? [...selectSchema.options] : [];
21
21
 
22
- const container = document.createElement('div');
23
-
24
22
  const inputStyle = {
25
- flexGrow: '1',
26
- padding: '8px',
23
+ width: '100%',
24
+ padding: '6.25px 11px',
27
25
  border: '1px solid #ccc',
28
26
  borderRadius: '4px',
29
27
  };
@@ -39,6 +37,7 @@ const addOptions = (props: PropPanelWidgetProps) => {
39
37
 
40
38
  const formContainer = document.createElement('div');
41
39
  Object.assign(formContainer.style, {
40
+ width: '100%',
42
41
  display: 'flex',
43
42
  alignItems: 'center',
44
43
  marginBottom: '10px',
@@ -105,9 +104,8 @@ const addOptions = (props: PropPanelWidgetProps) => {
105
104
  });
106
105
  };
107
106
 
108
- container.appendChild(formContainer);
109
- container.appendChild(optionsList);
110
- rootElement.appendChild(container);
107
+ rootElement.appendChild(formContainer);
108
+ rootElement.appendChild(optionsList);
111
109
 
112
110
  renderOptions();
113
111
  };
@@ -182,7 +180,7 @@ const schema: Plugin<Select> = {
182
180
  type: 'string',
183
181
  widget: 'Card',
184
182
  span: 24,
185
- properties: { options: { widget: 'addOptions' } },
183
+ properties: { options: { widget: 'addOptions', span: 24 } },
186
184
  },
187
185
  };
188
186
  },