@aquera/nile-elements 0.0.2 → 0.0.3-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/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/index.d.ts +1 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/index.js +1 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/index.js.map +1 -1
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-button/nile-button.d.ts +2 -2
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-button/nile-button.js.map +1 -1
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/index.d.ts +1 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/index.js +2 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/index.js.map +1 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/nile-date-picker.css.d.ts +12 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/nile-date-picker.css.js +178 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/nile-date-picker.css.js.map +1 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/nile-date-picker.d.ts +70 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/nile-date-picker.js +494 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-date-picker/nile-date-picker.js.map +1 -0
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-icon-button/nile-icon-button.d.ts +2 -1
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/src/nile-icon-button/nile-icon-button.js.map +1 -1
- package/.rollup.cache/opt/atlassian/pipelines/agent/build/packages/nile-elements/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.iife.js +315 -66
- package/dist/nile-button/nile-button.cjs.js.map +1 -1
- package/dist/nile-date-picker/index.cjs.js +2 -0
- package/dist/nile-date-picker/index.cjs.js.map +1 -0
- package/dist/nile-date-picker/index.esm.js +1 -0
- package/dist/nile-date-picker/nile-date-picker.cjs.js +2 -0
- package/dist/nile-date-picker/nile-date-picker.cjs.js.map +1 -0
- package/dist/nile-date-picker/nile-date-picker.css.cjs.js +2 -0
- package/dist/nile-date-picker/nile-date-picker.css.cjs.js.map +1 -0
- package/dist/nile-date-picker/nile-date-picker.css.esm.js +166 -0
- package/dist/nile-date-picker/nile-date-picker.esm.js +85 -0
- package/dist/nile-icon-button/nile-icon-button.cjs.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/nile-button/nile-button.d.ts +2 -2
- package/dist/src/nile-button/nile-button.js.map +1 -1
- package/dist/src/nile-date-picker/index.d.ts +1 -0
- package/dist/src/nile-date-picker/index.js +2 -0
- package/dist/src/nile-date-picker/index.js.map +1 -0
- package/dist/src/nile-date-picker/nile-date-picker.css.d.ts +12 -0
- package/dist/src/nile-date-picker/nile-date-picker.css.js +178 -0
- package/dist/src/nile-date-picker/nile-date-picker.css.js.map +1 -0
- package/dist/src/nile-date-picker/nile-date-picker.d.ts +70 -0
- package/dist/src/nile-date-picker/nile-date-picker.js +494 -0
- package/dist/src/nile-date-picker/nile-date-picker.js.map +1 -0
- package/dist/src/nile-icon-button/nile-icon-button.d.ts +2 -1
- package/dist/src/nile-icon-button/nile-icon-button.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/nile-button/nile-button.ts +2 -2
- package/src/nile-date-picker/index.ts +1 -0
- package/src/nile-date-picker/nile-date-picker.css.ts +180 -0
- package/src/nile-date-picker/nile-date-picker.ts +588 -0
- package/src/nile-icon-button/nile-icon-button.ts +1 -1
@@ -0,0 +1,588 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright Aquera Inc 2023
|
3
|
+
*
|
4
|
+
* This source code is licensed under the BSD-3-Clause license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
|
8
|
+
import {
|
9
|
+
LitElement,
|
10
|
+
html,
|
11
|
+
property,
|
12
|
+
CSSResultArray,
|
13
|
+
TemplateResult,
|
14
|
+
} from 'lit-element';
|
15
|
+
import { customElement } from 'lit/decorators.js';
|
16
|
+
import { styles } from './nile-date-picker.css';
|
17
|
+
import { animateTo, stopAnimations } from '../internal/animate';
|
18
|
+
import { classMap } from 'lit/directives/class-map.js';
|
19
|
+
import { query } from 'lit/decorators.js';
|
20
|
+
import {
|
21
|
+
getAnimation,
|
22
|
+
setDefaultAnimation,
|
23
|
+
} from '../utilities/animation-registry';
|
24
|
+
import { getTabbableBoundary } from '../internal/tabbable';
|
25
|
+
import { waitForEvent } from '../internal/event';
|
26
|
+
import { watch } from '../internal/watch';
|
27
|
+
import NileElement from '../internal/nile-element';
|
28
|
+
import type { CSSResultGroup, PropertyValues } from 'lit';
|
29
|
+
import type NileButton from '../nile-button/nile-button';
|
30
|
+
import type NileIconButton from '../nile-icon-button/nile-icon-button';
|
31
|
+
import type { NileMenu } from '../nile-menu';
|
32
|
+
import type { NilePopup } from '../nile-popup';
|
33
|
+
import '../nile-popup';
|
34
|
+
import { NileDropdown } from '../nile-dropdown';
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Nile icon component.
|
38
|
+
*
|
39
|
+
* @tag nile-date-picker
|
40
|
+
*
|
41
|
+
*/
|
42
|
+
@customElement('nile-date-picker')
|
43
|
+
export class NileDatePicker extends NileElement {
|
44
|
+
/**
|
45
|
+
* The styles for DatePicker
|
46
|
+
* @remarks If you are extending this class you can extend the base styles with super. Eg `return [super(), myCustomStyles]`
|
47
|
+
*/
|
48
|
+
public static get styles(): CSSResultArray {
|
49
|
+
return [styles];
|
50
|
+
}
|
51
|
+
|
52
|
+
private currentMonth: number = new Date().getMonth();
|
53
|
+
private currentYear: number = new Date().getFullYear();
|
54
|
+
|
55
|
+
@query('nile-dropdown') dropdown: NileDropdown;
|
56
|
+
|
57
|
+
@property({ type: Boolean, reflect: true }) dropDownOpened = false;
|
58
|
+
|
59
|
+
@property({ type: Object }) value : any;
|
60
|
+
|
61
|
+
@property({ type: Object }) rangeValue : any;
|
62
|
+
|
63
|
+
@property({ type: String, attribute: 'value' }) valueAttribute:
|
64
|
+
| string
|
65
|
+
| null = null;
|
66
|
+
|
67
|
+
@property({ type: String, attribute: 'value' }) formattedDate: string | null =
|
68
|
+
null;
|
69
|
+
|
70
|
+
@property({ type: Object }) startDate: Date | null = null;
|
71
|
+
@property({ type: Object }) endDate: Date | null = null;
|
72
|
+
@property({ type: Boolean }) isSelectingStart = true; // flag to indicate what we're selecting
|
73
|
+
|
74
|
+
@property({ type: Boolean }) range = false;
|
75
|
+
|
76
|
+
@watch('value')
|
77
|
+
valueChanged() {
|
78
|
+
|
79
|
+
if (this.range && this.value) {
|
80
|
+
this.rangeValue = this.value;
|
81
|
+
this.value = null;
|
82
|
+
return;
|
83
|
+
}
|
84
|
+
|
85
|
+
if (this.value && !isNaN(this.value.getTime())) {
|
86
|
+
const offset = this.value.getTimezoneOffset();
|
87
|
+
const localDate = new Date(this.value.getTime() - offset * 60 * 1000);
|
88
|
+
if (!isNaN(localDate.getTime())) {
|
89
|
+
this.valueAttribute = localDate.toISOString().split('T')[0];
|
90
|
+
this.formattedDate = `${String(localDate.getDate()).padStart(
|
91
|
+
2,
|
92
|
+
'0'
|
93
|
+
)}/${String(localDate.getMonth() + 1).padStart(
|
94
|
+
2,
|
95
|
+
'0'
|
96
|
+
)}/${localDate.getFullYear()}`;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
updated(changedProperties: PropertyValues) {
|
103
|
+
super.updated(changedProperties);
|
104
|
+
|
105
|
+
if (changedProperties.has('valueAttribute')) {
|
106
|
+
const date = new Date(this.valueAttribute || '');
|
107
|
+
if (!isNaN(date.getTime())) {
|
108
|
+
const offset = date.getTimezoneOffset();
|
109
|
+
this.value = new Date(date.getTime() - offset * 60 * 1000);
|
110
|
+
this.currentMonth = this.value.getMonth();
|
111
|
+
this.currentYear = this.value.getFullYear();
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
static get observedAttributes() {
|
117
|
+
return ['value', 'range'];
|
118
|
+
}
|
119
|
+
|
120
|
+
attributeChangedCallback(name: string, oldValue: string, newValue: string) {
|
121
|
+
if (name === 'value') {
|
122
|
+
this.valueAttribute = newValue;
|
123
|
+
this.initializeValue();
|
124
|
+
} else if (name === 'range') {
|
125
|
+
this.range = newValue !== null;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
initializeValue() {
|
130
|
+
if (this.range) {
|
131
|
+
try {
|
132
|
+
const rangeValue = JSON.parse(this.valueAttribute || '');
|
133
|
+
this.startDate = new Date(rangeValue.startDate);
|
134
|
+
this.endDate = new Date(rangeValue.endDate);
|
135
|
+
|
136
|
+
// Convert to local time
|
137
|
+
this.startDate = new Date(this.startDate.getTime());
|
138
|
+
this.endDate = new Date(this.endDate.getTime());
|
139
|
+
|
140
|
+
this.rangeValue = {
|
141
|
+
startDate: this.startDate,
|
142
|
+
endDate: this.endDate,
|
143
|
+
};
|
144
|
+
this.value = null;
|
145
|
+
} catch (e) {
|
146
|
+
console.error('Invalid range value');
|
147
|
+
}
|
148
|
+
} else {
|
149
|
+
if (this.valueAttribute) {
|
150
|
+
let date: Date;
|
151
|
+
|
152
|
+
date = new Date(this.valueAttribute);
|
153
|
+
|
154
|
+
date = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
|
155
|
+
|
156
|
+
if (!isNaN(date.getTime())) {
|
157
|
+
this.value = date;
|
158
|
+
this.currentMonth = this.value.getMonth();
|
159
|
+
this.currentYear = this.value.getFullYear();
|
160
|
+
this.rangeValue = null;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
this.requestUpdate();
|
165
|
+
}
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
connectedCallback() {
|
172
|
+
super.connectedCallback();
|
173
|
+
this.initializeValue();
|
174
|
+
|
175
|
+
if (this.valueAttribute) {
|
176
|
+
const date = new Date(this.valueAttribute);
|
177
|
+
if (!isNaN(date.getTime())) {
|
178
|
+
this.value = date;
|
179
|
+
this.currentMonth = this.value.getMonth();
|
180
|
+
this.currentYear = this.value.getFullYear();
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
private getDaysArray(year: number, month: number): number[] {
|
186
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
187
|
+
return Array.from({ length: daysInMonth }, (_, i) => i + 1);
|
188
|
+
}
|
189
|
+
|
190
|
+
private nextMonth(): void {
|
191
|
+
|
192
|
+
if (this.currentMonth === 11) {
|
193
|
+
this.currentMonth = 0;
|
194
|
+
this.currentYear++;
|
195
|
+
} else {
|
196
|
+
this.currentMonth++;
|
197
|
+
}
|
198
|
+
this.requestUpdate();
|
199
|
+
}
|
200
|
+
|
201
|
+
private prevMonth(): void {
|
202
|
+
|
203
|
+
if (this.currentMonth === 0) {
|
204
|
+
this.currentMonth = 11;
|
205
|
+
this.currentYear--;
|
206
|
+
} else {
|
207
|
+
this.currentMonth--;
|
208
|
+
}
|
209
|
+
this.requestUpdate();
|
210
|
+
}
|
211
|
+
|
212
|
+
private selectDate(day: number, month: number, year: number): void {
|
213
|
+
const selectedDate = new Date(year, month, day);
|
214
|
+
|
215
|
+
if (this.range) {
|
216
|
+
if (this.startDate && this.endDate) {
|
217
|
+
this.startDate = null;
|
218
|
+
this.endDate = null;
|
219
|
+
}
|
220
|
+
|
221
|
+
if (this.isSelectingStart) {
|
222
|
+
this.startDate = selectedDate;
|
223
|
+
if (this.endDate && selectedDate > this.endDate) {
|
224
|
+
this.endDate = null;
|
225
|
+
}
|
226
|
+
this.isSelectingStart = false;
|
227
|
+
} else {
|
228
|
+
this.isSelectingStart = true;
|
229
|
+
|
230
|
+
if (this.startDate && selectedDate < this.startDate) {
|
231
|
+
this.startDate = selectedDate;
|
232
|
+
this.endDate = null;
|
233
|
+
this.isSelectingStart = false;
|
234
|
+
} else {
|
235
|
+
this.endDate = selectedDate;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
} else {
|
239
|
+
this.value = selectedDate;
|
240
|
+
this.emit('nile-changed', { value: this.value });
|
241
|
+
if (this.dropdown) {
|
242
|
+
this.dropdown.hide();
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
this.requestUpdate();
|
247
|
+
}
|
248
|
+
|
249
|
+
private confimRange() {
|
250
|
+
if (this.startDate && this.endDate) {
|
251
|
+
this.emit('nile-range-changed', {
|
252
|
+
startDate: this.startDate,
|
253
|
+
endDate: this.endDate,
|
254
|
+
});
|
255
|
+
if (this.dropdown) {
|
256
|
+
this.dropdown.hide();
|
257
|
+
}
|
258
|
+
|
259
|
+
this.rangeValue = {
|
260
|
+
startDate: this.startDate,
|
261
|
+
endDate: this.endDate,
|
262
|
+
};
|
263
|
+
}
|
264
|
+
}
|
265
|
+
|
266
|
+
private renderMonth(
|
267
|
+
year: number,
|
268
|
+
month: number,
|
269
|
+
daysArray: number[]
|
270
|
+
): TemplateResult {
|
271
|
+
const firstDay = new Date(year, month, 1).getDay();
|
272
|
+
const lastDay = new Date(year, month + 1, 0).getDay();
|
273
|
+
const prevMonthDays = this.getDaysArray(
|
274
|
+
month === 0 ? year - 1 : year,
|
275
|
+
month === 0 ? 11 : month - 1
|
276
|
+
);
|
277
|
+
const nextMonthDays = this.getDaysArray(
|
278
|
+
month === 11 ? year + 1 : year,
|
279
|
+
month === 11 ? 0 : month + 1
|
280
|
+
);
|
281
|
+
const fillerDaysBefore = prevMonthDays.slice(
|
282
|
+
prevMonthDays.length - firstDay
|
283
|
+
);
|
284
|
+
const fillerDaysAfter = nextMonthDays.slice(0, 6 - lastDay);
|
285
|
+
const allDays = [...fillerDaysBefore, ...daysArray, ...fillerDaysAfter];
|
286
|
+
|
287
|
+
const isSelectedDate = (
|
288
|
+
day: number,
|
289
|
+
month: number,
|
290
|
+
year: number,
|
291
|
+
isCurrentMonth: boolean
|
292
|
+
) => {
|
293
|
+
if (!isCurrentMonth) return '';
|
294
|
+
|
295
|
+
if (!this.range && this.value) {
|
296
|
+
const isSelected =
|
297
|
+
day === this.value.getDate() &&
|
298
|
+
month === this.value.getMonth() &&
|
299
|
+
year === this.value.getFullYear();
|
300
|
+
if (isSelected) return 'selected-date';
|
301
|
+
}
|
302
|
+
|
303
|
+
const isStartDate =
|
304
|
+
this.startDate &&
|
305
|
+
day === this.startDate.getDate() &&
|
306
|
+
month === this.startDate.getMonth() &&
|
307
|
+
year === this.startDate.getFullYear();
|
308
|
+
const isEndDate =
|
309
|
+
this.endDate &&
|
310
|
+
day === this.endDate.getDate() &&
|
311
|
+
month === this.endDate.getMonth() &&
|
312
|
+
year === this.endDate.getFullYear();
|
313
|
+
|
314
|
+
return isStartDate ? 'range-start' : isEndDate ? 'range-end' : '';
|
315
|
+
};
|
316
|
+
|
317
|
+
const isInRange = (
|
318
|
+
day: number,
|
319
|
+
month: number,
|
320
|
+
year: number,
|
321
|
+
isCurrentMonth: boolean
|
322
|
+
) => {
|
323
|
+
if (!isCurrentMonth) return false;
|
324
|
+
if (this.startDate && this.endDate) {
|
325
|
+
const date = new Date(year, month, day);
|
326
|
+
return date >= this.startDate && date <= this.endDate;
|
327
|
+
}
|
328
|
+
return false;
|
329
|
+
};
|
330
|
+
|
331
|
+
return html`
|
332
|
+
<div class="calendar">
|
333
|
+
<div class="calendar-header">
|
334
|
+
<nile-icon name="arrowleft" color="black" @click="${this.prevMonth}">
|
335
|
+
</nile-icon>
|
336
|
+
<span
|
337
|
+
>${new Date(year, month).toLocaleString('default', {
|
338
|
+
month: 'long',
|
339
|
+
})}
|
340
|
+
${year}</span
|
341
|
+
>
|
342
|
+
<nile-icon name="arrowright" color="black" @click="${this.nextMonth}">
|
343
|
+
</nile-icon>
|
344
|
+
</div>
|
345
|
+
<div class="day-names">
|
346
|
+
<div class="day">Sun</div>
|
347
|
+
<div class="day">Mon</div>
|
348
|
+
<div class="day">Tue</div>
|
349
|
+
<div class="day">Wed</div>
|
350
|
+
<div class="day">Thu</div>
|
351
|
+
<div class="day">Fri</div>
|
352
|
+
<div class="day">Sat</div>
|
353
|
+
</div>
|
354
|
+
<div class="days">
|
355
|
+
${allDays.map((day, index) => {
|
356
|
+
const isCurrentMonth =
|
357
|
+
index >= fillerDaysBefore.length &&
|
358
|
+
index < fillerDaysBefore.length + daysArray.length;
|
359
|
+
return html` <div
|
360
|
+
class="day ${isSelectedDate(
|
361
|
+
day,
|
362
|
+
month,
|
363
|
+
year,
|
364
|
+
isCurrentMonth
|
365
|
+
)} ${isInRange(day, month, year, isCurrentMonth)
|
366
|
+
? 'in-range'
|
367
|
+
: ''} ${!isCurrentMonth ? 'filler' : ''}"
|
368
|
+
@click="${() => {
|
369
|
+
if (isCurrentMonth) {
|
370
|
+
this.selectDate(day, month, year);
|
371
|
+
}
|
372
|
+
}}"
|
373
|
+
>
|
374
|
+
${day}
|
375
|
+
</div>`;
|
376
|
+
})}
|
377
|
+
</div>
|
378
|
+
</div>
|
379
|
+
`;
|
380
|
+
}
|
381
|
+
|
382
|
+
private formatDate(date: Date | null): string {
|
383
|
+
if (!date) return '';
|
384
|
+
const day = String(date.getDate()).padStart(2, '0');
|
385
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
386
|
+
const year = date.getFullYear();
|
387
|
+
return `${day}/${month}/${year}`;
|
388
|
+
}
|
389
|
+
|
390
|
+
private formatDateRange(value: { startDate: Date | null, endDate: Date | null }): string {
|
391
|
+
if(!value){
|
392
|
+
return value;
|
393
|
+
}
|
394
|
+
if (!value.startDate || !value.endDate) return '';
|
395
|
+
return `${this.formatDate(value.startDate)} - ${this.formatDate(value.endDate)}`;
|
396
|
+
}
|
397
|
+
|
398
|
+
private handleStartDateInput(event: CustomEvent): void {
|
399
|
+
const date = this.parseDate(event.detail.value);
|
400
|
+
if (!this.isValidDateInput(date)) {
|
401
|
+
this.startDate = null;
|
402
|
+
}
|
403
|
+
if (date && (!this.endDate || date <= this.endDate)) {
|
404
|
+
this.startDate = date;
|
405
|
+
} else {
|
406
|
+
this.startDate = null;
|
407
|
+
this.endDate = null;
|
408
|
+
}
|
409
|
+
this.requestUpdate();
|
410
|
+
}
|
411
|
+
|
412
|
+
private handleEndDateInput(event: CustomEvent): void {
|
413
|
+
const date = this.parseDate(event.detail.value);
|
414
|
+
if (!this.isValidDateInput(date)) {
|
415
|
+
this.endDate = null;
|
416
|
+
}
|
417
|
+
if (date && (!this.startDate || date >= this.startDate)) {
|
418
|
+
this.endDate = date;
|
419
|
+
} else {
|
420
|
+
this.endDate = null;
|
421
|
+
|
422
|
+
}
|
423
|
+
this.requestUpdate();
|
424
|
+
}
|
425
|
+
|
426
|
+
private parseDate(dateString: string): Date | null {
|
427
|
+
const [day, month, year] = dateString.split('/').map(Number);
|
428
|
+
const date = new Date(year, month - 1, day);
|
429
|
+
return !isNaN(date.getTime()) ? date : null;
|
430
|
+
}
|
431
|
+
|
432
|
+
private isValidDateInput(input: any): boolean {
|
433
|
+
const regex = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/;
|
434
|
+
return regex.test(input);
|
435
|
+
}
|
436
|
+
|
437
|
+
private formatTime(date: Date | null): string {
|
438
|
+
if (!date) return '';
|
439
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
440
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
441
|
+
const seconds = String(date.getSeconds()).padStart(2, '0');
|
442
|
+
return `${hours}:${minutes}:${seconds}`;
|
443
|
+
}
|
444
|
+
|
445
|
+
// Validate time in HH:MM:SS format
|
446
|
+
private isValidTimeInput(input: string): boolean {
|
447
|
+
const regex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;
|
448
|
+
return regex.test(input);
|
449
|
+
}
|
450
|
+
|
451
|
+
// Parse time string to a Date object
|
452
|
+
private parseTime(input: string, date: Date): Date | null {
|
453
|
+
if (!this.isValidTimeInput(input)) {
|
454
|
+
return null;
|
455
|
+
}
|
456
|
+
const [hour, minute, second] = input.split(':').map(Number);
|
457
|
+
const newDate = new Date(date.getTime());
|
458
|
+
newDate.setHours(hour, minute, second);
|
459
|
+
return newDate;
|
460
|
+
}
|
461
|
+
|
462
|
+
private handleStartTimeInput(event: CustomEvent): void {
|
463
|
+
if (!this.startDate) {
|
464
|
+
this.startDate = null;
|
465
|
+
return;
|
466
|
+
}
|
467
|
+
const time = this.parseTime(event.detail.value, this.startDate);
|
468
|
+
if (time) {
|
469
|
+
this.startDate = time;
|
470
|
+
} else {
|
471
|
+
this.startDate.setHours(0, 0, 0);
|
472
|
+
}
|
473
|
+
this.requestUpdate();
|
474
|
+
}
|
475
|
+
|
476
|
+
private handleEndTimeInput(event: CustomEvent): void {
|
477
|
+
if (!this.endDate) {
|
478
|
+
this.endDate = null;
|
479
|
+
return;
|
480
|
+
}
|
481
|
+
const time = this.parseTime(event.detail.value, this.endDate);
|
482
|
+
if (time) {
|
483
|
+
this.endDate = time;
|
484
|
+
} else {
|
485
|
+
this.endDate.setHours(0, 0, 0);
|
486
|
+
}
|
487
|
+
this.requestUpdate();
|
488
|
+
}
|
489
|
+
|
490
|
+
|
491
|
+
|
492
|
+
/* #endregion */
|
493
|
+
|
494
|
+
/* #region Methods */
|
495
|
+
|
496
|
+
/**
|
497
|
+
* Render method
|
498
|
+
* @slot This is a slot test
|
499
|
+
*/
|
500
|
+
render(): TemplateResult {
|
501
|
+
const daysArray = this.getDaysArray(this.currentYear, this.currentMonth);
|
502
|
+
const nextMonth = (this.currentMonth + 1) % 12;
|
503
|
+
const nextYear =
|
504
|
+
this.currentMonth === 11 ? this.currentYear + 1 : this.currentYear;
|
505
|
+
const nextMonthDaysArray = this.getDaysArray(nextYear, nextMonth);
|
506
|
+
|
507
|
+
return html`
|
508
|
+
<nile-dropdown>
|
509
|
+
${this.range ? html`
|
510
|
+
<nile-input
|
511
|
+
slot="trigger"
|
512
|
+
label="Choose a date range"
|
513
|
+
readonly
|
514
|
+
value="${this.formatDateRange(this.rangeValue)}"
|
515
|
+
>
|
516
|
+
<nile-icon name="calendar" slot="suffix"> </nile-icon>
|
517
|
+
</nile-input>
|
518
|
+
` : html`
|
519
|
+
<nile-input
|
520
|
+
slot="trigger"
|
521
|
+
label="Choose a date"
|
522
|
+
readonly
|
523
|
+
value="${this.formatDate(this.value)}"
|
524
|
+
>
|
525
|
+
<nile-icon name="calendar" slot="suffix"> </nile-icon>
|
526
|
+
</nile-input>
|
527
|
+
`}
|
528
|
+
|
529
|
+
<div class="base">
|
530
|
+
<div class="calendar-wrapper">
|
531
|
+
<div class="calendar-container ${this.range ? 'with-margin' : ''}">
|
532
|
+
${this.renderMonth(
|
533
|
+
this.currentYear,
|
534
|
+
this.currentMonth,
|
535
|
+
this.getDaysArray(this.currentYear, this.currentMonth)
|
536
|
+
)}
|
537
|
+
</div>
|
538
|
+
${this.range
|
539
|
+
? html`
|
540
|
+
<div class="calendar-container">
|
541
|
+
${this.renderMonth(
|
542
|
+
this.currentYear,
|
543
|
+
(this.currentMonth + 1) % 12,
|
544
|
+
this.getDaysArray(
|
545
|
+
this.currentYear,
|
546
|
+
(this.currentMonth + 1) % 12
|
547
|
+
)
|
548
|
+
)}
|
549
|
+
</div>
|
550
|
+
`
|
551
|
+
: ''}
|
552
|
+
</div>
|
553
|
+
${this.range
|
554
|
+
? html`
|
555
|
+
<div class="calender-input">
|
556
|
+
<span class="manual-input-label">From </span>
|
557
|
+
<div class="from">
|
558
|
+
<nile-input class="manual-input" value="${this.formatDate(this.startDate)}" placeholder="DD/MM/YYYY" @nile-change="${this.handleStartDateInput}"></nile-input>
|
559
|
+
<nile-input class="manual-input" value="${this.formatTime(this.startDate)}" placeholder="HH:MM:SS" @nile-change="${this.handleStartTimeInput}"> </nile-input>
|
560
|
+
|
561
|
+
</div>
|
562
|
+
<br>
|
563
|
+
<span class="manual-input-label">To </span>
|
564
|
+
<div class="from">
|
565
|
+
<nile-input class="manual-input" value="${this.formatDate(this.endDate)}" placeholder="DD/MM/YYYY" @nile-change="${this.handleEndDateInput}"></nile-input>
|
566
|
+
<nile-input class="manual-input" value="${this.formatTime(this.endDate)}" placeholder="HH:MM:SS" @nile-change="${this.handleEndTimeInput}"> </nile-input>
|
567
|
+
</div>
|
568
|
+
<nile-button class="apply-button" ?disabled="${
|
569
|
+
!this.startDate || !this.endDate
|
570
|
+
}" @click="${this.confimRange}"> Apply</nile-button>
|
571
|
+
|
572
|
+
</div>
|
573
|
+
</div>
|
574
|
+
`
|
575
|
+
: ''}
|
576
|
+
</div>
|
577
|
+
</nile-dropdown>
|
578
|
+
`;
|
579
|
+
}
|
580
|
+
}
|
581
|
+
|
582
|
+
export default NileDatePicker;
|
583
|
+
|
584
|
+
declare global {
|
585
|
+
interface HTMLElementTagNameMap {
|
586
|
+
'nile-date-picker': NileDatePicker;
|
587
|
+
}
|
588
|
+
}
|