@luftborn/custom-elements 2.8.1 → 2.8.2

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 (20) hide show
  1. package/demo/index.js +466 -2853
  2. package/demo/index.min.js +465 -2852
  3. package/demo/index.min.js.map +1 -1
  4. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepicker.d.ts +45 -0
  5. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepicker.js +327 -0
  6. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepicker.js.map +1 -0
  7. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerStyles.d.ts +1 -0
  8. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerStyles.js +5 -0
  9. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerStyles.js.map +1 -0
  10. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerUtils.d.ts +6 -0
  11. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerUtils.js +45 -0
  12. package/dist/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerUtils.js.map +1 -0
  13. package/dist/elements/CustomFormatDateFieldElement/CustomFormatDateFieldElement.d.ts +2 -6
  14. package/dist/elements/CustomFormatDateFieldElement/CustomFormatDateFieldElement.js +14 -60
  15. package/dist/elements/CustomFormatDateFieldElement/CustomFormatDateFieldElement.js.map +1 -1
  16. package/package.json +2 -6
  17. package/src/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepicker.ts +355 -0
  18. package/src/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerStyles.ts +101 -0
  19. package/src/elements/CustomFormatDateFieldElement/CustomDatepicker/CustomDatepickerUtils.ts +44 -0
  20. package/src/elements/CustomFormatDateFieldElement/CustomFormatDateFieldElement.ts +18 -72
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luftborn/custom-elements",
3
- "version": "2.8.1",
3
+ "version": "2.8.2",
4
4
  "description": "custom HTML elements for the form builder application (node version: 18)",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -17,7 +17,6 @@
17
17
  "@types/googlemaps": "^3.39.6",
18
18
  "@webcomponents/custom-elements": "1.4.1",
19
19
  "@webcomponents/webcomponentsjs": "2.6.0",
20
- "flatpickr": "^4.6.13",
21
20
  "intl-tel-input": "^16.0.8",
22
21
  "restore": "^0.3.0"
23
22
  },
@@ -35,8 +34,5 @@
35
34
  "typescript": "4.4.3",
36
35
  "vinyl-buffer": "~1.0.1",
37
36
  "vinyl-source-stream": "~2.0.0"
38
- },
39
- "bundleDependencies": [
40
- "@webcomponents/webcomponentsjs"
41
- ]
37
+ }
42
38
  }
@@ -0,0 +1,355 @@
1
+ import { CustomDatepickerStyles } from "./CustomDatepickerStyles";
2
+ import { daysOfWeek, defaultDateFormat, formatDate, isMobileDevice, months, supportedDateFormats } from "./CustomDatepickerUtils";
3
+
4
+ type CustomDatepickerOptions = {
5
+ input: HTMLInputElement;
6
+ dateFormat: string;
7
+ otherTriggers?: HTMLElement[];
8
+ parentElement?: ShadowRoot | HTMLElement;
9
+ }
10
+
11
+ export default class CustomDatepicker {
12
+ private input: HTMLInputElement;
13
+ private otherTriggers: HTMLElement[];
14
+ private parentElement: ShadowRoot | HTMLElement;
15
+
16
+ private datepicker: HTMLElement;
17
+ private header: HTMLElement;
18
+ private monthYear: HTMLElement;
19
+ private selectNextMonth: HTMLElement;
20
+ private selectPrevMonth: HTMLElement;
21
+ private weekdays: HTMLElement;
22
+ private days: HTMLElement;
23
+ private selectMonthYear: HTMLElement;
24
+ private selectDate: HTMLElement;
25
+ private currentDate: Date;
26
+ private currentMonth: number;
27
+ private currentYear: number;
28
+ private selectedDate: Date;
29
+ private selectedMonth: number;
30
+ private selectedYear: number;
31
+ private selectedDay: number;
32
+ private firstDayOfMonth: Date;
33
+ private lastDayOfMonth: Date;
34
+ private firstDay: number;
35
+ private lastDay: number;
36
+
37
+ private dateFormat: string;
38
+
39
+ constructor(options: CustomDatepickerOptions) {
40
+ this.input = options.input;
41
+ this.dateFormat = supportedDateFormats.includes(options.dateFormat) ? options.dateFormat : defaultDateFormat;
42
+ this.otherTriggers = options.otherTriggers || [];
43
+ this.parentElement = options.parentElement;
44
+
45
+ this.currentDate = new Date();
46
+ this.currentMonth = this.currentDate.getMonth();
47
+ this.currentYear = this.currentDate.getFullYear();
48
+ this.selectedDate = new Date();
49
+ this.selectedMonth = this.selectedDate.getMonth();
50
+ this.selectedYear = this.selectedDate.getFullYear();
51
+ this.selectedDay = this.selectedDate.getDate();
52
+ this.firstDayOfMonth = new Date(this.currentYear, this.currentMonth, 1);
53
+ this.lastDayOfMonth = new Date(this.currentYear, this.currentMonth + 1, 0);
54
+ this.firstDay = this.firstDayOfMonth.getDay();
55
+ this.lastDay = this.lastDayOfMonth.getDate();
56
+
57
+ this.createDatePickerElements();
58
+ this.renderCalendar();
59
+ this.initSelectMonthYear();
60
+ this.addEventListeners();
61
+ }
62
+
63
+ private createDatePickerElements() {
64
+ this.datepicker = document.createElement('div');
65
+ this.datepicker.classList.add('datepicker');
66
+ this.header = document.createElement('div');
67
+ this.header.classList.add('header');
68
+ this.monthYear = document.createElement('span');
69
+ this.monthYear.classList.add('month-year');
70
+ this.monthYear.onclick = () => this.toggleSelectMonthYear();
71
+ this.selectNextMonth = document.createElement('span');
72
+ this.selectNextMonth.classList.add('next-month');
73
+ this.selectNextMonth.innerHTML = '▶';
74
+ this.selectNextMonth.onclick = () => this.moveMonth(1);
75
+ this.selectPrevMonth = document.createElement('span');
76
+ this.selectPrevMonth.classList.add('prev-month');
77
+ this.selectPrevMonth.innerHTML = '◀';
78
+ this.selectPrevMonth.onclick = () => this.moveMonth(-1);
79
+ this.header.appendChild(this.selectPrevMonth);
80
+ this.header.appendChild(this.monthYear);
81
+ this.header.appendChild(this.selectNextMonth);
82
+
83
+ this.weekdays = document.createElement('div');
84
+ this.weekdays.classList.add('weekdays');
85
+ this.days = document.createElement('div');
86
+ this.days.classList.add('days');
87
+ this.selectMonthYear = document.createElement('div');
88
+ this.selectMonthYear.classList.add('select-month-year');
89
+ this.selectDate = document.createElement('div');
90
+ this.selectDate.classList.add('select-date');
91
+ this.datepicker.appendChild(this.header);
92
+ this.datepicker.appendChild(this.selectDate);
93
+ this.selectDate.appendChild(this.weekdays);
94
+ this.selectDate.appendChild(this.days);
95
+ this.datepicker.appendChild(this.selectMonthYear);
96
+
97
+ let actions = document.createElement('div');
98
+ actions.classList.add('actions');
99
+ this.selectDate.appendChild(actions);
100
+ let cancel = document.createElement('input');
101
+ cancel.type = 'reset';
102
+ cancel.value = 'Cancel';
103
+ cancel.onclick = () => this.showPicker(false);
104
+ actions.appendChild(cancel);
105
+ let today = document.createElement('input');
106
+ today.type = 'reset';
107
+ today.value = 'Today';
108
+ today.onclick = () => this.setDateForToday();
109
+ actions.appendChild(today);
110
+
111
+ if (this.input.parentElement) {
112
+ this.input.parentElement.appendChild(this.datepicker);
113
+ } else {
114
+ document.body.appendChild(this.datepicker);
115
+ }
116
+
117
+ this.applyStyles();
118
+ }
119
+
120
+ private applyStyles() {
121
+ const style = document.createElement('style');
122
+ style.innerHTML = CustomDatepickerStyles;
123
+ this.datepicker.appendChild(style);
124
+ }
125
+
126
+ private moveMonth(steps: number) {
127
+ let newMonth = this.currentMonth + steps;
128
+ let newYear = this.currentYear;
129
+ if (newMonth < 0) {
130
+ newYear = this.currentYear + Math.floor(newMonth / 12);
131
+ newMonth = 12 + (newMonth % 12);
132
+ } else if (newMonth > 11) {
133
+ newYear = this.currentYear + Math.floor(newMonth / 12);
134
+ newMonth = newMonth % 12;
135
+ }
136
+ this.currentMonth = newMonth;
137
+ this.currentYear = newYear;
138
+ this.firstDayOfMonth = new Date(this.currentYear, this.currentMonth, 1);
139
+ this.lastDayOfMonth = new Date(this.currentYear, this.currentMonth + 1, 0);
140
+ this.firstDay = this.firstDayOfMonth.getDay();
141
+ this.lastDay = this.lastDayOfMonth.getDate();
142
+ this.renderCalendar();
143
+ }
144
+
145
+ private renderCalendar() {
146
+ this.monthYear.innerHTML = months[this.currentMonth] + ' ' + this.currentYear;
147
+ this.weekdays.innerHTML = '';
148
+ for (let i = 0; i < daysOfWeek.length; i++) {
149
+ let span = document.createElement('span');
150
+ span.innerHTML = daysOfWeek[i];
151
+ this.weekdays.appendChild(span);
152
+ }
153
+ this.days.innerHTML = '';
154
+ for (let i = 0; i < 42; i++) {
155
+ let span = document.createElement('span');
156
+ if (i < this.firstDay) {
157
+ span.classList.add('day-of-previous-month');
158
+ span.style.color = '#ccc';
159
+ let currentDate = new Date(this.currentYear, this.currentMonth, 0);
160
+ span.innerHTML = (currentDate.getDate() - this.firstDay + i + 1).toString();
161
+ } else if (i < this.lastDay + this.firstDay) {
162
+ span.classList.add('day-of-current-month');
163
+ span.innerHTML = (i - this.firstDay + 1).toString();
164
+ if (i - this.firstDay + 1 === this.selectedDay && this.currentMonth === this.selectedMonth && this.currentYear === this.selectedYear) {
165
+ span.classList.add('selected-day')
166
+ }
167
+ } else {
168
+ span.classList.add('day-of-next-month');
169
+ span.style.color = '#ccc';
170
+ span.innerHTML = (i - this.lastDay - this.firstDay + 1).toString();
171
+ }
172
+ span.onclick = () => {
173
+ let moveMonthSteps = 0;
174
+ this.selectedDay = parseInt(span.innerHTML);
175
+ if (span.classList.contains('day-of-previous-month')) {
176
+ this.selectedMonth = this.currentMonth - 1;
177
+ this.selectedYear = this.currentYear;
178
+ moveMonthSteps = -1;
179
+ } else if (span.classList.contains('day-of-current-month')) {
180
+ this.selectedMonth = this.currentMonth;
181
+ this.selectedYear = this.currentYear;
182
+ } else {
183
+ this.selectedMonth = this.currentMonth + 1;
184
+ this.selectedYear = this.currentYear;
185
+ moveMonthSteps = 1;
186
+ }
187
+ this.selectedDate = new Date(this.selectedYear, this.selectedMonth, this.selectedDay);
188
+ let selectedDayElement = this.days.querySelector('.selected-day');
189
+ if (selectedDayElement) {
190
+ selectedDayElement.classList.remove('selected-day');
191
+ }
192
+ span.classList.add('selected-day');
193
+
194
+ const formattedDate = formatDate(this.selectedDate, this.dateFormat);
195
+ this.input.value = formattedDate;
196
+
197
+ this.showPicker(false);
198
+ };
199
+ this.days.appendChild(span);
200
+ }
201
+
202
+ this.positionPicker();
203
+ }
204
+
205
+ private initSelectMonthYear() {
206
+ this.selectMonthYear.style.display = 'none';
207
+ this.selectMonthYear.style.height = '200px';
208
+ if (isMobileDevice()) {
209
+ this.selectMonthYear.style.height = '300px';
210
+ }
211
+ this.selectMonthYear.innerHTML = '';
212
+ let monthsContainer = document.createElement('div');
213
+ monthsContainer.classList.add('months');
214
+ for (let i = 0; i < months.length; i++) {
215
+ let span = document.createElement('span');
216
+ span.innerHTML = months[i].substring(0, 3);
217
+ span.classList.add('select-month');
218
+ monthsContainer.appendChild(span);
219
+ span.onclick = () => {
220
+ this.selectedMonth = months.findIndex(month => month.substring(0, 3) === span.innerHTML);
221
+ let moveMonthSteps = (this.selectedYear - this.currentYear) * 12 + this.selectedMonth - this.currentMonth;
222
+ this.moveMonth(moveMonthSteps);
223
+ this.hideSelectMonthYear();
224
+ }
225
+ }
226
+ for (let i = this.currentYear - 100; i < this.currentYear + 100; i++) {
227
+ let year = document.createElement('div');
228
+ year.classList.add('year');
229
+ year.innerHTML = i.toString();
230
+ this.selectMonthYear.appendChild(year);
231
+ if (i === this.currentYear) {
232
+ year.appendChild(monthsContainer);
233
+ }
234
+ }
235
+ let years = this.selectMonthYear.querySelectorAll('.year');
236
+ let tempSelectedYear = this.selectedYear;
237
+ for (let i = 0; i < years.length; i++) {
238
+ years[i].addEventListener('click', () => {
239
+ let year = parseInt(years[i].innerHTML);
240
+ if (year === tempSelectedYear) {
241
+ return;
242
+ } else {
243
+ tempSelectedYear = year;
244
+ this.selectedYear = year;
245
+ let monthsContainers = this.selectMonthYear.querySelectorAll('.months');
246
+ for (let i = 0; i < monthsContainers.length; i++) {
247
+ monthsContainers[i].remove();
248
+ }
249
+ years[i].appendChild(monthsContainer);
250
+ }
251
+ });
252
+ }
253
+ }
254
+
255
+ private toggleSelectMonthYear() {
256
+ if (this.selectMonthYear.style.display === 'none') {
257
+ this.selectDate.style.display = 'none';
258
+ this.selectMonthYear.style.display = 'block';
259
+ this.header.style.color = '#ccc';
260
+ let years = this.selectMonthYear.querySelectorAll('.year');
261
+ for (let i = 0; i < years.length; i++) {
262
+ if (years[i].querySelector('.months')) {
263
+ years[i].scrollIntoView();
264
+ break;
265
+ }
266
+ }
267
+ } else {
268
+ this.hideSelectMonthYear();
269
+ }
270
+ }
271
+
272
+ private hideSelectMonthYear() {
273
+ this.selectDate.style.display = 'block';
274
+ this.selectMonthYear.style.display = 'none';
275
+ this.header.style.color = '#000';
276
+ }
277
+
278
+ private showPicker(showpicker: boolean = true) {
279
+ if (showpicker) {
280
+ this.positionPicker();
281
+ this.datepicker.style.display = 'block';
282
+ } else {
283
+ this.datepicker.style.display = 'none';
284
+ this.hideSelectMonthYear();
285
+ return;
286
+ }
287
+ }
288
+
289
+ private positionPicker() {
290
+ this.datepicker.style.position = 'fixed';
291
+
292
+ let datepickerHeight = 250;
293
+ if (isMobileDevice()) {
294
+ this.datepicker.style.height = '400px';
295
+ this.datepicker.style.top = '50%';
296
+ this.datepicker.style.left = '50%';
297
+ this.datepicker.style.transform = 'translate(-50%, -50%)';
298
+ this.datepicker.style.width = '90%';
299
+ this.datepicker.style.maxWidth = '300px';
300
+ this.datepicker.style.fontSize = '16px';
301
+ this.datepicker.style.padding = '30px';
302
+ this.header.style.marginBottom = '20px';
303
+ let weekdaysSpans = this.weekdays.querySelectorAll('span');
304
+ let daysSpans = this.days.querySelectorAll('span');
305
+ weekdaysSpans.forEach(span => span.style.marginBottom = '10px');
306
+ daysSpans.forEach(span => span.style.marginBottom = '10px');
307
+ } else {
308
+ this.datepicker.style.height = datepickerHeight + 'px';
309
+ let dateInputRect = this.input.getBoundingClientRect();
310
+ datepickerHeight += 20;
311
+ if (window.innerHeight - dateInputRect.bottom < datepickerHeight) {
312
+ this.datepicker.style.top = 'auto';
313
+ this.datepicker.style.bottom = window.innerHeight - dateInputRect.top + 'px';
314
+ } else {
315
+ this.datepicker.style.bottom = 'auto';
316
+ this.datepicker.style.top = dateInputRect.bottom + 'px';
317
+ }
318
+ this.datepicker.style.left = dateInputRect.left + 'px';
319
+ }
320
+ }
321
+
322
+ private setDateForToday() {
323
+ this.input.value = formatDate(this.selectedDate, this.dateFormat);
324
+ this.showPicker(false);
325
+ }
326
+
327
+ private addEventListeners() {
328
+ this.input.addEventListener('click', () => this.showPicker(true));
329
+ this.input.addEventListener('focus', () => this.showPicker(true));
330
+ this.input.addEventListener('change', () => {
331
+ const date = new Date(this.input.value);
332
+ if (date.toString() !== 'Invalid Date') {
333
+ this.selectedDate = date;
334
+ this.selectedMonth = date.getMonth();
335
+ this.selectedYear = date.getFullYear();
336
+ this.selectedDay = date.getDate();
337
+ this.renderCalendar();
338
+ }
339
+ });
340
+
341
+ this.otherTriggers.forEach(trigger => {
342
+ trigger.addEventListener('click', () => this.showPicker(true));
343
+ });
344
+
345
+ document.onclick = (event: Event) => {
346
+ const elementsToNeglect = [this.input, this.datepicker, this.monthYear, this.weekdays, this.days, this.header, this.selectMonthYear];
347
+ const element = event.target as HTMLElement;
348
+ const isNeglected = elementsToNeglect.includes(element) || elementsToNeglect.includes(element.parentElement) || (element).classList.contains('select-month') || element === this.parentElement;
349
+
350
+ if (!isNeglected){
351
+ this.showPicker(false);
352
+ }
353
+ };
354
+ }
355
+ }
@@ -0,0 +1,101 @@
1
+ export const CustomDatepickerStyles = `
2
+ .datepicker {
3
+ position: fixed;
4
+ background-color: #fff;
5
+ display: none;
6
+ width: 200px;
7
+ border: 1px solid #ccc;
8
+ border-radius: 5px;
9
+ padding: 10px;
10
+ margin: 0 auto;
11
+ box-shadow: 0 0 10px 0 #ccc;
12
+ font: 12px Arial, sans-serif;
13
+ }
14
+
15
+ .header {
16
+ display: flex;
17
+ justify-content: space-between;
18
+ align-items: center;
19
+ margin-bottom: 10px;
20
+ }
21
+ .weekdays {
22
+ display: flex;
23
+ justify-content: space-between;
24
+ }
25
+ .weekdays span {
26
+ width: 14.28%;
27
+ text-align: center;
28
+ padding: 5px 0;
29
+ }
30
+ .days {
31
+ display: flex;
32
+ flex-wrap: wrap;
33
+ }
34
+ .days span {
35
+ width: 14.28%;
36
+ text-align: center;
37
+ padding: 5px 0;
38
+ }
39
+ .days span:hover {
40
+ background-color: #B2d5ff;
41
+ cursor: pointer;
42
+ }
43
+ .days span.today {
44
+ border: 1px solid #000;
45
+ }
46
+ .days span.selected-day {
47
+ background-color: #0075ff;
48
+ color: #fff;
49
+ }
50
+ .prev-month, .next-month {
51
+ cursor: pointer;
52
+ }
53
+ .month-year {
54
+ font-weight: bold;
55
+ }
56
+ .month-year:hover {
57
+ cursor: pointer;
58
+ }
59
+ .select-month-year {
60
+ display: none;
61
+ width: 100%;
62
+ overflow-y: auto;
63
+ }
64
+ .select-month-year .year {
65
+ text-align: center;
66
+ background-color: #f0f0f0;
67
+ border-bottom: 1px solid #3f3d3d;
68
+ padding: 5px 0;
69
+ cursor: pointer;
70
+ }
71
+ .select-month-year .year .months {
72
+ display: flex;
73
+ flex-wrap: wrap;
74
+ }
75
+ .select-month-year .year .months span {
76
+ width: 25%;
77
+ text-align: center;
78
+ padding: 10px 0;
79
+ background-color: #fff;
80
+ }
81
+ .select-month-year .year .months span:hover {
82
+ background-color: #B2d5ff;
83
+ cursor: pointer;
84
+ }
85
+ .actions {
86
+ display: flex;
87
+ justify-content: space-between;
88
+ margin-top: 10px;
89
+ }
90
+ .actions input {
91
+ color: #0075ff;
92
+ border: none;
93
+ background-color: transparent;
94
+ padding: 5px;
95
+ border: 1px solid transparent;
96
+ }
97
+ .actions input:hover {
98
+ background-color: #B2d5ff;
99
+ border-color: #000;
100
+ }
101
+ `;
@@ -0,0 +1,44 @@
1
+ export const months: string[] = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
2
+ export const daysOfWeek: string[] = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
3
+
4
+ export const defaultDateFormat = 'yyyy-mm-dd';
5
+ export const supportedDateFormats = [
6
+ 'ddmmyyyy',
7
+ 'mmddyyyy',
8
+ 'dd/mm/yyyy',
9
+ 'mm/dd/yyyy',
10
+ 'dd-mm-yyyy',
11
+ 'mm-dd-yyyy',
12
+ 'yyyy-mm-dd',
13
+ 'yyyy-dd-mm',
14
+ 'Month dd, yyyy',
15
+ 'mm/dd/yy',
16
+ 'dd/mm/yy',
17
+ ];
18
+
19
+ export function formatDate(date: Date, dateFormat: string): string {
20
+ const year = date.getFullYear();
21
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
22
+ const day = date.getDate().toString().padStart(2, '0');
23
+ const monthName = date.toLocaleString('default', { month: 'long' });
24
+
25
+ const dateFormats = {
26
+ 'ddmmyyyy': `${day}${month}${year}`,
27
+ 'mmddyyyy': `${month}${day}${year}`,
28
+ 'dd/mm/yyyy': `${day}/${month}/${year}`,
29
+ 'mm/dd/yyyy': `${month}/${day}/${year}`,
30
+ 'dd-mm-yyyy': `${day}-${month}-${year}`,
31
+ 'mm-dd-yyyy': `${month}-${day}-${year}`,
32
+ 'yyyy-mm-dd': `${year}-${month}-${day}`,
33
+ 'yyyy-dd-mm': `${year}-${day}-${month}`,
34
+ 'Month dd, yyyy': `${monthName} ${day}, ${year}`,
35
+ 'mm/dd/yy': `${month}/${day}/${year.toString().slice(-2)}`,
36
+ 'dd/mm/yy': `${day}/${month}/${year.toString().slice(-2)}`,
37
+ }
38
+
39
+ return dateFormats[dateFormat];
40
+ }
41
+
42
+ export function isMobileDevice() {
43
+ return /Android|webOS|iPhone|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || window.innerWidth < 480;
44
+ }
@@ -1,20 +1,23 @@
1
1
  import CustomElement from '../../framework/custom-element.decorator';
2
2
  import { CustomInputElement } from '../../framework/CustomInputElement';
3
3
  import { CustomElementEventArgs } from '../../framework/CustomEvents';
4
- const flatpickr = require('flatpickr');
4
+ import CustomDatepicker from './CustomDatepicker/CustomDatepicker';
5
+ import { defaultDateFormat, supportedDateFormats } from './CustomDatepicker/CustomDatepickerUtils';
5
6
 
6
7
  @CustomElement({
7
8
  selector: 'custom-format-date-element',
8
9
  template: `
9
- <div class="wrapper flatpickr">
10
- <input type="text" id="date-field" data-input />
10
+ <div class="wrapper">
11
+ <input type="text" id="date-field" readonly />
11
12
  <svg id="picker-trigger" data-toggle viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="4" width="20" height="18" rx="1" fill="#000"/><rect x="4" y="8" width="16" height="12" fill="white"/><path d="M4 10H20" stroke="#000" stroke-width="1"/><circle cx="16" cy="14" r="2" fill="#F44336"/><rect x="6" y="2" width="3" height="4" rx=".5" fill="#000"/><rect x="15" y="2" width="3" height="4" rx=".5" fill="#000"/></svg>
12
13
  </div>`,
13
14
  style: `
14
- @import '../../../node_modules/flatpickr/dist/flatpickr.min.css';
15
15
  :host{
16
16
  width:100%;
17
17
  }
18
+ * {
19
+ box-sizing: border-box;
20
+ }
18
21
  .wrapper{
19
22
  display:flex;
20
23
  position: relative;
@@ -40,34 +43,13 @@ const flatpickr = require('flatpickr');
40
43
  right: 2px;
41
44
  top: 15%;
42
45
  }
43
- .flatpickr-calendar {
44
- position: fixed !important; /* Use fixed positioning */
45
- top: 50% !important; /* Center vertically */
46
- left: 50% !important; /* Center horizontally */
47
- z-index: 1000 !important; /* Ensure it's above other content */
48
- }
49
46
  `,
50
47
  useShadow: true,
51
48
  })
52
49
  export class CustomFormatDateFieldElement extends CustomInputElement {
53
50
  date: HTMLInputElement;
54
51
  dateWrapper: HTMLElement;
55
- datepicker: any;
56
-
57
- private readonly defaultDateFormat = 'yyyy-mm-dd';
58
- private readonly supportedDateFormats = [
59
- 'ddmmyyyy',
60
- 'mmddyyyy',
61
- 'dd/mm/yyyy',
62
- 'mm/dd/yyyy',
63
- 'dd-mm-yyyy',
64
- 'mm-dd-yyyy',
65
- 'yyyy-mm-dd',
66
- 'yyyy-dd-mm',
67
- 'Month dd, yyyy',
68
- 'mm/dd/yy',
69
- 'dd/mm/yy',
70
- ];
52
+ pickerTrigger: HTMLElement;
71
53
 
72
54
  constructor() {
73
55
  super();
@@ -91,9 +73,9 @@ export class CustomFormatDateFieldElement extends CustomInputElement {
91
73
 
92
74
  initChildInputs() {
93
75
  this.date = super.getChildInput('#date-field');
94
- this.dateWrapper = super.getChildInput('.flatpickr');
95
- this.validateDateFormats();
76
+ this.pickerTrigger = this.getChildElement('#picker-trigger');
96
77
 
78
+ this.dateFormat = supportedDateFormats.includes(this.dateFormat) ? this.dateFormat : defaultDateFormat;
97
79
  this.date.placeholder = this.dateFormat;
98
80
 
99
81
  this.date.addEventListener('change', this.change.bind(this));
@@ -107,7 +89,7 @@ export class CustomFormatDateFieldElement extends CustomInputElement {
107
89
  this.date.setAttribute('min', this.min);
108
90
  }
109
91
 
110
- this.initFlatpickr();
92
+ this.initCustomPicker();
111
93
  }
112
94
 
113
95
  // events
@@ -123,48 +105,12 @@ export class CustomFormatDateFieldElement extends CustomInputElement {
123
105
  );
124
106
  }
125
107
 
126
- initFlatpickr() {
127
- flatpickr(this.dateWrapper, {
128
- wrap: true,
129
- altInput: true,
130
- appendTo: this.shadowRoot.querySelector('.wrapper'),
131
- disableMobile: true,
132
- parseDate: (datestr) => {
133
- return new Date(datestr);
134
- },
135
- formatDate: (date, format) => {
136
- return this.formatDate(date);
137
- }
138
- });
139
- }
140
-
141
- private formatDate(date: Date): string {
142
-
143
- const year = date.getFullYear();
144
- const month = (date.getMonth() + 1).toString().padStart(2, '0');
145
- const day = date.getDate().toString().padStart(2, '0');
146
- const monthName = date.toLocaleString('default', { month: 'long' });
147
-
148
- const dateFormats = {
149
- 'ddmmyyyy': `${day}${month}${year}`,
150
- 'mmddyyyy': `${month}${day}${year}`,
151
- 'dd/mm/yyyy': `${day}/${month}/${year}`,
152
- 'mm/dd/yyyy': `${month}/${day}/${year}`,
153
- 'dd-mm-yyyy': `${day}-${month}-${year}`,
154
- 'mm-dd-yyyy': `${month}-${day}-${year}`,
155
- 'yyyy-mm-dd': `${year}-${month}-${day}`,
156
- 'yyyy-dd-mm': `${year}-${day}-${month}`,
157
- 'Month dd, yyyy': `${monthName} ${day}, ${year}`,
158
- 'mm/dd/yy': `${month}/${day}/${year.toString().slice(-2)}`,
159
- 'dd/mm/yy': `${day}/${month}/${year.toString().slice(-2)}`,
160
- }
161
-
162
- return dateFormats[this.dateFormat];
163
- }
164
-
165
- private validateDateFormats() {
166
- if (!this.supportedDateFormats.includes(this.dateFormat)) {
167
- this.dateFormat = this.defaultDateFormat;
168
- }
108
+ initCustomPicker() {
109
+ new CustomDatepicker({
110
+ input: this.date,
111
+ dateFormat: this.dateFormat,
112
+ otherTriggers: [this.pickerTrigger],
113
+ parentElement: this,
114
+ })
169
115
  }
170
116
  }