update
This commit is contained in:
@ -298,6 +298,73 @@ export const demoFunc = () => html`
|
|||||||
</dees-panel>
|
</dees-panel>
|
||||||
</dees-demowrapper>
|
</dees-demowrapper>
|
||||||
|
|
||||||
|
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
||||||
|
// Generate sample events for the calendar
|
||||||
|
const today = new Date();
|
||||||
|
const currentMonth = today.getMonth();
|
||||||
|
const currentYear = today.getFullYear();
|
||||||
|
|
||||||
|
const sampleEvents = [
|
||||||
|
// Current week events
|
||||||
|
{
|
||||||
|
date: `${currentYear}-${(currentMonth + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`,
|
||||||
|
title: "Team Meeting",
|
||||||
|
type: "info" as const,
|
||||||
|
count: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: `${currentYear}-${(currentMonth + 1).toString().padStart(2, '0')}-${(today.getDate() + 1).toString().padStart(2, '0')}`,
|
||||||
|
title: "Project Deadline",
|
||||||
|
type: "warning" as const
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: `${currentYear}-${(currentMonth + 1).toString().padStart(2, '0')}-${(today.getDate() + 2).toString().padStart(2, '0')}`,
|
||||||
|
title: "Release Day",
|
||||||
|
type: "success" as const
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: `${currentYear}-${(currentMonth + 1).toString().padStart(2, '0')}-${(today.getDate() + 5).toString().padStart(2, '0')}`,
|
||||||
|
title: "Urgent Fix Required",
|
||||||
|
type: "error" as const
|
||||||
|
},
|
||||||
|
// Multiple events on one day
|
||||||
|
{
|
||||||
|
date: `${currentYear}-${(currentMonth + 1).toString().padStart(2, '0')}-${(today.getDate() + 7).toString().padStart(2, '0')}`,
|
||||||
|
title: "Multiple Events Today",
|
||||||
|
type: "info" as const,
|
||||||
|
count: 5
|
||||||
|
},
|
||||||
|
// Next month event
|
||||||
|
{
|
||||||
|
date: `${currentYear}-${(currentMonth + 2).toString().padStart(2, '0')}-15`,
|
||||||
|
title: "Future Planning Session",
|
||||||
|
type: "info" as const
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const picker = elementArg.querySelector('dees-input-datepicker');
|
||||||
|
if (picker) {
|
||||||
|
picker.events = sampleEvents;
|
||||||
|
console.log('Calendar events loaded:', sampleEvents);
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<dees-panel .title=${'Calendar with Events'} .subtitle=${'Visual feedback for scheduled events'}>
|
||||||
|
<dees-input-datepicker
|
||||||
|
label="Event Calendar"
|
||||||
|
description="Days with colored dots have events. Hover to see details."
|
||||||
|
></dees-input-datepicker>
|
||||||
|
|
||||||
|
<div class="demo-output" style="margin-top: 16px;">
|
||||||
|
<strong>Event Legend:</strong><br>
|
||||||
|
<span style="color: #0969da;">● Info</span> |
|
||||||
|
<span style="color: #d29922;">● Warning</span> |
|
||||||
|
<span style="color: #2ea043;">● Success</span> |
|
||||||
|
<span style="color: #cf222e;">● Error</span><br>
|
||||||
|
<em>Days with more than 3 events show a count badge</em>
|
||||||
|
</div>
|
||||||
|
</dees-panel>
|
||||||
|
</dees-demowrapper>
|
||||||
|
|
||||||
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
||||||
// Interactive event demonstration
|
// Interactive event demonstration
|
||||||
const picker = elementArg.querySelector('dees-input-datepicker');
|
const picker = elementArg.querySelector('dees-input-datepicker');
|
||||||
|
@ -12,6 +12,14 @@ import { demoFunc } from './dees-input-datepicker.demo.js';
|
|||||||
import './dees-icon.js';
|
import './dees-icon.js';
|
||||||
import './dees-label.js';
|
import './dees-label.js';
|
||||||
|
|
||||||
|
export interface IDateEvent {
|
||||||
|
date: string; // ISO date string (YYYY-MM-DD)
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
type?: 'info' | 'warning' | 'success' | 'error';
|
||||||
|
count?: number; // Number of events on this day
|
||||||
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
'dees-input-datepicker': DeesInputDatepicker;
|
'dees-input-datepicker': DeesInputDatepicker;
|
||||||
@ -58,6 +66,9 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
|
|||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
public timezone: string = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
public timezone: string = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
|
||||||
|
@property({ type: Array })
|
||||||
|
public events: IDateEvent[] = [];
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private isOpened: boolean = false;
|
private isOpened: boolean = false;
|
||||||
|
|
||||||
@ -327,6 +338,95 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
|
|||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Event indicators */
|
||||||
|
.day.has-event {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-indicator {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 4px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-dot {
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: ${cssManager.bdTheme('hsl(220 8.9% 46.1%)', 'hsl(215 20.2% 65.1%)')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-dot.info {
|
||||||
|
background: ${cssManager.bdTheme('hsl(211 70% 52%)', 'hsl(211 70% 62%)')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-dot.warning {
|
||||||
|
background: ${cssManager.bdTheme('hsl(45 90% 45%)', 'hsl(45 90% 55%)')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-dot.success {
|
||||||
|
background: ${cssManager.bdTheme('hsl(142 69% 45%)', 'hsl(142 69% 55%)')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-dot.error {
|
||||||
|
background: ${cssManager.bdTheme('hsl(0 72% 51%)', 'hsl(0 72% 61%)')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-count {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
|
min-width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
padding: 0 4px;
|
||||||
|
background: ${cssManager.bdTheme('hsl(0 72% 51%)', 'hsl(0 72% 61%)')};
|
||||||
|
color: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltip for event details */
|
||||||
|
.event-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
bottom: calc(100% + 8px);
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
|
||||||
|
color: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 0%)')};
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
z-index: 10;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-tooltip::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
border: 4px solid transparent;
|
||||||
|
border-top-color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.day.has-event:hover .event-tooltip {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Time selector */
|
/* Time selector */
|
||||||
.time-selector {
|
.time-selector {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
@ -589,13 +689,33 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
|
|||||||
const isSelected = this.isSelected(day);
|
const isSelected = this.isSelected(day);
|
||||||
const isOtherMonth = day.getMonth() !== this.viewDate.getMonth();
|
const isOtherMonth = day.getMonth() !== this.viewDate.getMonth();
|
||||||
const isDisabled = this.isDisabled(day);
|
const isDisabled = this.isDisabled(day);
|
||||||
|
const dayEvents = this.getEventsForDate(day);
|
||||||
|
const hasEvents = dayEvents.length > 0;
|
||||||
|
const totalEventCount = dayEvents.reduce((sum, event) => sum + (event.count || 1), 0);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
class="day ${isOtherMonth ? 'other-month' : ''} ${isToday ? 'today' : ''} ${isSelected ? 'selected' : ''} ${isDisabled ? 'disabled' : ''}"
|
class="day ${isOtherMonth ? 'other-month' : ''} ${isToday ? 'today' : ''} ${isSelected ? 'selected' : ''} ${isDisabled ? 'disabled' : ''} ${hasEvents ? 'has-event' : ''}"
|
||||||
@click="${() => !isDisabled && this.selectDate(day)}"
|
@click="${() => !isDisabled && this.selectDate(day)}"
|
||||||
>
|
>
|
||||||
${day.getDate()}
|
${day.getDate()}
|
||||||
|
${hasEvents ? html`
|
||||||
|
${totalEventCount > 3 ? html`
|
||||||
|
<div class="event-count">${totalEventCount}</div>
|
||||||
|
` : html`
|
||||||
|
<div class="event-indicator">
|
||||||
|
${dayEvents.slice(0, 3).map(event => html`
|
||||||
|
<div class="event-dot ${event.type || 'info'}"></div>
|
||||||
|
`)}
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
${dayEvents[0].title ? html`
|
||||||
|
<div class="event-tooltip">
|
||||||
|
${dayEvents[0].title}
|
||||||
|
${totalEventCount > 1 ? html` (+${totalEventCount - 1} more)` : ''}
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
` : ''}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
@ -876,6 +996,13 @@ export class DeesInputDatepicker extends DeesInputBase<DeesInputDatepicker> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getEventsForDate(date: Date): IDateEvent[] {
|
||||||
|
if (!this.events || this.events.length === 0) return [];
|
||||||
|
|
||||||
|
const dateStr = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
|
||||||
|
return this.events.filter(event => event.date === dateStr);
|
||||||
|
}
|
||||||
|
|
||||||
private selectDate(date: Date): void {
|
private selectDate(date: Date): void {
|
||||||
this.selectedDate = new Date(
|
this.selectedDate = new Date(
|
||||||
date.getFullYear(),
|
date.getFullYear(),
|
||||||
|
Reference in New Issue
Block a user