| class CustomCalendar extends HTMLElement { |
| connectedCallback() { |
| this.attachShadow({ mode: 'open' }); |
| this.renderCalendar(new Date()); |
| } |
|
|
| renderCalendar(date) { |
| const monthNames = ["January", "February", "March", "April", "May", "June", |
| "July", "August", "September", "October", "November", "December" |
| ]; |
|
|
| const firstDay = new Date(date.getFullYear(), date.getMonth(), 1); |
| const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0); |
| const daysInMonth = lastDay.getDate(); |
| const startingDay = firstDay.getDay(); |
|
|
| let calendarHTML = ''; |
| let day = 1; |
|
|
| this.shadowRoot.innerHTML = ` |
| <style> |
| .calendar { |
| width: 100%; |
| max-width: 400px; |
| background: white; |
| border-radius: 0.75rem; |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); |
| padding: 1rem; |
| } |
| .calendar-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 1rem; |
| } |
| .calendar-title { |
| font-size: 1.25rem; |
| font-weight: 600; |
| color: #1a365d; |
| } |
| .calendar-nav { |
| display: flex; |
| gap: 0.5rem; |
| } |
| .calendar-nav button { |
| background: #edf2f7; |
| border: none; |
| border-radius: 0.375rem; |
| padding: 0.25rem 0.5rem; |
| cursor: pointer; |
| } |
| .calendar-weekdays { |
| display: grid; |
| grid-template-columns: repeat(7, 1fr); |
| text-align: center; |
| font-weight: 500; |
| margin-bottom: 0.5rem; |
| } |
| .calendar-days { |
| display: grid; |
| grid-template-columns: repeat(7, 1fr); |
| gap: 0.25rem; |
| } |
| .calendar-day { |
| padding: 0.5rem; |
| text-align: center; |
| border-radius: 0.375rem; |
| cursor: pointer; |
| } |
| .calendar-day:hover { |
| background: #ebf8ff; |
| } |
| .calendar-day.empty { |
| visibility: hidden; |
| } |
| .calendar-day.today { |
| background: #4299e1; |
| color: white; |
| } |
| .calendar-day.selected { |
| background: #3182ce; |
| color: white; |
| } |
| </style> |
| <div class="calendar"> |
| <div class="calendar-header"> |
| <div class="calendar-title">${monthNames[date.getMonth()]} ${date.getFullYear()}</div> |
| <div class="calendar-nav"> |
| <button id="prevMonth"><</button> |
| <button id="nextMonth">></button> |
| </div> |
| </div> |
| <div class="calendar-weekdays"> |
| <div>Sun</div> |
| <div>Mon</div> |
| <div>Tue</div> |
| <div>Wed</div> |
| <div>Thu</div> |
| <div>Fri</div> |
| <div>Sat</div> |
| </div> |
| <div class="calendar-days"> |
| ${Array(42).fill().map((_, i) => { |
| if (i < startingDay || day > daysInMonth) { |
| return `<div class="calendar-day empty"></div>`; |
| } |
| const currentDay = day; |
| const isToday = currentDay === new Date().getDate() && |
| date.getMonth() === new Date().getMonth() && |
| date.getFullYear() === new Date().getFullYear(); |
| day++; |
| return `<div class="calendar-day ${isToday ? 'today' : ''}">${currentDay}</div>`; |
| }).join('')} |
| </div> |
| </div> |
| `; |
|
|
| this.shadowRoot.getElementById('prevMonth').addEventListener('click', () => { |
| this.renderCalendar(new Date(date.getFullYear(), date.getMonth() - 1, 1)); |
| }); |
|
|
| this.shadowRoot.getElementById('nextMonth').addEventListener('click', () => { |
| this.renderCalendar(new Date(date.getFullYear(), date.getMonth() + 1, 1)); |
| }); |
| } |
| } |
|
|
| customElements.define('custom-calendar', CustomCalendar); |