This commit is contained in:
Juergen Kunz
2025-06-30 10:58:31 +00:00
parent 60a811fd18
commit 2c12c22666
3 changed files with 138 additions and 9 deletions

View File

@ -455,15 +455,15 @@ Dynamic list input for managing arrays of typed values.
```
#### `DeesInputDatepicker`
Date and time picker component with calendar interface.
Date and time picker component with calendar interface and manual typing support.
```typescript
<dees-input-datepicker
key="eventDate"
label="Event Date"
placeholder="Select date"
placeholder="YYYY-MM-DD"
value="2025-01-15T14:30:00Z" // ISO string format
dateFormat="DD/MM/YYYY" // Display format
dateFormat="YYYY-MM-DD" // Display format (default: YYYY-MM-DD)
enableTime={true} // Enable time selection
timeFormat="24h" // Options: 24h, 12h
minuteIncrement={15} // Time step in minutes
@ -481,6 +481,7 @@ Date and time picker component with calendar interface.
Key Features:
- Interactive calendar popup
- Manual date typing with multiple formats
- Optional time selection
- Configurable date format
- Min/max date constraints
@ -490,6 +491,22 @@ Key Features:
- Clear functionality
- 12/24 hour time formats
- Theme-aware styling
- Live parsing and validation
Manual Input Formats:
```typescript
// Date formats supported
"2023-12-20" // ISO format (YYYY-MM-DD)
"20.12.2023" // European format (DD.MM.YYYY)
"12/20/2023" // US format (MM/DD/YYYY)
// Date with time (add space and time after any date format)
"2023-12-20 14:30"
"20.12.2023 9:45"
"12/20/2023 16:00"
```
The component automatically parses and validates input as you type, updating the internal date value when a valid date is recognized.
#### `DeesInputSearchselect`
Search-enabled dropdown selection component.

View File

@ -56,7 +56,6 @@ export const demoFunc = () => html`
<dees-input-datepicker
label="Select Date"
description="Choose a date from the calendar"
placeholder="Pick a date"
></dees-input-datepicker>
</dees-panel>
</dees-demowrapper>

View File

@ -35,7 +35,7 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
public minuteIncrement: number = 1;
@property({ type: String })
public dateFormat: string = 'DD/MM/YYYY';
public dateFormat: string = 'YYYY-MM-DD';
@property({ type: String })
public minDate: string = '';
@ -50,7 +50,7 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
public weekStartsOn: 0 | 1 = 1; // Default to Monday
@property({ type: String })
public placeholder: string = 'Select date';
public placeholder: string = 'YYYY-MM-DD';
@state()
private isOpened: boolean = false;
@ -479,7 +479,8 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
?disabled=${this.disabled}
@click=${this.toggleCalendar}
@keydown=${this.handleKeydown}
readonly
@input=${this.handleManualInput}
@blur=${this.handleInputBlur}
style="padding-right: ${this.value ? '64px' : '40px'}"
/>
<div class="icon-container">
@ -641,10 +642,11 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear().toString();
formatted = formatted.replace('DD', day);
formatted = formatted.replace('MM', month);
// Replace in correct order to avoid conflicts
formatted = formatted.replace('YYYY', year);
formatted = formatted.replace('YY', year.slice(-2));
formatted = formatted.replace('MM', month);
formatted = formatted.replace('DD', day);
// Time formatting if enabled
if (this.enableTime) {
@ -894,6 +896,117 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
this.changeSubject.next(this);
}
private handleManualInput(e: InputEvent): void {
const input = e.target as HTMLInputElement;
const inputValue = input.value.trim();
if (!inputValue) {
// Clear the value if input is empty
this.value = '';
this.selectedDate = null;
return;
}
const parsedDate = this.parseManualDate(inputValue);
if (parsedDate && !isNaN(parsedDate.getTime())) {
// Update internal state without triggering re-render of input
this.value = parsedDate.toISOString();
this.selectedDate = parsedDate;
this.viewDate = new Date(parsedDate);
this.selectedHour = parsedDate.getHours();
this.selectedMinute = parsedDate.getMinutes();
this.changeSubject.next(this);
}
}
private handleInputBlur(e: FocusEvent): void {
const input = e.target as HTMLInputElement;
const inputValue = input.value.trim();
if (!inputValue) {
this.value = '';
this.selectedDate = null;
this.changeSubject.next(this);
return;
}
const parsedDate = this.parseManualDate(inputValue);
if (parsedDate && !isNaN(parsedDate.getTime())) {
this.value = parsedDate.toISOString();
this.selectedDate = parsedDate;
this.viewDate = new Date(parsedDate);
this.selectedHour = parsedDate.getHours();
this.selectedMinute = parsedDate.getMinutes();
this.changeSubject.next(this);
// Update the input with formatted date
input.value = this.formatDate(this.value);
} else {
// Revert to previous valid value on blur if parsing failed
input.value = this.formatDate(this.value);
}
}
private parseManualDate(input: string): Date | null {
if (!input) return null;
// Split date and time parts if present
const parts = input.split(' ');
let datePart = parts[0];
let timePart = parts[1] || '';
let parsedDate: Date | null = null;
// Try different date formats
// Format 1: YYYY-MM-DD (ISO-like)
const isoMatch = datePart.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
if (isoMatch) {
const [_, year, month, day] = isoMatch;
parsedDate = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
}
// Format 2: DD.MM.YYYY (European)
if (!parsedDate) {
const euMatch = datePart.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/);
if (euMatch) {
const [_, day, month, year] = euMatch;
parsedDate = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
}
}
// Format 3: MM/DD/YYYY (US)
if (!parsedDate) {
const usMatch = datePart.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
if (usMatch) {
const [_, month, day, year] = usMatch;
parsedDate = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
}
}
// If no date was parsed, return null
if (!parsedDate || isNaN(parsedDate.getTime())) {
return null;
}
// Parse time if present (HH:MM format)
if (timePart) {
const timeMatch = timePart.match(/^(\d{1,2}):(\d{2})$/);
if (timeMatch) {
const [_, hours, minutes] = timeMatch;
parsedDate.setHours(parseInt(hours));
parsedDate.setMinutes(parseInt(minutes));
}
} else if (!this.enableTime) {
// If time is not enabled and not provided, use current time
const now = new Date();
parsedDate.setHours(now.getHours());
parsedDate.setMinutes(now.getMinutes());
parsedDate.setSeconds(0);
parsedDate.setMilliseconds(0);
}
return parsedDate;
}
public getValue(): string {
return this.value;
}