Compare commits
9 Commits
1.0.0
..
acf1728cb9
| Author | SHA1 | Date | |
|---|---|---|---|
| acf1728cb9 | |||
| 722e674526 | |||
| a777e585e8 | |||
| 56d5d3ab1c | |||
| 1e5a4bc3d3 | |||
| 3641de7ebd | |||
| 9fc38c42e8 | |||
| 7fb1757174 | |||
| f5377e83ad |
+3
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@tp/tp-date-input",
|
"name": "@tp/tp-date-input",
|
||||||
"version": "1.0.0",
|
"version": "2.1.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "tp-date-input.js",
|
"main": "tp-date-input.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -13,8 +13,7 @@
|
|||||||
"author": "trading_peter",
|
"author": "trading_peter",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"date-fns": "^2.28.0",
|
"luxon": "^3.0.0",
|
||||||
"date-fns-tz": "^1.3.3",
|
"lit": "^3.0.0"
|
||||||
"lit": "^2.2.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-25
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
@license
|
@license
|
||||||
Copyright (c) 2022 trading_peter
|
Copyright (c) 2025 trading_peter
|
||||||
This program is available under Apache License Version 2.0
|
This program is available under Apache License Version 2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -9,8 +9,7 @@ import { ControlState } from '@tp/helpers/control-state.js';
|
|||||||
import { EventHelpers } from '@tp/helpers/event-helpers.js';
|
import { EventHelpers } from '@tp/helpers/event-helpers.js';
|
||||||
import { FormElement } from '@tp/helpers/form-element.js';
|
import { FormElement } from '@tp/helpers/form-element.js';
|
||||||
import { LitElement, html, css } from 'lit';
|
import { LitElement, html, css } from 'lit';
|
||||||
import { format, parse, parseISO, isAfter, isValid, endOfDay } from 'date-fns/esm';
|
import { DateTime } from 'luxon';
|
||||||
import { zonedTimeToUtc } from 'date-fns-tz/esm';
|
|
||||||
import { closest } from '@tp/helpers';
|
import { closest } from '@tp/helpers';
|
||||||
|
|
||||||
class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
||||||
@@ -181,7 +180,7 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
super.firstUpdated();
|
super.firstUpdated();
|
||||||
this.listen(this, 'input', '_autoMoveCursor');
|
this.listen(this, 'input', '_autoMoveCursor');
|
||||||
|
|
||||||
const datepicker = this.querySelector('tp-datepicker');
|
const datepicker = this.querySelector('tp-date-picker');
|
||||||
if (datepicker) {
|
if (datepicker) {
|
||||||
datepicker.addEventListener('value-changed', e => {
|
datepicker.addEventListener('value-changed', e => {
|
||||||
this.value = e.detail;
|
this.value = e.detail;
|
||||||
@@ -232,14 +231,14 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
* of the control, like allowedDates, maxDate, ...
|
* of the control, like allowedDates, maxDate, ...
|
||||||
*/
|
*/
|
||||||
dateValid(date, maxDate = this.maxDate, allowedDates = this.allowedDates) {
|
dateValid(date, maxDate = this.maxDate, allowedDates = this.allowedDates) {
|
||||||
date = this._toDate(date);
|
const dt = this._toDateTime(date);
|
||||||
|
|
||||||
if (isValid(date) === false) {
|
if (!dt || !dt.isValid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((allowedDates.length > 0 && allowedDates.indexOf(date) === -1) ||
|
if ((allowedDates.length > 0 && allowedDates.indexOf(date) === -1) ||
|
||||||
(maxDate && isAfter(date, maxDate))) {
|
(maxDate && dt > this._toDateTime(maxDate))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -292,14 +291,27 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const date = parse(i0 + '-' + i1 + '-' + i2, this._inputAssign.join('-'), new Date());
|
// Convert luxon format to match input assignment
|
||||||
|
const luxonFormat = this._inputAssign.map(part => {
|
||||||
|
switch (part) {
|
||||||
|
case 'MM': return 'LL';
|
||||||
|
case 'dd': return 'dd';
|
||||||
|
case 'y': return 'yyyy';
|
||||||
|
default: return part;
|
||||||
|
}
|
||||||
|
}).join('-');
|
||||||
|
|
||||||
if (isValid(date)) {
|
// Parse the date in the specified timezone (or local if not set).
|
||||||
|
// This interprets the entered values as being in that timezone.
|
||||||
|
const dt = DateTime.fromFormat(i0 + '-' + i1 + '-' + i2, luxonFormat, { zone: this.timeZone || 'local' });
|
||||||
|
|
||||||
|
if (dt.isValid) {
|
||||||
this.inputs[0].invalid = false;
|
this.inputs[0].invalid = false;
|
||||||
this.inputs[1].invalid = false;
|
this.inputs[1].invalid = false;
|
||||||
this.inputs[2].invalid = false;
|
this.inputs[2].invalid = false;
|
||||||
this.date = this.timeZone ? zonedTimeToUtc(date, this.timeZone) : date;
|
|
||||||
this.value = this.date.toISOString();
|
this.date = dt.toJSDate();
|
||||||
|
this.value = dt.toUTC().toISO();
|
||||||
this.invalid = false;
|
this.invalid = false;
|
||||||
this.dispatchEvent(new CustomEvent('value-changed', { detail: this.value, bubbles: true, composed: true }));
|
this.dispatchEvent(new CustomEvent('value-changed', { detail: this.value, bubbles: true, composed: true }));
|
||||||
} else {
|
} else {
|
||||||
@@ -378,8 +390,9 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
_setClass(idx) {
|
_setClass(idx) {
|
||||||
switch (this._inputAssign[idx]) {
|
switch (this._inputAssign[idx]) {
|
||||||
case 'dd':
|
case 'dd':
|
||||||
|
return 'day';
|
||||||
case 'MM':
|
case 'MM':
|
||||||
return '';
|
return 'month';
|
||||||
case 'y':
|
case 'y':
|
||||||
return 'year';
|
return 'year';
|
||||||
}
|
}
|
||||||
@@ -411,6 +424,10 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._inputAssign.length !== 3) {
|
||||||
|
console.error(this.tagname + ': Not all date parts where found. Make sure to have MM, dd, and y in your format string.');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.value) {
|
if (this.value) {
|
||||||
this._onValueChanged();
|
this._onValueChanged();
|
||||||
}
|
}
|
||||||
@@ -439,7 +456,7 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
|
|
||||||
this.invalid = false;
|
this.invalid = false;
|
||||||
|
|
||||||
if (this.value === null || this.value === undefined || this.value === 'Invalid date') {
|
if (this.value === null || this.value === undefined || this.value === 'Invalid date' || this.value === '') {
|
||||||
this.date = null;
|
this.date = null;
|
||||||
this.value = null;
|
this.value = null;
|
||||||
this._input0 = '';
|
this._input0 = '';
|
||||||
@@ -448,18 +465,35 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const date = this._toDate(this.value);
|
let dt = this._toDateTime(this.value);
|
||||||
this._input0 = format(date, this._inputAssign[0]);
|
if (dt && dt.isValid) {
|
||||||
this._input1 = format(date, this._inputAssign[1]);
|
// Convert to user's timezone for display (input values are expected to be UTC)
|
||||||
this._input2 = format(date, this._inputAssign[2]);
|
if (this.timeZone) {
|
||||||
this.date = date;
|
dt = dt.setZone(this.timeZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert luxon format parts to match display format
|
||||||
|
this._input0 = dt.toFormat(this._getLuxonFormat(this._inputAssign[0]));
|
||||||
|
this._input1 = dt.toFormat(this._getLuxonFormat(this._inputAssign[1]));
|
||||||
|
this._input2 = dt.toFormat(this._getLuxonFormat(this._inputAssign[2]));
|
||||||
|
this.date = dt.toJSDate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getLuxonFormat(inputFormat) {
|
||||||
|
switch (inputFormat) {
|
||||||
|
case 'MM': return 'LL';
|
||||||
|
case 'dd': return 'dd';
|
||||||
|
case 'y': return 'yyyy';
|
||||||
|
default: return inputFormat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setToday() {
|
_setToday() {
|
||||||
if (this.today) {
|
if (this.today) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!this.value) {
|
if (!this.value) {
|
||||||
this.value = new Date().toISOString();
|
this.value = DateTime.now().toISO();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -468,9 +502,9 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
_getMaxDate(maxDate) {
|
_getMaxDate(maxDate) {
|
||||||
if (typeof maxDate !== 'string') return null;
|
if (typeof maxDate !== 'string') return null;
|
||||||
if (maxDate.toLowerCase() === 'today') {
|
if (maxDate.toLowerCase() === 'today') {
|
||||||
return endOfDay(new Date());
|
return DateTime.now().endOf('day');
|
||||||
}
|
}
|
||||||
return this._toDate(maxDate);
|
return this._toDateTime(maxDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
_autoMoveCursor(e) {
|
_autoMoveCursor(e) {
|
||||||
@@ -481,13 +515,16 @@ class TpDateInput extends EventHelpers(ControlState(FormElement(LitElement))) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_toDate(value) {
|
_toDateTime(value) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
return parseISO(value);
|
return DateTime.fromISO(value);
|
||||||
} else {
|
} else if (value instanceof Date) {
|
||||||
|
return DateTime.fromJSDate(value);
|
||||||
|
} else if (value && typeof value === 'object' && value.isLuxonDateTime) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.customElements.define('tp-date-input', TpDateInput);
|
window.customElements.define('tp-date-input', TpDateInput);
|
||||||
Reference in New Issue
Block a user