@pdfme/schemas 5.2.11-dev.6 → 5.2.12

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 (35) hide show
  1. package/dist/cjs/src/date/date.js +1 -43
  2. package/dist/cjs/src/date/date.js.map +1 -1
  3. package/dist/cjs/src/date/dateTime.js +1 -90
  4. package/dist/cjs/src/date/dateTime.js.map +1 -1
  5. package/dist/cjs/src/date/helper.js +227 -71
  6. package/dist/cjs/src/date/helper.js.map +1 -1
  7. package/dist/cjs/src/date/time.js +1 -15
  8. package/dist/cjs/src/date/time.js.map +1 -1
  9. package/dist/cjs/src/tables/helper.js +1 -0
  10. package/dist/cjs/src/tables/helper.js.map +1 -1
  11. package/dist/cjs/src/text/propPanel.js +1 -0
  12. package/dist/cjs/src/text/propPanel.js.map +1 -1
  13. package/dist/esm/src/date/date.js +1 -43
  14. package/dist/esm/src/date/date.js.map +1 -1
  15. package/dist/esm/src/date/dateTime.js +1 -90
  16. package/dist/esm/src/date/dateTime.js.map +1 -1
  17. package/dist/esm/src/date/helper.js +206 -73
  18. package/dist/esm/src/date/helper.js.map +1 -1
  19. package/dist/esm/src/date/time.js +1 -15
  20. package/dist/esm/src/date/time.js.map +1 -1
  21. package/dist/esm/src/tables/helper.js +1 -0
  22. package/dist/esm/src/tables/helper.js.map +1 -1
  23. package/dist/esm/src/text/propPanel.js +1 -0
  24. package/dist/esm/src/text/propPanel.js.map +1 -1
  25. package/dist/types/src/date/helper.d.ts +5 -5
  26. package/dist/types/src/date/types.d.ts +1 -0
  27. package/dist/types/src/tables/helper.d.ts +1 -0
  28. package/package.json +1 -1
  29. package/src/date/date.ts +1 -46
  30. package/src/date/dateTime.ts +1 -93
  31. package/src/date/helper.ts +256 -106
  32. package/src/date/time.ts +1 -18
  33. package/src/date/types.ts +1 -0
  34. package/src/tables/helper.ts +1 -0
  35. package/src/text/propPanel.ts +1 -0
package/src/date/date.ts CHANGED
@@ -1,54 +1,9 @@
1
- import { Lang } from '@pdfme/common';
2
1
  import { getPlugin } from './helper';
3
2
  import { createSvgStr } from '../utils.js';
4
3
  import { Calendar } from 'lucide';
5
4
 
6
5
  const type = 'date';
7
6
 
8
- const defaultFormat = 'yyyy/MM/dd';
9
-
10
- const formatsByLang: Record<Lang, string[]> = {
11
- en: [
12
- defaultFormat,
13
- 'MM/dd/yyyy',
14
- 'MMMM d, yyyy',
15
- 'MMM d, yyyy',
16
- 'EEEE, MMMM d, yyyy',
17
- 'yyyy-MM-dd',
18
- ],
19
- zh: [defaultFormat, 'yyyy年MM月dd日', 'MM月dd日', 'M月d日', 'yyyy-MM-dd'],
20
- ja: [defaultFormat, 'yyyy年MM月dd日', 'MM月dd日', 'M月d日', 'yyyy-MM-dd'],
21
- ko: [defaultFormat, 'yyyy년 MM월 dd일', 'MM월 dd일', 'M월 d일', 'yyyy-MM-dd'],
22
- ar: [defaultFormat, 'dd/MM/yyyy', 'd MMMM yyyy', 'd MMM yyyy', 'EEEE، d MMMM yyyy', 'yyyy-MM-dd'],
23
- th: [
24
- defaultFormat,
25
- 'dd/MM/yyyy',
26
- 'd MMMM yyyy',
27
- 'd MMM yyyy',
28
- 'EEEEที่ d MMMM G yyyy',
29
- 'yyyy-MM-dd',
30
- ],
31
- pl: [defaultFormat, 'dd.MM.yyyy', 'd MMMM yyyy', 'd MMM yyyy', 'EEEE, d MMMM yyyy', 'yyyy-MM-dd'],
32
- it: [defaultFormat, 'dd/MM/yyyy', 'd MMMM yyyy', 'd MMM yyyy', 'EEEE d MMMM yyyy', 'yyyy-MM-dd'],
33
- de: [
34
- defaultFormat,
35
- 'dd.MM.yyyy',
36
- 'd. MMMM yyyy',
37
- 'd. MMM yyyy',
38
- 'EEEE, d. MMMM yyyy',
39
- 'yyyy-MM-dd',
40
- ],
41
- es: [
42
- defaultFormat,
43
- 'dd/MM/yyyy',
44
- 'd de MMMM de yyyy',
45
- 'd de MMM de yyyy',
46
- 'EEEE, d de MMMM de yyyy',
47
- 'yyyy-MM-dd',
48
- ],
49
- fr: [defaultFormat, 'dd/MM/yyyy', 'd MMMM yyyy', 'd MMM yyyy', 'EEEE d MMMM yyyy', 'yyyy-MM-dd'],
50
- };
51
-
52
7
  const icon = createSvgStr(Calendar);
53
8
 
54
- export default getPlugin({ type, defaultFormat, icon, formatsByLang });
9
+ export default getPlugin({ type, icon });
@@ -1,101 +1,9 @@
1
- import { Lang } from '@pdfme/common';
2
1
  import { getPlugin } from './helper';
3
2
  import { createSvgStr } from '../utils.js';
4
3
  import { CalendarClock } from 'lucide';
5
4
 
6
5
  const type = 'dateTime';
7
6
 
8
- const defaultFormat = 'yyyy/MM/dd HH:mm';
9
-
10
- const formatsByLang: Record<Lang, string[]> = {
11
- en: [
12
- defaultFormat,
13
- 'MM/dd/yyyy h:mm a',
14
- 'MMMM d, yyyy h:mm a',
15
- 'MMM d, yyyy h:mm a',
16
- 'EEEE, MMMM d, yyyy h:mm a',
17
- "yyyy-MM-dd'T'HH:mm:ss",
18
- ],
19
- zh: [
20
- defaultFormat,
21
- 'yyyy年MM月dd日 HH:mm',
22
- 'MM月dd日 HH:mm',
23
- 'M月d日 HH:mm',
24
- "yyyy-MM-dd'T'HH:mm:ss",
25
- ],
26
- ja: [
27
- defaultFormat,
28
- 'yyyy年MM月dd日 HH:mm',
29
- 'MM月dd日 HH:mm',
30
- 'M月d日 HH:mm',
31
- "yyyy-MM-dd'T'HH:mm:ss",
32
- ],
33
- ko: [
34
- defaultFormat,
35
- 'yyyy-MM-dd HH:mm',
36
- 'yyyy년 MM월 dd일 HH:mm',
37
- 'MM월 dd일 HH:mm',
38
- 'M월 d일 HH:mm',
39
- "yyyy-MM-dd'T'HH:mm:ss",
40
- ],
41
- ar: [
42
- defaultFormat,
43
- 'dd/MM/yyyy h:mm a',
44
- 'd MMMM yyyy h:mm a',
45
- 'd MMM yyyy h:mm a',
46
- 'EEEE، d MMMM yyyy h:mm a',
47
- "yyyy-MM-dd'T'HH:mm:ss",
48
- ],
49
- th: [
50
- defaultFormat,
51
- 'dd/MM/yyyy HH:mm',
52
- 'd MMMM yyyy HH:mm',
53
- 'd MMM yyyy HH:mm',
54
- 'EEEEที่ d MMMM G yyyy HH:mm',
55
- "yyyy-MM-dd'T'HH:mm:ss",
56
- ],
57
- pl: [
58
- defaultFormat,
59
- 'dd.MM.yyyy HH:mm',
60
- 'd MMMM yyyy HH:mm',
61
- 'd MMM yyyy HH:mm',
62
- 'EEEE, d MMMM yyyy HH:mm',
63
- "yyyy-MM-dd'T'HH:mm:ss",
64
- ],
65
- it: [
66
- defaultFormat,
67
- 'dd/MM/yyyy HH:mm',
68
- 'd MMMM yyyy HH:mm',
69
- 'd MMM yyyy HH:mm',
70
- 'EEEE d MMMM yyyy HH:mm',
71
- "yyyy-MM-dd'T'HH:mm:ss",
72
- ],
73
- de: [
74
- defaultFormat,
75
- 'dd.MM.yyyy HH:mm',
76
- 'd. MMMM yyyy HH:mm',
77
- 'd. MMM yyyy HH:mm',
78
- 'EEEE, d. MMMM yyyy HH:mm',
79
- "yyyy-MM-dd'T'HH:mm:ss",
80
- ],
81
- es: [
82
- defaultFormat,
83
- 'dd/MM/yyyy h:mm a',
84
- 'd de MMMM de yyyy h:mm a',
85
- 'd de MMM de yyyy h:mm a',
86
- 'EEEE, d de MMMM de yyyy h:mm a',
87
- "yyyy-MM-dd'T'HH:mm:ss",
88
- ],
89
- fr: [
90
- defaultFormat,
91
- 'dd/MM/yyyy HH:mm',
92
- 'd MMMM yyyy HH:mm',
93
- 'd MMM yyyy HH:mm',
94
- 'EEEE d MMMM yyyy HH:mm',
95
- "yyyy-MM-dd'T'HH:mm:ss",
96
- ],
97
- };
98
-
99
7
  const icon = createSvgStr(CalendarClock);
100
8
 
101
- export default getPlugin({ type, defaultFormat, icon, formatsByLang });
9
+ export default getPlugin({ type, icon });
@@ -1,28 +1,48 @@
1
1
  import type * as CSS from 'csstype';
2
- import AirDatepicker, { AirDatepickerLocale } from 'air-datepicker';
2
+
3
+ import AirDatepicker from 'air-datepicker';
4
+ import type { AirDatepickerLocale } from 'air-datepicker';
5
+ import localeAr from 'air-datepicker/locale/ar';
6
+ import localeBg from 'air-datepicker/locale/bg';
7
+ import localeCa from 'air-datepicker/locale/ca';
8
+ import localeCs from 'air-datepicker/locale/cs';
9
+ import localeDa from 'air-datepicker/locale/da';
10
+ import localeDe from 'air-datepicker/locale/de';
11
+ import localeEl from 'air-datepicker/locale/el';
3
12
  import localeEn from 'air-datepicker/locale/en';
4
- import localeZh from 'air-datepicker/locale/zh';
13
+ import localeEs from 'air-datepicker/locale/es';
14
+ import localeEu from 'air-datepicker/locale/eu';
15
+ import localeFi from 'air-datepicker/locale/fi';
16
+ import localeFr from 'air-datepicker/locale/fr';
17
+ import localeHr from 'air-datepicker/locale/hr';
18
+ import localeHu from 'air-datepicker/locale/hu';
19
+ import localeId from 'air-datepicker/locale/id';
20
+ import localeIt from 'air-datepicker/locale/it';
5
21
  import localeJa from 'air-datepicker/locale/ja';
6
22
  import localeKo from 'air-datepicker/locale/ko';
7
- import localeAr from 'air-datepicker/locale/ar';
23
+ import localeNb from 'air-datepicker/locale/nb';
24
+ import localeNl from 'air-datepicker/locale/nl';
8
25
  import localeTh from 'air-datepicker/locale/th';
9
26
  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';
27
+ import localePtBR from 'air-datepicker/locale/pt-BR';
28
+ import localePt from 'air-datepicker/locale/pt';
29
+ import localeRo from 'air-datepicker/locale/ro';
30
+ import localeRu from 'air-datepicker/locale/ru';
31
+ import localeSi from 'air-datepicker/locale/si';
32
+ import localeSk from 'air-datepicker/locale/sk';
33
+ import localeSl from 'air-datepicker/locale/sl';
34
+ import localeSv from 'air-datepicker/locale/sv';
35
+ import localeTr from 'air-datepicker/locale/tr';
36
+ import localeUk from 'air-datepicker/locale/uk';
37
+ import localeZh from 'air-datepicker/locale/zh';
38
+
39
+ import * as dateFns from 'date-fns/locale';
14
40
  import { format } from 'date-fns';
15
- import { enUS, zhCN, ja, ko, ar, th, pl, it, de, es, fr, Locale } from 'date-fns/locale';
16
- import {
17
- Lang,
18
- Plugin,
19
- getFallbackFontName,
20
- DEFAULT_FONT_NAME,
21
- PropPanelSchema,
22
- } from '@pdfme/common';
41
+
42
+ import { Plugin, getFallbackFontName, DEFAULT_FONT_NAME, PropPanelSchema } from '@pdfme/common';
23
43
  import text from '../text';
24
44
  import { DEFAULT_OPACITY, HEX_COLOR_PATTERN } from '../constants.js';
25
- import { mapVerticalAlignToFlex, getBackgroundColor } from '../text/uiRender';
45
+ import { mapVerticalAlignToFlex } from '../text/uiRender';
26
46
  import {
27
47
  DEFAULT_FONT_SIZE,
28
48
  DEFAULT_ALIGNMENT,
@@ -35,6 +55,77 @@ import { DateSchema } from './types';
35
55
  import { getExtraFormatterSchema, Formatter } from '../text/extraFormatter';
36
56
  import { isEditable } from '../utils';
37
57
 
58
+ type PickerType = 'date' | 'time' | 'dateTime';
59
+
60
+ interface Locale {
61
+ label: string;
62
+ adLocale: AirDatepickerLocale;
63
+ close: string;
64
+ formatLocale: dateFns.Locale;
65
+ }
66
+
67
+ const LOCALE_MAP: Record<
68
+ string,
69
+ {
70
+ label: string;
71
+ adLocale: AirDatepickerLocale;
72
+ close: string;
73
+ formatLocale: dateFns.Locale;
74
+ }
75
+ > = {
76
+ ar: { label: 'Arabic', adLocale: localeAr, close: 'يغلق', formatLocale: dateFns.ar },
77
+ bg: { label: 'Bulgarian', adLocale: localeBg, close: 'близо', formatLocale: dateFns.bg },
78
+ ca: { label: 'Catalan', adLocale: localeCa, close: 'Fermer', formatLocale: dateFns.ca },
79
+ cs: { label: 'Czech', adLocale: localeCs, close: 'Blízko', formatLocale: dateFns.cs },
80
+ da: { label: 'Danish', adLocale: localeDa, close: 'Tæt', formatLocale: dateFns.da },
81
+ de: { label: 'German', adLocale: localeDe, close: 'Schließen', formatLocale: dateFns.de },
82
+ el: { label: 'Greek', adLocale: localeEl, close: 'κοντά', formatLocale: dateFns.el },
83
+ en: { label: 'English', adLocale: localeEn, close: 'Close', formatLocale: dateFns.enUS },
84
+ es: { label: 'Spanish', adLocale: localeEs, close: 'Cerca', formatLocale: dateFns.es },
85
+ eu: { label: 'Basque', adLocale: localeEu, close: 'Itxi', formatLocale: dateFns.eu },
86
+ fi: { label: 'Finnish', adLocale: localeFi, close: 'Lähellä', formatLocale: dateFns.fi },
87
+ fr: { label: 'French', adLocale: localeFr, close: 'Fermer', formatLocale: dateFns.fr },
88
+ hr: { label: 'Croatian', adLocale: localeHr, close: 'Zatvoriti', formatLocale: dateFns.hr },
89
+ hu: { label: 'Hungarian', adLocale: localeHu, close: 'Közeli', formatLocale: dateFns.hu },
90
+ id: { label: 'Indonesian', adLocale: localeId, close: 'Menutup', formatLocale: dateFns.id },
91
+ it: { label: 'Italian', adLocale: localeIt, close: 'Vicino', formatLocale: dateFns.it },
92
+ ja: { label: 'Japanese', adLocale: localeJa, close: '閉じる', formatLocale: dateFns.ja },
93
+ ko: { label: 'Korean', adLocale: localeKo, close: '닫다', formatLocale: dateFns.ko },
94
+ nb: { label: 'Norwegian Bokmål', adLocale: localeNb, close: 'Lukke', formatLocale: dateFns.nb },
95
+ nl: { label: 'Dutch', adLocale: localeNl, close: 'Dichtbij', formatLocale: dateFns.nl },
96
+ pl: { label: 'Polish', adLocale: localePl, close: 'Zamknąć', formatLocale: dateFns.pl },
97
+ 'pt-Br': {
98
+ label: 'Portuguese',
99
+ adLocale: localePtBR,
100
+ close: 'Fechar',
101
+ formatLocale: dateFns.ptBR,
102
+ },
103
+ pt: { label: 'Portuguese', adLocale: localePt, close: 'Fechar', formatLocale: dateFns.pt },
104
+ ro: { label: 'Romanian', adLocale: localeRo, close: 'Aproape', formatLocale: dateFns.ro },
105
+ ru: { label: 'Russian', adLocale: localeRu, close: 'закрывать', formatLocale: dateFns.ru },
106
+ si: {
107
+ label: 'Sinhala',
108
+ adLocale: localeSi,
109
+ close: 'සමීපයි',
110
+ formatLocale: dateFns.enUS,
111
+ },
112
+ sk: { label: 'Slovak', adLocale: localeSk, close: 'Zavrieť', formatLocale: dateFns.sk },
113
+ sl: { label: 'Slovenian', adLocale: localeSl, close: 'Blizu', formatLocale: dateFns.sl },
114
+ sv: { label: 'Swedish', adLocale: localeSv, close: 'Nära', formatLocale: dateFns.sv },
115
+ th: { label: 'Thai', adLocale: localeTh, close: 'ปิด', formatLocale: dateFns.th },
116
+ tr: { label: 'Turkish', adLocale: localeTr, close: 'kapalı', formatLocale: dateFns.tr },
117
+ uk: { label: 'Ukrainian', adLocale: localeUk, close: 'Закрити', formatLocale: dateFns.uk },
118
+ zh: { label: 'Chinese', adLocale: localeZh, close: '关闭', formatLocale: dateFns.zhCN },
119
+ };
120
+
121
+ const getAirDatepickerLocale = (locale: string) => {
122
+ const data = LOCALE_MAP[locale];
123
+ if (!data) {
124
+ throw new Error(`Unsupported locale: ${locale}`);
125
+ }
126
+ return data;
127
+ };
128
+
38
129
  const airDatepickerCss = `.air-datepicker-cell.-year-.-other-decade-,.air-datepicker-cell.-day-.-other-month-{color:var(--adp-color-other-month)}.air-datepicker-cell.-year-.-other-decade-:hover,.air-datepicker-cell.-day-.-other-month-:hover{color:var(--adp-color-other-month-hover)}.-disabled-.-focus-.air-datepicker-cell.-year-.-other-decade-,.-disabled-.-focus-.air-datepicker-cell.-day-.-other-month-{color:var(--adp-color-other-month)}.-selected-.air-datepicker-cell.-year-.-other-decade-,.-selected-.air-datepicker-cell.-day-.-other-month-{color:#fff;background:var(--adp-background-color-selected-other-month)}.-selected-.-focus-.air-datepicker-cell.-year-.-other-decade-,.-selected-.-focus-.air-datepicker-cell.-day-.-other-month-{background:var(--adp-background-color-selected-other-month-focused)}.-in-range-.air-datepicker-cell.-year-.-other-decade-,.-in-range-.air-datepicker-cell.-day-.-other-month-{background-color:var(--adp-background-color-in-range);color:var(--adp-color)}.-in-range-.-focus-.air-datepicker-cell.-year-.-other-decade-,.-in-range-.-focus-.air-datepicker-cell.-day-.-other-month-{background-color:var(--adp-background-color-in-range-focused)}.air-datepicker-cell.-year-.-other-decade-:empty,.air-datepicker-cell.-day-.-other-month-:empty{background:none;border:none}.air-datepicker-cell{border-radius:var(--adp-cell-border-radius);box-sizing:border-box;cursor:pointer;display:flex;position:relative;align-items:center;justify-content:center;z-index:1}.air-datepicker-cell.-focus-{background:var(--adp-cell-background-color-hover)}.air-datepicker-cell.-current-{color:var(--adp-color-current-date)}.air-datepicker-cell.-current-.-focus-{color:var(--adp-color)}.air-datepicker-cell.-current-.-in-range-{color:var(--adp-color-current-date)}.air-datepicker-cell.-disabled-{cursor:default;color:var(--adp-color-disabled)}.air-datepicker-cell.-disabled-.-focus-{color:var(--adp-color-disabled)}.air-datepicker-cell.-disabled-.-in-range-{color:var(--adp-color-disabled-in-range)}.air-datepicker-cell.-disabled-.-current-.-focus-{color:var(--adp-color-disabled)}.air-datepicker-cell.-in-range-{background:var(--adp-cell-background-color-in-range);border-radius:0}.air-datepicker-cell.-in-range-:hover,.air-datepicker-cell.-in-range-.-focus-{background:var(--adp-cell-background-color-in-range-hover)}.air-datepicker-cell.-range-from-{border:1px solid var(--adp-cell-border-color-in-range);background-color:var(--adp-cell-background-color-in-range);border-radius:var(--adp-cell-border-radius) 0 0 var(--adp-cell-border-radius)}.air-datepicker-cell.-range-to-{border:1px solid var(--adp-cell-border-color-in-range);background-color:var(--adp-cell-background-color-in-range);border-radius:0 var(--adp-cell-border-radius) var(--adp-cell-border-radius) 0}.air-datepicker-cell.-range-to-.-range-from-{border-radius:var(--adp-cell-border-radius)}.air-datepicker-cell.-selected-{color:#fff;border:none;background:var(--adp-cell-background-color-selected)}.air-datepicker-cell.-selected-.-current-{color:#fff;background:var(--adp-cell-background-color-selected)}.air-datepicker-cell.-selected-.-focus-{background:var(--adp-cell-background-color-selected-hover)}
39
130
  .air-datepicker-body{transition:all var(--adp-transition-duration) var(--adp-transition-ease)}.air-datepicker-body.-hidden-{display:none}.air-datepicker-body--day-names{display:grid;grid-template-columns:repeat(7, var(--adp-day-cell-width));margin:8px 0 3px}.air-datepicker-body--day-name{color:var(--adp-day-name-color);display:flex;align-items:center;justify-content:center;flex:1;text-align:center;text-transform:uppercase;font-size:.8em}.air-datepicker-body--day-name.-clickable-{cursor:pointer}.air-datepicker-body--day-name.-clickable-:hover{color:var(--adp-day-name-color-hover)}.air-datepicker-body--cells{display:grid}.air-datepicker-body--cells.-days-{grid-template-columns:repeat(7, var(--adp-day-cell-width));grid-auto-rows:var(--adp-day-cell-height)}.air-datepicker-body--cells.-months-{grid-template-columns:repeat(3, 1fr);grid-auto-rows:var(--adp-month-cell-height)}.air-datepicker-body--cells.-years-{grid-template-columns:repeat(4, 1fr);grid-auto-rows:var(--adp-year-cell-height)}
40
131
  .air-datepicker-nav{display:flex;justify-content:space-between;border-bottom:1px solid var(--adp-border-color-inner);min-height:var(--adp-nav-height);padding:var(--adp-padding);box-sizing:content-box}.-only-timepicker- .air-datepicker-nav{display:none}.air-datepicker-nav--title,.air-datepicker-nav--action{display:flex;cursor:pointer;align-items:center;justify-content:center}.air-datepicker-nav--action{width:var(--adp-nav-action-size);border-radius:var(--adp-border-radius);-webkit-user-select:none;-moz-user-select:none;user-select:none}.air-datepicker-nav--action:hover{background:var(--adp-background-color-hover)}.air-datepicker-nav--action:active{background:var(--adp-background-color-active)}.air-datepicker-nav--action.-disabled-{visibility:hidden}.air-datepicker-nav--action svg{width:32px;height:32px}.air-datepicker-nav--action path{fill:none;stroke:var(--adp-nav-arrow-color);stroke-width:2px}.air-datepicker-nav--title{border-radius:var(--adp-border-radius);padding:0 8px}.air-datepicker-nav--title i{font-style:normal;color:var(--adp-nav-color-secondary);margin-left:.3em}.air-datepicker-nav--title:hover{background:var(--adp-background-color-hover)}.air-datepicker-nav--title:active{background:var(--adp-background-color-active)}.air-datepicker-nav--title.-disabled-{cursor:default;background:none}
@@ -56,25 +147,11 @@ const injectStyles = (css: string) => {
56
147
  }
57
148
  };
58
149
 
59
- const getDateFnsLocale = (lang: Lang): Locale | undefined =>
60
- ({ en: enUS, zh: zhCN, ja, ko, ar, th, pl, it, de, es, fr }[lang]);
61
-
62
- const getAirDatepickerLocale = (lang: Lang): AirDatepickerLocale | undefined =>
63
- ({
64
- en: localeEn,
65
- zh: localeZh,
66
- ja: localeJa,
67
- ko: localeKo,
68
- ar: localeAr,
69
- th: localeTh,
70
- pl: localePl,
71
- it: localeIt,
72
- de: localeDe,
73
- es: localeEs,
74
- fr: localeFr,
75
- }[lang]);
76
-
77
- const strDateToDate = (strDate: string, type: 'date' | 'time' | 'dateTime'): Date => {
150
+ const strDateToDate = (strDate: string, type: PickerType): Date => {
151
+ if (!strDate.trim()) {
152
+ return new Date();
153
+ }
154
+
78
155
  if (type === 'time') {
79
156
  const dateTimePattern = /^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}$/;
80
157
  if (dateTimePattern.test(strDate)) {
@@ -82,74 +159,111 @@ const strDateToDate = (strDate: string, type: 'date' | 'time' | 'dateTime'): Dat
82
159
  }
83
160
  return new Date(`2021-01-01T${strDate}`);
84
161
  }
162
+
85
163
  return new Date(strDate);
86
164
  };
87
165
 
88
- export const getPlugin = ({
89
- type,
90
- defaultFormat,
91
- icon,
92
- formatsByLang,
93
- }: {
94
- type: 'date' | 'time' | 'dateTime';
95
- defaultFormat: string;
96
- icon: string;
97
- formatsByLang: Record<Lang, string[]>;
98
- }) => {
166
+ const getFormat = (type: PickerType, locale: Locale): string => {
167
+ switch (type) {
168
+ case 'date': {
169
+ return locale.adLocale.dateFormat;
170
+ }
171
+ case 'time': {
172
+ return 'HH:mm';
173
+ }
174
+ case 'dateTime': {
175
+ return `${locale.adLocale.dateFormat} ${locale.adLocale.timeFormat}`;
176
+ }
177
+ }
178
+ };
179
+
180
+ const getFmtValue = (
181
+ value: string,
182
+ type: PickerType,
183
+ schema: DateSchema,
184
+ locale: Locale
185
+ ): string => {
186
+ return value
187
+ ? format(strDateToDate(value, type), schema.format, {
188
+ locale: locale.formatLocale,
189
+ })
190
+ : '';
191
+ };
192
+
193
+ const getFmtContent = (date: Date[], type: PickerType) => {
194
+ const fmt = (() => {
195
+ switch (type) {
196
+ case 'date': {
197
+ return 'yyyy/MM/dd';
198
+ }
199
+ case 'time': {
200
+ return 'HH:mm';
201
+ }
202
+ case 'dateTime': {
203
+ return 'yyyy/MM/dd HH:mm';
204
+ }
205
+ }
206
+ })();
207
+ return date[0] ? format(date[0], fmt) : '';
208
+ };
209
+
210
+ export const getPlugin = ({ type, icon }: { type: PickerType; icon: string }) => {
211
+ const defaultLocale = 'en';
212
+ const defaultFormat = getFormat(type, getAirDatepickerLocale(defaultLocale));
213
+
99
214
  const plugin: Plugin<DateSchema> = {
100
- ui: (arg) => {
101
- const { schema, value, onChange, rootElement, mode, options, i18n } = arg;
102
- injectStyles(airDatepickerCss);
215
+ ui: async (arg) => {
216
+ const { schema, value, onChange, rootElement, mode, options } = arg;
103
217
 
104
- const beforeRemoveEvent = new Event('beforeRemove');
105
- rootElement.dispatchEvent(beforeRemoveEvent);
218
+ const locale = getAirDatepickerLocale(schema.locale || options.lang || defaultLocale);
106
219
 
107
- const textStyle: CSS.Properties = {
108
- fontFamily: schema.fontName ? `'${schema.fontName}'` : 'inherit',
109
- color: schema.fontColor ?? DEFAULT_FONT_COLOR,
110
- fontSize: `${schema.fontSize ?? DEFAULT_FONT_SIZE}pt`,
111
- letterSpacing: `${schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING}pt`,
112
- textAlign: schema.alignment ?? DEFAULT_ALIGNMENT,
113
- backgroundColor: getBackgroundColor(value, schema),
114
-
115
- margin: '0',
116
- padding: '0',
117
- border: 'none',
118
- outline: 'none',
220
+ const textElement = document.createElement('div');
221
+ const textElementStyle: CSS.Properties = {
119
222
  width: `${schema.width}mm`,
120
223
  height: `${schema.height}mm`,
121
224
  display: 'flex',
122
225
  flexDirection: 'column',
123
226
  justifyContent: mapVerticalAlignToFlex(VERTICAL_ALIGN_MIDDLE),
124
- position: 'relative',
125
227
  };
228
+ Object.assign(textElement.style, textElementStyle);
126
229
 
127
- const input = document.createElement('input');
230
+ await text.ui({
231
+ ...arg,
232
+ rootElement: textElement,
233
+ mode: 'viewer',
234
+ value: getFmtValue(value, type, schema, locale),
235
+ schema: {
236
+ ...schema,
237
+ verticalAlignment: VERTICAL_ALIGN_MIDDLE,
238
+ lineHeight: DEFAULT_LINE_HEIGHT,
239
+ },
240
+ });
241
+
242
+ injectStyles(airDatepickerCss);
128
243
 
129
- Object.assign(input.style, textStyle);
244
+ const beforeRemoveEvent = new Event('beforeRemove');
245
+ rootElement.dispatchEvent(beforeRemoveEvent);
246
+
247
+ const input = document.createElement('input');
248
+ Object.assign(input.style, { visibility: 'hidden', position: 'absolute' });
130
249
 
131
250
  const commitChange = ({ datepicker }: { datepicker: AirDatepicker<HTMLInputElement> }) => {
132
251
  if (onChange) {
133
- const date = datepicker.selectedDates;
134
- const fmt =
135
- type === 'time' ? 'HH:mm' : type === 'date' ? 'yyyy/MM/dd' : 'yyyy/MM/dd HH:mm';
136
- const d = Array.isArray(date) ? date[0] : date || '';
137
- const value = d ? format(d, fmt) : '';
138
- onChange({ key: 'content', value });
252
+ onChange({ key: 'content', value: getFmtContent(datepicker.selectedDates, type) });
139
253
  }
140
254
  };
141
255
 
142
256
  const airDatepicker = new AirDatepicker(input, {
143
- locale: getAirDatepickerLocale(options.lang || 'en'),
257
+ locale: locale.adLocale,
144
258
  selectedDates: [strDateToDate(value, type)],
145
- dateFormat: (date) => (schema.format ? format(date, schema.format) : ''),
259
+ dateFormat: (date) => format(date, schema.format, { locale: locale.formatLocale }),
146
260
  timepicker: type !== 'date',
147
261
  onlyTimepicker: type === 'time',
148
262
  isMobile: window.innerWidth < 768,
149
263
  buttons: [
150
264
  'clear',
151
265
  {
152
- content: i18n('close'),
266
+ content: locale.close,
153
267
  onClick: (datepicker) => {
154
268
  datepicker.hide();
155
269
  commitChange({ datepicker });
@@ -165,61 +279,86 @@ export const getPlugin = ({
165
279
  });
166
280
 
167
281
  rootElement.addEventListener('beforeRemove', () => {
168
- if (mode === 'designer') {
282
+ if (isEditable(mode, schema)) {
169
283
  airDatepicker.destroy();
170
284
  }
171
285
  });
172
- input.addEventListener('click', () => {
173
- if (mode === 'designer') {
286
+ textElement.addEventListener('click', () => {
287
+ if (isEditable(mode, schema)) {
174
288
  airDatepicker.show();
175
289
  }
176
290
  });
177
291
 
178
292
  rootElement.appendChild(input);
293
+ rootElement.appendChild(textElement);
179
294
  },
180
295
  pdf: (arg) => {
181
- const { schema, value } = arg;
296
+ const { schema, value, options } = arg;
182
297
  if (!value) return void 0;
183
- const date = strDateToDate(value, type);
184
- const formattedValue = format(date, schema.format);
185
- return text.pdf(
186
- Object.assign(arg, {
187
- value: formattedValue,
188
- schema: {
189
- ...schema,
190
- verticalAlignment: VERTICAL_ALIGN_MIDDLE,
191
- lineHeight: DEFAULT_LINE_HEIGHT,
192
- },
193
- })
194
- );
298
+ const locale = getAirDatepickerLocale(schema.locale || options.lang || defaultLocale);
299
+ return text.pdf({
300
+ ...arg,
301
+ value: getFmtValue(value, type, schema, locale),
302
+ schema: {
303
+ ...schema,
304
+ verticalAlignment: VERTICAL_ALIGN_MIDDLE,
305
+ lineHeight: DEFAULT_LINE_HEIGHT,
306
+ },
307
+ });
195
308
  },
196
309
  propPanel: {
197
- schema: ({ options, i18n }) => {
310
+ schema: ({ options, i18n, activeSchema, changeSchemas }) => {
198
311
  const font = options.font || { [DEFAULT_FONT_NAME]: { data: '', fallback: true } };
199
- const lang = options.lang || 'en';
200
- const locale = getDateFnsLocale(lang);
201
-
202
312
  const fontNames = Object.keys(font);
203
313
  const fallbackFontName = getFallbackFontName(font);
204
314
 
315
+ const locale = getAirDatepickerLocale(
316
+ (activeSchema as any).locale || options.lang || defaultLocale
317
+ );
318
+
319
+ if (
320
+ (activeSchema as any).locale === undefined &&
321
+ (activeSchema as any).locale !== options.lang
322
+ ) {
323
+ changeSchemas([
324
+ { schemaId: activeSchema.id, key: 'locale', value: options.lang },
325
+ { schemaId: activeSchema.id, key: 'format', value: getFormat(type, locale) },
326
+ ]);
327
+ }
328
+
205
329
  const formatter = getExtraFormatterSchema(i18n);
206
330
  formatter.buttons = formatter.buttons.filter(
207
331
  (button) => button.key === Formatter.ALIGNMENT
208
332
  );
209
333
 
210
- const currentDate = new Date();
334
+ const validateDateTimeFormat = (_rule: any, formatString: string): boolean => {
335
+ try {
336
+ format('Thu Jan 01 1970 00:00:00 GMT+0000', formatString, {
337
+ locale: locale.formatLocale,
338
+ });
339
+ return true;
340
+ } catch (_err) {
341
+ return false;
342
+ }
343
+ };
344
+
345
+ const localeOptions = Object.keys(LOCALE_MAP).map((lc) => ({
346
+ label: `${lc} (${LOCALE_MAP[lc].label})`,
347
+ value: lc,
348
+ }));
211
349
 
212
350
  const dateSchema: Record<string, PropPanelSchema> = {
213
351
  format: {
214
352
  title: i18n('schemas.date.format'),
215
353
  type: 'string',
216
- widget: 'select',
217
- props: {
218
- options: formatsByLang[lang].map((formatString) => ({
219
- label: `${formatString} (${format(currentDate, formatString, { locale })})`,
220
- value: formatString,
221
- })),
222
- },
354
+ default: getFormat(type, locale),
355
+ placeholder: getFormat(type, locale),
356
+ rules: [
357
+ {
358
+ validator: validateDateTimeFormat,
359
+ message: i18n('validation.dateTimeFormat'),
360
+ },
361
+ ],
223
362
  span: 24,
224
363
  },
225
364
  fontName: {
@@ -227,6 +366,7 @@ export const getPlugin = ({
227
366
  type: 'string',
228
367
  widget: 'select',
229
368
  default: fallbackFontName,
369
+ placeholder: fallbackFontName,
230
370
  props: { options: fontNames.map((name) => ({ label: name, value: name })) },
231
371
  span: 12,
232
372
  },
@@ -250,7 +390,7 @@ export const getPlugin = ({
250
390
  type: 'string',
251
391
  widget: 'color',
252
392
  props: {
253
- disabledAlpha: true
393
+ disabledAlpha: true,
254
394
  },
255
395
  rules: [
256
396
  {
@@ -264,7 +404,7 @@ export const getPlugin = ({
264
404
  type: 'string',
265
405
  widget: 'color',
266
406
  props: {
267
- disabledAlpha: true
407
+ disabledAlpha: true,
268
408
  },
269
409
  rules: [
270
410
  {
@@ -273,6 +413,15 @@ export const getPlugin = ({
273
413
  },
274
414
  ],
275
415
  },
416
+ locale: {
417
+ title: i18n('schemas.date.locale'),
418
+ type: 'string',
419
+ widget: 'select',
420
+ props: {
421
+ options: localeOptions,
422
+ },
423
+ span: 16,
424
+ },
276
425
  };
277
426
 
278
427
  return dateSchema;
@@ -281,7 +430,7 @@ export const getPlugin = ({
281
430
  name: '',
282
431
  format: defaultFormat,
283
432
  type,
284
- content: format(new Date(), defaultFormat),
433
+ content: getFmtContent([new Date()], type),
285
434
  position: { x: 0, y: 0 },
286
435
  width: 50,
287
436
  height: 10,
@@ -292,6 +441,7 @@ export const getPlugin = ({
292
441
  fontColor: DEFAULT_FONT_COLOR,
293
442
  fontName: undefined,
294
443
  backgroundColor: '',
444
+ locale: undefined,
295
445
  opacity: DEFAULT_OPACITY,
296
446
  },
297
447
  },