@triptease/tt-calendar 6.1.2 → 6.2.0

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.
@@ -20,6 +20,9 @@ class Calendar extends lit_1.LitElement {
20
20
  constructor() {
21
21
  super(...arguments);
22
22
  this.range = false;
23
+ this.displayOnly = false;
24
+ this.highlightedRanges = [];
25
+ this._parsedHighlights = [];
23
26
  this.focusedDate = this.today;
24
27
  this.visible = false;
25
28
  this.newWeek = () => new Array(7).fill(null);
@@ -29,6 +32,8 @@ class Calendar extends lit_1.LitElement {
29
32
  }
30
33
  };
31
34
  this.onDayHover = (event) => {
35
+ if (this.displayOnly)
36
+ return;
32
37
  const day = event.target.dataset.date;
33
38
  if (!day)
34
39
  return;
@@ -59,6 +64,14 @@ class Calendar extends lit_1.LitElement {
59
64
  }
60
65
  return luxon_1.Interval.invalid('Invalid range');
61
66
  }
67
+ willUpdate(changedProperties) {
68
+ if (changedProperties.has('highlightedRanges')) {
69
+ this._parsedHighlights = this.highlightedRanges.map((range) => ({
70
+ start: luxon_1.DateTime.fromISO(range.startDate),
71
+ end: luxon_1.DateTime.fromISO(range.endDate),
72
+ }));
73
+ }
74
+ }
62
75
  updated(changedProperties) {
63
76
  if (changedProperties.has('value') && this.value) {
64
77
  super.updateComplete.then(() => {
@@ -98,6 +111,8 @@ class Calendar extends lit_1.LitElement {
98
111
  }
99
112
  }
100
113
  handleKeyDown(event) {
114
+ if (this.displayOnly)
115
+ return;
101
116
  const currentDate = this.focusedDate;
102
117
  switch (event.key) {
103
118
  case 'ArrowLeft':
@@ -161,7 +176,7 @@ class Calendar extends lit_1.LitElement {
161
176
  focusDay(date) {
162
177
  this.focusedDate = date;
163
178
  this.updateComplete.then(() => {
164
- const dayElement = this.shadowRoot?.querySelector(`.day[data-date="${date.toISO()}"]`);
179
+ const dayElement = (this.shadowRoot?.querySelector(`.day[data-date="${date.toISODate()}"]`));
165
180
  if (dayElement) {
166
181
  dayElement.focus();
167
182
  }
@@ -205,6 +220,8 @@ class Calendar extends lit_1.LitElement {
205
220
  return luxon_1.DateTime.local();
206
221
  }
207
222
  handleDayClick(day) {
223
+ if (this.displayOnly)
224
+ return;
208
225
  if (this.isRange()) {
209
226
  if (!this.value?.startDate || this.value?.endDate) {
210
227
  this.value = { startDate: day.toISODate() };
@@ -260,6 +277,18 @@ class Calendar extends lit_1.LitElement {
260
277
  get isSelectingRange() {
261
278
  return Boolean(this.isRange() && this.value?.startDate && !this.value?.endDate);
262
279
  }
280
+ isHighlighted(date) {
281
+ return this._parsedHighlights.some(({ start, end }) => date >= start && date <= end);
282
+ }
283
+ isHighlightedStart(date) {
284
+ return this._parsedHighlights.some(({ start, end }) => date.equals(start) && !start.equals(end));
285
+ }
286
+ isHighlightedEnd(date) {
287
+ return this._parsedHighlights.some(({ start, end }) => date.equals(end) && !start.equals(end));
288
+ }
289
+ isHighlightedInRange(date) {
290
+ return this._parsedHighlights.some(({ start, end }) => date > start && date < end);
291
+ }
263
292
  handleToggle(e) {
264
293
  const details = e.target;
265
294
  if (details.open) {
@@ -270,48 +299,51 @@ class Calendar extends lit_1.LitElement {
270
299
  }
271
300
  }
272
301
  render() {
273
- const weeks = this.getDaysInMonth(this.focusedDate);
274
- const monthYear = this.focusedDate.toLocaleString({
302
+ const displayDate = this.month ? luxon_1.DateTime.fromISO(this.month + '-01') : this.focusedDate;
303
+ const weeks = this.getDaysInMonth(displayDate);
304
+ const monthYear = displayDate.toLocaleString({
275
305
  month: 'long',
276
306
  year: 'numeric',
277
307
  });
278
308
  return (0, lit_1.html) `
279
309
  <div class="calendar-panel" @keydown=${this.handleKeyDown} role="application" aria-label="${monthYear}">
280
- <div class="calendar-header">
281
- <button
282
- @click=${this.previousYear}
283
- @keydown=${this.handleButtonKeyDown}
284
- aria-label="Previous year"
285
- class="compact"
286
- >
287
- ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.doubleChevron)}
288
- </button>
289
- <button
290
- @click=${this.previousMonth}
291
- @keydown="${this.handleButtonKeyDown}"
292
- aria-label="Previous month"
293
- class="compact"
294
- >
295
- ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.chevron)}
296
- </button>
297
- <h2>${monthYear}</h2>
298
- <button
299
- @click=${this.nextMonth}
300
- @keydown="${this.handleButtonKeyDown}"
301
- aria-label="Next month"
302
- class="compact right"
303
- >
304
- ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.chevron)}
305
- </button>
306
- <button
307
- @click=${this.nextYear}
308
- @keydown=${this.handleButtonKeyDown}
309
- aria-label="Next year"
310
- class="compact right"
311
- >
312
- ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.doubleChevron)}
313
- </button>
314
- </div>
310
+ ${this.displayOnly
311
+ ? lit_1.nothing
312
+ : (0, lit_1.html) `<div class="calendar-header">
313
+ <button
314
+ @click=${this.previousYear}
315
+ @keydown=${this.handleButtonKeyDown}
316
+ aria-label="Previous year"
317
+ class="compact"
318
+ >
319
+ ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.doubleChevron)}
320
+ </button>
321
+ <button
322
+ @click=${this.previousMonth}
323
+ @keydown="${this.handleButtonKeyDown}"
324
+ aria-label="Previous month"
325
+ class="compact"
326
+ >
327
+ ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.chevron)}
328
+ </button>
329
+ <h2>${monthYear}</h2>
330
+ <button
331
+ @click=${this.nextMonth}
332
+ @keydown="${this.handleButtonKeyDown}"
333
+ aria-label="Next month"
334
+ class="compact right"
335
+ >
336
+ ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.chevron)}
337
+ </button>
338
+ <button
339
+ @click=${this.nextYear}
340
+ @keydown=${this.handleButtonKeyDown}
341
+ aria-label="Next year"
342
+ class="compact right"
343
+ >
344
+ ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.doubleChevron)}
345
+ </button>
346
+ </div>`}
315
347
  <div class="calendar-grid">
316
348
  <table
317
349
  role="grid"
@@ -335,15 +367,15 @@ class Calendar extends lit_1.LitElement {
335
367
  return (0, lit_1.html) ` <td
336
368
  class="${(0, class_map_js_1.classMap)({
337
369
  day: true,
338
- 'in-range': this.isInRange(day),
339
- 'start-date': this.isStartDate(day),
340
- 'end-date': this.isEndDate(day),
370
+ 'in-range': this.isInRange(day) || this.isHighlightedInRange(day),
371
+ 'start-date': this.isStartDate(day) || this.isHighlightedStart(day),
372
+ 'end-date': this.isEndDate(day) || this.isHighlightedEnd(day),
341
373
  })}"
342
374
  @click=${() => this.handleDayClick(day)}
343
375
  role="gridcell"
344
376
  data-date="${day.toISODate()}"
345
377
  aria-label="${day.toLocaleString({ dateStyle: 'long' })}"
346
- aria-selected="${this.isSelected(day)}"
378
+ aria-selected="${this.isSelected(day) || this.isHighlighted(day)}"
347
379
  aria-disabled="${isDisabled}"
348
380
  tabindex="-1"
349
381
  @mouseenter="${this.onDayHover}"
@@ -356,32 +388,36 @@ class Calendar extends lit_1.LitElement {
356
388
  </table>
357
389
  </div>
358
390
 
359
- <div class="calendar-footer">
360
- <div class="actions" @keydown="${this.handleButtonKeyDown}">
361
- ${this.isRange()
362
- ? (0, lit_1.html) `
363
- <button @click=${() => this.handleClearSelection()} data-theme="secondary" id="clear-selection">
364
- Clear selection
365
- </button>
366
- `
367
- : (0, lit_1.html) ` <button @click=${() => this.handleDayClick(this.today)} data-theme="secondary">Today</button> `}
368
- </div>
369
- <div>
370
- <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>
371
- <summary>${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.keyboard)} Keyboard commands ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.chevronDown)}</summary>
372
- <p>Arrow keys: navigate the calendar</p>
373
- <p>Enter or Space: select the date</p>
374
- <p>Escape: close the calendar without selecting a date</p>
375
- <p>Tab: navigate between the calendar and the presets</p>
376
- <p>Home: move to first day of week</p>
377
- <p>End: move to last day of week</p>
378
- <p>Page Up: move to previous month</p>
379
- <p>Page Down: move to next month</p>
380
- <p>Shift + Page Up: move to next year</p>
381
- <p>Shift + Page Down: move to previous year</p>
382
- </details>
383
- </div>
384
- </div>
391
+ ${this.displayOnly
392
+ ? lit_1.nothing
393
+ : (0, lit_1.html) `<div class="calendar-footer">
394
+ <div class="actions" @keydown="${this.handleButtonKeyDown}">
395
+ ${this.isRange()
396
+ ? (0, lit_1.html) `
397
+ <button @click=${() => this.handleClearSelection()} data-theme="secondary" id="clear-selection">
398
+ Clear selection
399
+ </button>
400
+ `
401
+ : (0, lit_1.html) `
402
+ <button @click=${() => this.handleDayClick(this.today)} data-theme="secondary">Today</button>
403
+ `}
404
+ </div>
405
+ <div>
406
+ <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>
407
+ <summary>${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.keyboard)} Keyboard commands ${(0, unsafe_svg_js_1.unsafeSVG)(icons_1.chevronDown)}</summary>
408
+ <p>Arrow keys: navigate the calendar</p>
409
+ <p>Enter or Space: select the date</p>
410
+ <p>Escape: close the calendar without selecting a date</p>
411
+ <p>Tab: navigate between the calendar and the presets</p>
412
+ <p>Home: move to first day of week</p>
413
+ <p>End: move to last day of week</p>
414
+ <p>Page Up: move to previous month</p>
415
+ <p>Page Down: move to next month</p>
416
+ <p>Shift + Page Up: move to next year</p>
417
+ <p>Shift + Page Down: move to previous year</p>
418
+ </details>
419
+ </div>
420
+ </div>`}
385
421
  </div>
386
422
  `;
387
423
  }
@@ -423,6 +459,15 @@ __decorate([
423
459
  __decorate([
424
460
  (0, decorators_js_1.property)({ type: Number, attribute: 'min-days' })
425
461
  ], Calendar.prototype, "minDays", void 0);
462
+ __decorate([
463
+ (0, decorators_js_1.property)({ type: Boolean, reflect: true, attribute: 'display-only' })
464
+ ], Calendar.prototype, "displayOnly", void 0);
465
+ __decorate([
466
+ (0, decorators_js_1.property)({ type: String })
467
+ ], Calendar.prototype, "month", void 0);
468
+ __decorate([
469
+ (0, decorators_js_1.property)({ attribute: false })
470
+ ], Calendar.prototype, "highlightedRanges", void 0);
426
471
  __decorate([
427
472
  (0, decorators_js_1.query)('.calendar-panel')
428
473
  ], Calendar.prototype, "calendarDiv", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"TtCalendar.js","sourceRoot":"","sources":["../../../src/TtCalendar.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, PropertyValues } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { unsafeSVG } from 'lit/directives/unsafe-svg.js';\nimport { DateTime, Interval } from 'luxon';\nimport { DateRange, DateRangeSelectionEvent, DateSelectionEvent } from './DateSelectionContext.js';\nimport { chevron, chevronDown, doubleChevron, keyboard } from '@triptease/icons';\nimport { styles } from './Styles.js';\nimport { dateTimeConverter } from './helpers.js';\n\ntype WeekdayList = [\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n];\n\ninterface CalendarWithRange {\n value?: DateRange;\n range: true;\n}\n\ninterface InternalDateRange {\n startDate?: DateTime;\n endDate?: DateTime;\n}\n\nexport class Calendar extends LitElement {\n static styles = styles;\n\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n // Start public properties\n\n @property({ type: String })\n public value?: string | DateRange;\n\n @property({ type: Boolean })\n public range = false;\n\n @property({ attribute: 'max-date', converter: dateTimeConverter })\n public maxDate?: DateTime;\n\n @property({ type: Number, attribute: 'max-days' })\n public maxDays?: number;\n\n @property({ attribute: 'min-date', converter: dateTimeConverter })\n public minDate?: DateTime;\n\n @property({ type: Number, attribute: 'min-days' })\n public minDays?: number;\n\n get internalRangeValue(): InternalDateRange {\n if (this.range && this.value) {\n const startDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : undefined;\n const endDate = (this.value as DateRange)?.endDate\n ? DateTime.fromISO((this.value as DateRange).endDate!)\n : undefined;\n return { startDate, endDate };\n }\n return { startDate: undefined, endDate: undefined };\n }\n\n getRange(): Interval {\n if (this.range && this.internalRangeValue.startDate && this.internalRangeValue.endDate) {\n return Interval.fromDateTimes(\n this.internalRangeValue.startDate,\n this.internalRangeValue.endDate.plus({ days: 1 })\n );\n }\n return Interval.invalid('Invalid range');\n }\n\n public updated(changedProperties: PropertyValues) {\n if (changedProperties.has('value') && this.value) {\n super.updateComplete.then(() => {\n if (!this.range) {\n const parsedDate = DateTime.fromISO(this.value as string);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = this.internalRangeValue?.startDate || this.today;\n }\n });\n }\n super.updated(changedProperties);\n }\n\n public toggleVisibility() {\n if (this.visible) {\n this.visible = false;\n } else {\n this.visible = true;\n this.updateComplete.then(() => {\n this.calendarDiv.focus();\n this.calendarDiv.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n });\n if (!this.range) {\n const parsedDate = DateTime.fromISO((this.value as string) ?? this.today);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : this.today;\n }\n }\n }\n\n // end public properties\n\n @query('.calendar-panel')\n private calendarDiv!: HTMLElement;\n\n @state()\n private focusedDate: DateTime = this.today;\n\n @state()\n private visible: boolean = false;\n\n private handleKeyDown(event: KeyboardEvent) {\n const currentDate = this.focusedDate;\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n this.focusDay(currentDate.minus({ day: 1 }));\n break;\n case 'ArrowRight':\n event.preventDefault();\n this.focusDay(currentDate.plus({ day: 1 }));\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusDay(currentDate.minus({ week: 1 }));\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.focusDay(currentDate.plus({ week: 1 }));\n break;\n case 'Home':\n event.preventDefault();\n // Move to first day of week\n this.focusDay(currentDate.startOf('week'));\n break;\n case 'End':\n event.preventDefault();\n // Move to last day of week\n this.focusDay(currentDate.endOf('week'));\n break;\n case 'PageUp':\n event.preventDefault();\n if (event.shiftKey) {\n // Previous year\n this.focusDay(currentDate.minus({ year: 1 }));\n } else {\n // Previous month\n this.focusDay(currentDate.minus({ month: 1 }));\n }\n break;\n case 'PageDown':\n event.preventDefault();\n if (event.shiftKey) {\n // Next year\n this.focusDay(currentDate.plus({ year: 1 }));\n } else {\n // Next month\n this.focusDay(currentDate.plus({ month: 1 }));\n }\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.handleDayClick(this.focusedDate);\n return;\n\n default:\n return;\n }\n\n event.preventDefault();\n }\n\n private focusDay(date: DateTime) {\n this.focusedDate = date;\n this.updateComplete.then(() => {\n const dayElement = <HTMLElement | undefined>this.shadowRoot?.querySelector(`.day[data-date=\"${date.toISO()}\"]`);\n if (dayElement) {\n dayElement.focus();\n }\n });\n }\n\n private newWeek = () => new Array(7).fill(null) as WeekdayList;\n\n private getDaysInMonth(date: DateTime): WeekdayList[] {\n const startOfMonth = date.startOf('month');\n const endOfMonth = date.endOf('month');\n\n const weeks: WeekdayList[] = [];\n let currentWeek: WeekdayList = this.newWeek();\n\n let currentDay = startOfMonth;\n\n while (currentDay <= endOfMonth) {\n // Get the day of week (0-6, Sunday=0, Saturday=6)\n const dayOfWeek = currentDay.weekday === 7 ? 0 : currentDay.weekday;\n\n currentWeek[dayOfWeek] = currentDay;\n\n const isWeekComplete = dayOfWeek === 6; // Saturday (last day of week)\n const isLastDayOfMonth = currentDay.hasSame(endOfMonth, 'day');\n\n if (isWeekComplete || isLastDayOfMonth) {\n weeks.push(currentWeek);\n\n if (!isLastDayOfMonth) {\n currentWeek = this.newWeek();\n }\n }\n\n currentDay = currentDay.plus({ days: 1 });\n }\n\n return weeks;\n }\n\n private previousYear() {\n this.focusedDate = this.focusedDate.minus({ year: 1 });\n }\n\n private previousMonth() {\n this.focusedDate = this.focusedDate.minus({ month: 1 });\n }\n\n private nextMonth() {\n this.focusedDate = this.focusedDate.plus({ month: 1 });\n }\n\n private nextYear() {\n this.focusedDate = this.focusedDate.plus({ year: 1 });\n }\n\n private get today(): DateTime {\n return DateTime.local();\n }\n\n private handleDayClick(day: DateTime) {\n if (this.isRange()) {\n if (!this.value?.startDate || this.value?.endDate) {\n this.value = { startDate: day.toISODate()! };\n this.focusedDate = day;\n return;\n }\n\n if (!this.value.endDate) {\n this.value = { ...(this.value as DateRange), endDate: day.toISODate()! };\n this.focusedDate = day;\n this.dispatchEvent(new DateRangeSelectionEvent(this.value));\n return;\n }\n }\n\n if (day.isValid) {\n this.dispatchEvent(new DateSelectionEvent(day.toISODate()!));\n }\n }\n\n private handleButtonKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.stopPropagation();\n }\n };\n\n private getWeekdayLabels(): string[] {\n const monday = DateTime.fromISO('2024-06-02T00:00:00Z').startOf('week'); //Weeks start on Monday in Luxon https://moment.github.io/luxon/api-docs/index.html#datetimestartof\n const sunday = monday.plus({ days: 6 });\n return Array.from({ length: 7 }, (_, i) => {\n const date = sunday.plus({ days: i });\n return date.toLocaleString({ weekday: 'short' });\n });\n }\n\n private isSelected(date: DateTime): boolean {\n if (date.equals(this.focusedDate)) return true;\n\n if (this.isRange() && this.internalRangeValue.startDate) {\n if (!this.internalRangeValue.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate.plus({ days: 1 }));\n return range.contains(date);\n }\n\n const range = this.getRange();\n return range.contains(date);\n }\n\n return false;\n }\n\n private isInRange(date: DateTime): boolean {\n if (!this.isRange() || !this.internalRangeValue?.startDate) {\n return false;\n }\n\n if (!this.internalRangeValue?.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate);\n return range.contains(date) && !this.isStartDate(date) && !date.equals(this.focusedDate);\n }\n\n const range = this.getRange();\n return range.contains(date) && !this.isStartDate(date) && !this.isEndDate(date);\n }\n\n private isRange(): this is CalendarWithRange {\n return this.range;\n }\n\n private get isSelectingRange(): boolean {\n return Boolean(this.isRange() && this.value?.startDate && !this.value?.endDate);\n }\n\n private onDayHover = (event: MouseEvent) => {\n const day = (event.target as HTMLElement).dataset.date;\n if (!day) return;\n\n this.focusedDate = DateTime.fromISO(day);\n };\n\n private isStartDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.startDate && this.internalRangeValue.startDate.equals(date));\n\n private isEndDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.endDate && this.internalRangeValue.endDate.equals(date));\n\n private handleClearSelection = () => {\n this.value = { startDate: undefined, endDate: undefined };\n this.dispatchEvent(new DateRangeSelectionEvent({ startDate: undefined, endDate: undefined }));\n };\n\n private handleToggle(e: Event) {\n const details = e.target as HTMLDetailsElement;\n if (details.open) {\n details.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n }\n }\n\n render() {\n const weeks = this.getDaysInMonth(this.focusedDate);\n const monthYear = this.focusedDate.toLocaleString({\n month: 'long',\n year: 'numeric',\n });\n\n return html`\n <div class=\"calendar-panel\" @keydown=${this.handleKeyDown} role=\"application\" aria-label=\"${monthYear}\">\n <div class=\"calendar-header\">\n <button\n @click=${this.previousYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Previous year\"\n class=\"compact\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n <button\n @click=${this.previousMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Previous month\"\n class=\"compact\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <h2>${monthYear}</h2>\n <button\n @click=${this.nextMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Next month\"\n class=\"compact right\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <button\n @click=${this.nextYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Next year\"\n class=\"compact right\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n </div>\n <div class=\"calendar-grid\">\n <table\n role=\"grid\"\n aria-labelledby=\"month-year\"\n data-range=\"${this.range}\"\n class=\"${this.isSelectingRange ? 'selecting' : ''}\"\n >\n <thead>\n <tr>\n ${this.getWeekdayLabels().map((label) => html` <th>${label}</th>`)}\n </tr>\n </thead>\n\n <tbody>\n ${weeks.map(\n (week) =>\n html` <tr>\n ${week.map((day) => {\n if (!day) {\n return html` <td></td>`;\n }\n\n const isDisabled = this.dayIsDisabled(day);\n\n return html` <td\n class=\"${classMap({\n day: true,\n 'in-range': this.isInRange(day),\n 'start-date': this.isStartDate(day),\n 'end-date': this.isEndDate(day),\n })}\"\n @click=${() => this.handleDayClick(day)}\n role=\"gridcell\"\n data-date=\"${day.toISODate()}\"\n aria-label=\"${day.toLocaleString({ dateStyle: 'long' })}\"\n aria-selected=\"${this.isSelected(day)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"-1\"\n @mouseenter=\"${this.onDayHover}\"\n >\n ${day.day}\n </td>`;\n })}\n </tr>`\n )}\n </tbody>\n </table>\n </div>\n\n <div class=\"calendar-footer\">\n <div class=\"actions\" @keydown=\"${this.handleButtonKeyDown}\">\n ${this.isRange()\n ? html`\n <button @click=${() => this.handleClearSelection()} data-theme=\"secondary\" id=\"clear-selection\">\n Clear selection\n </button>\n `\n : html` <button @click=${() => this.handleDayClick(this.today)} data-theme=\"secondary\">Today</button> `}\n </div>\n <div>\n <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>\n <summary>${unsafeSVG(keyboard)} Keyboard commands ${unsafeSVG(chevronDown)}</summary>\n <p>Arrow keys: navigate the calendar</p>\n <p>Enter or Space: select the date</p>\n <p>Escape: close the calendar without selecting a date</p>\n <p>Tab: navigate between the calendar and the presets</p>\n <p>Home: move to first day of week</p>\n <p>End: move to last day of week</p>\n <p>Page Up: move to previous month</p>\n <p>Page Down: move to next month</p>\n <p>Shift + Page Up: move to next year</p>\n <p>Shift + Page Down: move to previous year</p>\n </details>\n </div>\n </div>\n </div>\n `;\n }\n\n private dayIsDisabled(day: DateTime) {\n if (this.maxDate && day > this.maxDate) return true;\n\n if (this.minDate && day < this.minDate) return true;\n\n if (this.range && this.isSelectingRange && this.internalRangeValue?.startDate) {\n if (day < this.internalRangeValue.startDate) return true;\n\n if (this.maxDays && day > this.internalRangeValue.startDate.plus({ days: this.maxDays })) return true;\n }\n\n return false;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'tt-calendar': Calendar;\n }\n}\n"]}
1
+ {"version":3,"file":"TtCalendar.js","sourceRoot":"","sources":["../../../src/TtCalendar.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing, PropertyValues } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { unsafeSVG } from 'lit/directives/unsafe-svg.js';\nimport { DateTime, Interval } from 'luxon';\nimport { DateRange, DateRangeSelectionEvent, DateSelectionEvent } from './DateSelectionContext.js';\nimport { chevron, chevronDown, doubleChevron, keyboard } from '@triptease/icons';\nimport { styles } from './Styles.js';\nimport { dateTimeConverter } from './helpers.js';\n\ntype WeekdayList = [\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n];\n\ninterface CalendarWithRange {\n value?: DateRange;\n range: true;\n}\n\ninterface InternalDateRange {\n startDate?: DateTime;\n endDate?: DateTime;\n}\n\nexport class Calendar extends LitElement {\n static styles = styles;\n\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n // Start public properties\n\n @property({ type: String })\n public value?: string | DateRange;\n\n @property({ type: Boolean })\n public range = false;\n\n @property({ attribute: 'max-date', converter: dateTimeConverter })\n public maxDate?: DateTime;\n\n @property({ type: Number, attribute: 'max-days' })\n public maxDays?: number;\n\n @property({ attribute: 'min-date', converter: dateTimeConverter })\n public minDate?: DateTime;\n\n @property({ type: Number, attribute: 'min-days' })\n public minDays?: number;\n\n @property({ type: Boolean, reflect: true, attribute: 'display-only' })\n public displayOnly: boolean = false;\n\n @property({ type: String })\n public month?: string;\n\n @property({ attribute: false })\n public highlightedRanges: Required<DateRange>[] = [];\n\n private _parsedHighlights: { start: DateTime; end: DateTime }[] = [];\n\n get internalRangeValue(): InternalDateRange {\n if (this.range && this.value) {\n const startDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : undefined;\n const endDate = (this.value as DateRange)?.endDate\n ? DateTime.fromISO((this.value as DateRange).endDate!)\n : undefined;\n return { startDate, endDate };\n }\n return { startDate: undefined, endDate: undefined };\n }\n\n getRange(): Interval {\n if (this.range && this.internalRangeValue.startDate && this.internalRangeValue.endDate) {\n return Interval.fromDateTimes(\n this.internalRangeValue.startDate,\n this.internalRangeValue.endDate.plus({ days: 1 })\n );\n }\n return Interval.invalid('Invalid range');\n }\n\n protected override willUpdate(changedProperties: PropertyValues) {\n if (changedProperties.has('highlightedRanges')) {\n this._parsedHighlights = this.highlightedRanges.map((range) => ({\n start: DateTime.fromISO(range.startDate),\n end: DateTime.fromISO(range.endDate),\n }));\n }\n }\n\n public updated(changedProperties: PropertyValues) {\n if (changedProperties.has('value') && this.value) {\n super.updateComplete.then(() => {\n if (!this.range) {\n const parsedDate = DateTime.fromISO(this.value as string);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = this.internalRangeValue?.startDate || this.today;\n }\n });\n }\n super.updated(changedProperties);\n }\n\n public toggleVisibility() {\n if (this.visible) {\n this.visible = false;\n } else {\n this.visible = true;\n this.updateComplete.then(() => {\n this.calendarDiv.focus();\n this.calendarDiv.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n });\n if (!this.range) {\n const parsedDate = DateTime.fromISO((this.value as string) ?? this.today);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : this.today;\n }\n }\n }\n\n // end public properties\n\n @query('.calendar-panel')\n private calendarDiv!: HTMLElement;\n\n @state()\n private focusedDate: DateTime = this.today;\n\n @state()\n private visible: boolean = false;\n\n private handleKeyDown(event: KeyboardEvent) {\n if (this.displayOnly) return;\n const currentDate = this.focusedDate;\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n this.focusDay(currentDate.minus({ day: 1 }));\n break;\n case 'ArrowRight':\n event.preventDefault();\n this.focusDay(currentDate.plus({ day: 1 }));\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusDay(currentDate.minus({ week: 1 }));\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.focusDay(currentDate.plus({ week: 1 }));\n break;\n case 'Home':\n event.preventDefault();\n // Move to first day of week\n this.focusDay(currentDate.startOf('week'));\n break;\n case 'End':\n event.preventDefault();\n // Move to last day of week\n this.focusDay(currentDate.endOf('week'));\n break;\n case 'PageUp':\n event.preventDefault();\n if (event.shiftKey) {\n // Previous year\n this.focusDay(currentDate.minus({ year: 1 }));\n } else {\n // Previous month\n this.focusDay(currentDate.minus({ month: 1 }));\n }\n break;\n case 'PageDown':\n event.preventDefault();\n if (event.shiftKey) {\n // Next year\n this.focusDay(currentDate.plus({ year: 1 }));\n } else {\n // Next month\n this.focusDay(currentDate.plus({ month: 1 }));\n }\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.handleDayClick(this.focusedDate);\n return;\n\n default:\n return;\n }\n\n event.preventDefault();\n }\n\n public focusDay(date: DateTime) {\n this.focusedDate = date;\n this.updateComplete.then(() => {\n const dayElement = <HTMLElement | undefined>(\n this.shadowRoot?.querySelector(`.day[data-date=\"${date.toISODate()}\"]`)\n );\n if (dayElement) {\n dayElement.focus();\n }\n });\n }\n\n private newWeek = () => new Array(7).fill(null) as WeekdayList;\n\n private getDaysInMonth(date: DateTime): WeekdayList[] {\n const startOfMonth = date.startOf('month');\n const endOfMonth = date.endOf('month');\n\n const weeks: WeekdayList[] = [];\n let currentWeek: WeekdayList = this.newWeek();\n\n let currentDay = startOfMonth;\n\n while (currentDay <= endOfMonth) {\n // Get the day of week (0-6, Sunday=0, Saturday=6)\n const dayOfWeek = currentDay.weekday === 7 ? 0 : currentDay.weekday;\n\n currentWeek[dayOfWeek] = currentDay;\n\n const isWeekComplete = dayOfWeek === 6; // Saturday (last day of week)\n const isLastDayOfMonth = currentDay.hasSame(endOfMonth, 'day');\n\n if (isWeekComplete || isLastDayOfMonth) {\n weeks.push(currentWeek);\n\n if (!isLastDayOfMonth) {\n currentWeek = this.newWeek();\n }\n }\n\n currentDay = currentDay.plus({ days: 1 });\n }\n\n return weeks;\n }\n\n private previousYear() {\n this.focusedDate = this.focusedDate.minus({ year: 1 });\n }\n\n private previousMonth() {\n this.focusedDate = this.focusedDate.minus({ month: 1 });\n }\n\n private nextMonth() {\n this.focusedDate = this.focusedDate.plus({ month: 1 });\n }\n\n private nextYear() {\n this.focusedDate = this.focusedDate.plus({ year: 1 });\n }\n\n private get today(): DateTime {\n return DateTime.local();\n }\n\n private handleDayClick(day: DateTime) {\n if (this.displayOnly) return;\n if (this.isRange()) {\n if (!this.value?.startDate || this.value?.endDate) {\n this.value = { startDate: day.toISODate()! };\n this.focusedDate = day;\n return;\n }\n\n if (!this.value.endDate) {\n this.value = { ...(this.value as DateRange), endDate: day.toISODate()! };\n this.focusedDate = day;\n this.dispatchEvent(new DateRangeSelectionEvent(this.value));\n return;\n }\n }\n\n if (day.isValid) {\n this.dispatchEvent(new DateSelectionEvent(day.toISODate()!));\n }\n }\n\n private handleButtonKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.stopPropagation();\n }\n };\n\n private getWeekdayLabels(): string[] {\n const monday = DateTime.fromISO('2024-06-02T00:00:00Z').startOf('week'); //Weeks start on Monday in Luxon https://moment.github.io/luxon/api-docs/index.html#datetimestartof\n const sunday = monday.plus({ days: 6 });\n return Array.from({ length: 7 }, (_, i) => {\n const date = sunday.plus({ days: i });\n return date.toLocaleString({ weekday: 'short' });\n });\n }\n\n private isSelected(date: DateTime): boolean {\n if (date.equals(this.focusedDate)) return true;\n\n if (this.isRange() && this.internalRangeValue.startDate) {\n if (!this.internalRangeValue.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate.plus({ days: 1 }));\n return range.contains(date);\n }\n\n const range = this.getRange();\n return range.contains(date);\n }\n\n return false;\n }\n\n private isInRange(date: DateTime): boolean {\n if (!this.isRange() || !this.internalRangeValue?.startDate) {\n return false;\n }\n\n if (!this.internalRangeValue?.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate);\n return range.contains(date) && !this.isStartDate(date) && !date.equals(this.focusedDate);\n }\n\n const range = this.getRange();\n return range.contains(date) && !this.isStartDate(date) && !this.isEndDate(date);\n }\n\n private isRange(): this is CalendarWithRange {\n return this.range;\n }\n\n private get isSelectingRange(): boolean {\n return Boolean(this.isRange() && this.value?.startDate && !this.value?.endDate);\n }\n\n private onDayHover = (event: MouseEvent) => {\n if (this.displayOnly) return;\n const day = (event.target as HTMLElement).dataset.date;\n if (!day) return;\n\n this.focusedDate = DateTime.fromISO(day);\n };\n\n private isStartDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.startDate && this.internalRangeValue.startDate.equals(date));\n\n private isEndDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.endDate && this.internalRangeValue.endDate.equals(date));\n\n private handleClearSelection = () => {\n this.value = { startDate: undefined, endDate: undefined };\n this.dispatchEvent(new DateRangeSelectionEvent({ startDate: undefined, endDate: undefined }));\n };\n\n private isHighlighted(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date >= start && date <= end);\n }\n\n private isHighlightedStart(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date.equals(start) && !start.equals(end));\n }\n\n private isHighlightedEnd(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date.equals(end) && !start.equals(end));\n }\n\n private isHighlightedInRange(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date > start && date < end);\n }\n\n private handleToggle(e: Event) {\n const details = e.target as HTMLDetailsElement;\n if (details.open) {\n details.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n }\n }\n\n render() {\n const displayDate = this.month ? DateTime.fromISO(this.month + '-01') : this.focusedDate;\n const weeks = this.getDaysInMonth(displayDate);\n const monthYear = displayDate.toLocaleString({\n month: 'long',\n year: 'numeric',\n });\n\n return html`\n <div class=\"calendar-panel\" @keydown=${this.handleKeyDown} role=\"application\" aria-label=\"${monthYear}\">\n ${this.displayOnly\n ? nothing\n : html`<div class=\"calendar-header\">\n <button\n @click=${this.previousYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Previous year\"\n class=\"compact\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n <button\n @click=${this.previousMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Previous month\"\n class=\"compact\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <h2>${monthYear}</h2>\n <button\n @click=${this.nextMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Next month\"\n class=\"compact right\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <button\n @click=${this.nextYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Next year\"\n class=\"compact right\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n </div>`}\n <div class=\"calendar-grid\">\n <table\n role=\"grid\"\n aria-labelledby=\"month-year\"\n data-range=\"${this.range}\"\n class=\"${this.isSelectingRange ? 'selecting' : ''}\"\n >\n <thead>\n <tr>\n ${this.getWeekdayLabels().map((label) => html` <th>${label}</th>`)}\n </tr>\n </thead>\n\n <tbody>\n ${weeks.map(\n (week) =>\n html` <tr>\n ${week.map((day) => {\n if (!day) {\n return html` <td></td>`;\n }\n\n const isDisabled = this.dayIsDisabled(day);\n\n return html` <td\n class=\"${classMap({\n day: true,\n 'in-range': this.isInRange(day) || this.isHighlightedInRange(day),\n 'start-date': this.isStartDate(day) || this.isHighlightedStart(day),\n 'end-date': this.isEndDate(day) || this.isHighlightedEnd(day),\n })}\"\n @click=${() => this.handleDayClick(day)}\n role=\"gridcell\"\n data-date=\"${day.toISODate()}\"\n aria-label=\"${day.toLocaleString({ dateStyle: 'long' })}\"\n aria-selected=\"${this.isSelected(day) || this.isHighlighted(day)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"-1\"\n @mouseenter=\"${this.onDayHover}\"\n >\n ${day.day}\n </td>`;\n })}\n </tr>`\n )}\n </tbody>\n </table>\n </div>\n\n ${this.displayOnly\n ? nothing\n : html`<div class=\"calendar-footer\">\n <div class=\"actions\" @keydown=\"${this.handleButtonKeyDown}\">\n ${this.isRange()\n ? html`\n <button @click=${() => this.handleClearSelection()} data-theme=\"secondary\" id=\"clear-selection\">\n Clear selection\n </button>\n `\n : html`\n <button @click=${() => this.handleDayClick(this.today)} data-theme=\"secondary\">Today</button>\n `}\n </div>\n <div>\n <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>\n <summary>${unsafeSVG(keyboard)} Keyboard commands ${unsafeSVG(chevronDown)}</summary>\n <p>Arrow keys: navigate the calendar</p>\n <p>Enter or Space: select the date</p>\n <p>Escape: close the calendar without selecting a date</p>\n <p>Tab: navigate between the calendar and the presets</p>\n <p>Home: move to first day of week</p>\n <p>End: move to last day of week</p>\n <p>Page Up: move to previous month</p>\n <p>Page Down: move to next month</p>\n <p>Shift + Page Up: move to next year</p>\n <p>Shift + Page Down: move to previous year</p>\n </details>\n </div>\n </div>`}\n </div>\n `;\n }\n\n private dayIsDisabled(day: DateTime) {\n if (this.maxDate && day > this.maxDate) return true;\n\n if (this.minDate && day < this.minDate) return true;\n\n if (this.range && this.isSelectingRange && this.internalRangeValue?.startDate) {\n if (day < this.internalRangeValue.startDate) return true;\n\n if (this.maxDays && day > this.internalRangeValue.startDate.plus({ days: this.maxDays })) return true;\n }\n\n return false;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'tt-calendar': Calendar;\n }\n}\n"]}
@@ -21,15 +21,20 @@ export declare class Calendar extends LitElement {
21
21
  maxDays?: number;
22
22
  minDate?: DateTime;
23
23
  minDays?: number;
24
+ displayOnly: boolean;
25
+ month?: string;
26
+ highlightedRanges: Required<DateRange>[];
27
+ private _parsedHighlights;
24
28
  get internalRangeValue(): InternalDateRange;
25
29
  getRange(): Interval;
30
+ protected willUpdate(changedProperties: PropertyValues): void;
26
31
  updated(changedProperties: PropertyValues): void;
27
32
  toggleVisibility(): void;
28
33
  private calendarDiv;
29
34
  private focusedDate;
30
35
  private visible;
31
36
  private handleKeyDown;
32
- private focusDay;
37
+ focusDay(date: DateTime): void;
33
38
  private newWeek;
34
39
  private getDaysInMonth;
35
40
  private previousYear;
@@ -48,6 +53,10 @@ export declare class Calendar extends LitElement {
48
53
  private isStartDate;
49
54
  private isEndDate;
50
55
  private handleClearSelection;
56
+ private isHighlighted;
57
+ private isHighlightedStart;
58
+ private isHighlightedEnd;
59
+ private isHighlightedInRange;
51
60
  private handleToggle;
52
61
  render(): import("lit-html").TemplateResult<1>;
53
62
  private dayIsDisabled;
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { html, LitElement } from 'lit';
7
+ import { html, LitElement, nothing } from 'lit';
8
8
  import { property, query, state } from 'lit/decorators.js';
9
9
  import { classMap } from 'lit/directives/class-map.js';
10
10
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
@@ -17,6 +17,9 @@ export class Calendar extends LitElement {
17
17
  constructor() {
18
18
  super(...arguments);
19
19
  this.range = false;
20
+ this.displayOnly = false;
21
+ this.highlightedRanges = [];
22
+ this._parsedHighlights = [];
20
23
  this.focusedDate = this.today;
21
24
  this.visible = false;
22
25
  this.newWeek = () => new Array(7).fill(null);
@@ -26,6 +29,8 @@ export class Calendar extends LitElement {
26
29
  }
27
30
  };
28
31
  this.onDayHover = (event) => {
32
+ if (this.displayOnly)
33
+ return;
29
34
  const day = event.target.dataset.date;
30
35
  if (!day)
31
36
  return;
@@ -56,6 +61,14 @@ export class Calendar extends LitElement {
56
61
  }
57
62
  return Interval.invalid('Invalid range');
58
63
  }
64
+ willUpdate(changedProperties) {
65
+ if (changedProperties.has('highlightedRanges')) {
66
+ this._parsedHighlights = this.highlightedRanges.map((range) => ({
67
+ start: DateTime.fromISO(range.startDate),
68
+ end: DateTime.fromISO(range.endDate),
69
+ }));
70
+ }
71
+ }
59
72
  updated(changedProperties) {
60
73
  if (changedProperties.has('value') && this.value) {
61
74
  super.updateComplete.then(() => {
@@ -95,6 +108,8 @@ export class Calendar extends LitElement {
95
108
  }
96
109
  }
97
110
  handleKeyDown(event) {
111
+ if (this.displayOnly)
112
+ return;
98
113
  const currentDate = this.focusedDate;
99
114
  switch (event.key) {
100
115
  case 'ArrowLeft':
@@ -158,7 +173,7 @@ export class Calendar extends LitElement {
158
173
  focusDay(date) {
159
174
  this.focusedDate = date;
160
175
  this.updateComplete.then(() => {
161
- const dayElement = this.shadowRoot?.querySelector(`.day[data-date="${date.toISO()}"]`);
176
+ const dayElement = (this.shadowRoot?.querySelector(`.day[data-date="${date.toISODate()}"]`));
162
177
  if (dayElement) {
163
178
  dayElement.focus();
164
179
  }
@@ -202,6 +217,8 @@ export class Calendar extends LitElement {
202
217
  return DateTime.local();
203
218
  }
204
219
  handleDayClick(day) {
220
+ if (this.displayOnly)
221
+ return;
205
222
  if (this.isRange()) {
206
223
  if (!this.value?.startDate || this.value?.endDate) {
207
224
  this.value = { startDate: day.toISODate() };
@@ -257,6 +274,18 @@ export class Calendar extends LitElement {
257
274
  get isSelectingRange() {
258
275
  return Boolean(this.isRange() && this.value?.startDate && !this.value?.endDate);
259
276
  }
277
+ isHighlighted(date) {
278
+ return this._parsedHighlights.some(({ start, end }) => date >= start && date <= end);
279
+ }
280
+ isHighlightedStart(date) {
281
+ return this._parsedHighlights.some(({ start, end }) => date.equals(start) && !start.equals(end));
282
+ }
283
+ isHighlightedEnd(date) {
284
+ return this._parsedHighlights.some(({ start, end }) => date.equals(end) && !start.equals(end));
285
+ }
286
+ isHighlightedInRange(date) {
287
+ return this._parsedHighlights.some(({ start, end }) => date > start && date < end);
288
+ }
260
289
  handleToggle(e) {
261
290
  const details = e.target;
262
291
  if (details.open) {
@@ -267,48 +296,51 @@ export class Calendar extends LitElement {
267
296
  }
268
297
  }
269
298
  render() {
270
- const weeks = this.getDaysInMonth(this.focusedDate);
271
- const monthYear = this.focusedDate.toLocaleString({
299
+ const displayDate = this.month ? DateTime.fromISO(this.month + '-01') : this.focusedDate;
300
+ const weeks = this.getDaysInMonth(displayDate);
301
+ const monthYear = displayDate.toLocaleString({
272
302
  month: 'long',
273
303
  year: 'numeric',
274
304
  });
275
305
  return html `
276
306
  <div class="calendar-panel" @keydown=${this.handleKeyDown} role="application" aria-label="${monthYear}">
277
- <div class="calendar-header">
278
- <button
279
- @click=${this.previousYear}
280
- @keydown=${this.handleButtonKeyDown}
281
- aria-label="Previous year"
282
- class="compact"
283
- >
284
- ${unsafeSVG(doubleChevron)}
285
- </button>
286
- <button
287
- @click=${this.previousMonth}
288
- @keydown="${this.handleButtonKeyDown}"
289
- aria-label="Previous month"
290
- class="compact"
291
- >
292
- ${unsafeSVG(chevron)}
293
- </button>
294
- <h2>${monthYear}</h2>
295
- <button
296
- @click=${this.nextMonth}
297
- @keydown="${this.handleButtonKeyDown}"
298
- aria-label="Next month"
299
- class="compact right"
300
- >
301
- ${unsafeSVG(chevron)}
302
- </button>
303
- <button
304
- @click=${this.nextYear}
305
- @keydown=${this.handleButtonKeyDown}
306
- aria-label="Next year"
307
- class="compact right"
308
- >
309
- ${unsafeSVG(doubleChevron)}
310
- </button>
311
- </div>
307
+ ${this.displayOnly
308
+ ? nothing
309
+ : html `<div class="calendar-header">
310
+ <button
311
+ @click=${this.previousYear}
312
+ @keydown=${this.handleButtonKeyDown}
313
+ aria-label="Previous year"
314
+ class="compact"
315
+ >
316
+ ${unsafeSVG(doubleChevron)}
317
+ </button>
318
+ <button
319
+ @click=${this.previousMonth}
320
+ @keydown="${this.handleButtonKeyDown}"
321
+ aria-label="Previous month"
322
+ class="compact"
323
+ >
324
+ ${unsafeSVG(chevron)}
325
+ </button>
326
+ <h2>${monthYear}</h2>
327
+ <button
328
+ @click=${this.nextMonth}
329
+ @keydown="${this.handleButtonKeyDown}"
330
+ aria-label="Next month"
331
+ class="compact right"
332
+ >
333
+ ${unsafeSVG(chevron)}
334
+ </button>
335
+ <button
336
+ @click=${this.nextYear}
337
+ @keydown=${this.handleButtonKeyDown}
338
+ aria-label="Next year"
339
+ class="compact right"
340
+ >
341
+ ${unsafeSVG(doubleChevron)}
342
+ </button>
343
+ </div>`}
312
344
  <div class="calendar-grid">
313
345
  <table
314
346
  role="grid"
@@ -332,15 +364,15 @@ export class Calendar extends LitElement {
332
364
  return html ` <td
333
365
  class="${classMap({
334
366
  day: true,
335
- 'in-range': this.isInRange(day),
336
- 'start-date': this.isStartDate(day),
337
- 'end-date': this.isEndDate(day),
367
+ 'in-range': this.isInRange(day) || this.isHighlightedInRange(day),
368
+ 'start-date': this.isStartDate(day) || this.isHighlightedStart(day),
369
+ 'end-date': this.isEndDate(day) || this.isHighlightedEnd(day),
338
370
  })}"
339
371
  @click=${() => this.handleDayClick(day)}
340
372
  role="gridcell"
341
373
  data-date="${day.toISODate()}"
342
374
  aria-label="${day.toLocaleString({ dateStyle: 'long' })}"
343
- aria-selected="${this.isSelected(day)}"
375
+ aria-selected="${this.isSelected(day) || this.isHighlighted(day)}"
344
376
  aria-disabled="${isDisabled}"
345
377
  tabindex="-1"
346
378
  @mouseenter="${this.onDayHover}"
@@ -353,32 +385,36 @@ export class Calendar extends LitElement {
353
385
  </table>
354
386
  </div>
355
387
 
356
- <div class="calendar-footer">
357
- <div class="actions" @keydown="${this.handleButtonKeyDown}">
358
- ${this.isRange()
359
- ? html `
360
- <button @click=${() => this.handleClearSelection()} data-theme="secondary" id="clear-selection">
361
- Clear selection
362
- </button>
363
- `
364
- : html ` <button @click=${() => this.handleDayClick(this.today)} data-theme="secondary">Today</button> `}
365
- </div>
366
- <div>
367
- <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>
368
- <summary>${unsafeSVG(keyboard)} Keyboard commands ${unsafeSVG(chevronDown)}</summary>
369
- <p>Arrow keys: navigate the calendar</p>
370
- <p>Enter or Space: select the date</p>
371
- <p>Escape: close the calendar without selecting a date</p>
372
- <p>Tab: navigate between the calendar and the presets</p>
373
- <p>Home: move to first day of week</p>
374
- <p>End: move to last day of week</p>
375
- <p>Page Up: move to previous month</p>
376
- <p>Page Down: move to next month</p>
377
- <p>Shift + Page Up: move to next year</p>
378
- <p>Shift + Page Down: move to previous year</p>
379
- </details>
380
- </div>
381
- </div>
388
+ ${this.displayOnly
389
+ ? nothing
390
+ : html `<div class="calendar-footer">
391
+ <div class="actions" @keydown="${this.handleButtonKeyDown}">
392
+ ${this.isRange()
393
+ ? html `
394
+ <button @click=${() => this.handleClearSelection()} data-theme="secondary" id="clear-selection">
395
+ Clear selection
396
+ </button>
397
+ `
398
+ : html `
399
+ <button @click=${() => this.handleDayClick(this.today)} data-theme="secondary">Today</button>
400
+ `}
401
+ </div>
402
+ <div>
403
+ <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>
404
+ <summary>${unsafeSVG(keyboard)} Keyboard commands ${unsafeSVG(chevronDown)}</summary>
405
+ <p>Arrow keys: navigate the calendar</p>
406
+ <p>Enter or Space: select the date</p>
407
+ <p>Escape: close the calendar without selecting a date</p>
408
+ <p>Tab: navigate between the calendar and the presets</p>
409
+ <p>Home: move to first day of week</p>
410
+ <p>End: move to last day of week</p>
411
+ <p>Page Up: move to previous month</p>
412
+ <p>Page Down: move to next month</p>
413
+ <p>Shift + Page Up: move to next year</p>
414
+ <p>Shift + Page Down: move to previous year</p>
415
+ </details>
416
+ </div>
417
+ </div>`}
382
418
  </div>
383
419
  `;
384
420
  }
@@ -419,6 +455,15 @@ __decorate([
419
455
  __decorate([
420
456
  property({ type: Number, attribute: 'min-days' })
421
457
  ], Calendar.prototype, "minDays", void 0);
458
+ __decorate([
459
+ property({ type: Boolean, reflect: true, attribute: 'display-only' })
460
+ ], Calendar.prototype, "displayOnly", void 0);
461
+ __decorate([
462
+ property({ type: String })
463
+ ], Calendar.prototype, "month", void 0);
464
+ __decorate([
465
+ property({ attribute: false })
466
+ ], Calendar.prototype, "highlightedRanges", void 0);
422
467
  __decorate([
423
468
  query('.calendar-panel')
424
469
  ], Calendar.prototype, "calendarDiv", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"TtCalendar.js","sourceRoot":"","sources":["../../../src/TtCalendar.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, PropertyValues } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { unsafeSVG } from 'lit/directives/unsafe-svg.js';\nimport { DateTime, Interval } from 'luxon';\nimport { DateRange, DateRangeSelectionEvent, DateSelectionEvent } from './DateSelectionContext.js';\nimport { chevron, chevronDown, doubleChevron, keyboard } from '@triptease/icons';\nimport { styles } from './Styles.js';\nimport { dateTimeConverter } from './helpers.js';\n\ntype WeekdayList = [\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n];\n\ninterface CalendarWithRange {\n value?: DateRange;\n range: true;\n}\n\ninterface InternalDateRange {\n startDate?: DateTime;\n endDate?: DateTime;\n}\n\nexport class Calendar extends LitElement {\n static styles = styles;\n\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n // Start public properties\n\n @property({ type: String })\n public value?: string | DateRange;\n\n @property({ type: Boolean })\n public range = false;\n\n @property({ attribute: 'max-date', converter: dateTimeConverter })\n public maxDate?: DateTime;\n\n @property({ type: Number, attribute: 'max-days' })\n public maxDays?: number;\n\n @property({ attribute: 'min-date', converter: dateTimeConverter })\n public minDate?: DateTime;\n\n @property({ type: Number, attribute: 'min-days' })\n public minDays?: number;\n\n get internalRangeValue(): InternalDateRange {\n if (this.range && this.value) {\n const startDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : undefined;\n const endDate = (this.value as DateRange)?.endDate\n ? DateTime.fromISO((this.value as DateRange).endDate!)\n : undefined;\n return { startDate, endDate };\n }\n return { startDate: undefined, endDate: undefined };\n }\n\n getRange(): Interval {\n if (this.range && this.internalRangeValue.startDate && this.internalRangeValue.endDate) {\n return Interval.fromDateTimes(\n this.internalRangeValue.startDate,\n this.internalRangeValue.endDate.plus({ days: 1 })\n );\n }\n return Interval.invalid('Invalid range');\n }\n\n public updated(changedProperties: PropertyValues) {\n if (changedProperties.has('value') && this.value) {\n super.updateComplete.then(() => {\n if (!this.range) {\n const parsedDate = DateTime.fromISO(this.value as string);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = this.internalRangeValue?.startDate || this.today;\n }\n });\n }\n super.updated(changedProperties);\n }\n\n public toggleVisibility() {\n if (this.visible) {\n this.visible = false;\n } else {\n this.visible = true;\n this.updateComplete.then(() => {\n this.calendarDiv.focus();\n this.calendarDiv.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n });\n if (!this.range) {\n const parsedDate = DateTime.fromISO((this.value as string) ?? this.today);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : this.today;\n }\n }\n }\n\n // end public properties\n\n @query('.calendar-panel')\n private calendarDiv!: HTMLElement;\n\n @state()\n private focusedDate: DateTime = this.today;\n\n @state()\n private visible: boolean = false;\n\n private handleKeyDown(event: KeyboardEvent) {\n const currentDate = this.focusedDate;\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n this.focusDay(currentDate.minus({ day: 1 }));\n break;\n case 'ArrowRight':\n event.preventDefault();\n this.focusDay(currentDate.plus({ day: 1 }));\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusDay(currentDate.minus({ week: 1 }));\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.focusDay(currentDate.plus({ week: 1 }));\n break;\n case 'Home':\n event.preventDefault();\n // Move to first day of week\n this.focusDay(currentDate.startOf('week'));\n break;\n case 'End':\n event.preventDefault();\n // Move to last day of week\n this.focusDay(currentDate.endOf('week'));\n break;\n case 'PageUp':\n event.preventDefault();\n if (event.shiftKey) {\n // Previous year\n this.focusDay(currentDate.minus({ year: 1 }));\n } else {\n // Previous month\n this.focusDay(currentDate.minus({ month: 1 }));\n }\n break;\n case 'PageDown':\n event.preventDefault();\n if (event.shiftKey) {\n // Next year\n this.focusDay(currentDate.plus({ year: 1 }));\n } else {\n // Next month\n this.focusDay(currentDate.plus({ month: 1 }));\n }\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.handleDayClick(this.focusedDate);\n return;\n\n default:\n return;\n }\n\n event.preventDefault();\n }\n\n private focusDay(date: DateTime) {\n this.focusedDate = date;\n this.updateComplete.then(() => {\n const dayElement = <HTMLElement | undefined>this.shadowRoot?.querySelector(`.day[data-date=\"${date.toISO()}\"]`);\n if (dayElement) {\n dayElement.focus();\n }\n });\n }\n\n private newWeek = () => new Array(7).fill(null) as WeekdayList;\n\n private getDaysInMonth(date: DateTime): WeekdayList[] {\n const startOfMonth = date.startOf('month');\n const endOfMonth = date.endOf('month');\n\n const weeks: WeekdayList[] = [];\n let currentWeek: WeekdayList = this.newWeek();\n\n let currentDay = startOfMonth;\n\n while (currentDay <= endOfMonth) {\n // Get the day of week (0-6, Sunday=0, Saturday=6)\n const dayOfWeek = currentDay.weekday === 7 ? 0 : currentDay.weekday;\n\n currentWeek[dayOfWeek] = currentDay;\n\n const isWeekComplete = dayOfWeek === 6; // Saturday (last day of week)\n const isLastDayOfMonth = currentDay.hasSame(endOfMonth, 'day');\n\n if (isWeekComplete || isLastDayOfMonth) {\n weeks.push(currentWeek);\n\n if (!isLastDayOfMonth) {\n currentWeek = this.newWeek();\n }\n }\n\n currentDay = currentDay.plus({ days: 1 });\n }\n\n return weeks;\n }\n\n private previousYear() {\n this.focusedDate = this.focusedDate.minus({ year: 1 });\n }\n\n private previousMonth() {\n this.focusedDate = this.focusedDate.minus({ month: 1 });\n }\n\n private nextMonth() {\n this.focusedDate = this.focusedDate.plus({ month: 1 });\n }\n\n private nextYear() {\n this.focusedDate = this.focusedDate.plus({ year: 1 });\n }\n\n private get today(): DateTime {\n return DateTime.local();\n }\n\n private handleDayClick(day: DateTime) {\n if (this.isRange()) {\n if (!this.value?.startDate || this.value?.endDate) {\n this.value = { startDate: day.toISODate()! };\n this.focusedDate = day;\n return;\n }\n\n if (!this.value.endDate) {\n this.value = { ...(this.value as DateRange), endDate: day.toISODate()! };\n this.focusedDate = day;\n this.dispatchEvent(new DateRangeSelectionEvent(this.value));\n return;\n }\n }\n\n if (day.isValid) {\n this.dispatchEvent(new DateSelectionEvent(day.toISODate()!));\n }\n }\n\n private handleButtonKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.stopPropagation();\n }\n };\n\n private getWeekdayLabels(): string[] {\n const monday = DateTime.fromISO('2024-06-02T00:00:00Z').startOf('week'); //Weeks start on Monday in Luxon https://moment.github.io/luxon/api-docs/index.html#datetimestartof\n const sunday = monday.plus({ days: 6 });\n return Array.from({ length: 7 }, (_, i) => {\n const date = sunday.plus({ days: i });\n return date.toLocaleString({ weekday: 'short' });\n });\n }\n\n private isSelected(date: DateTime): boolean {\n if (date.equals(this.focusedDate)) return true;\n\n if (this.isRange() && this.internalRangeValue.startDate) {\n if (!this.internalRangeValue.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate.plus({ days: 1 }));\n return range.contains(date);\n }\n\n const range = this.getRange();\n return range.contains(date);\n }\n\n return false;\n }\n\n private isInRange(date: DateTime): boolean {\n if (!this.isRange() || !this.internalRangeValue?.startDate) {\n return false;\n }\n\n if (!this.internalRangeValue?.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate);\n return range.contains(date) && !this.isStartDate(date) && !date.equals(this.focusedDate);\n }\n\n const range = this.getRange();\n return range.contains(date) && !this.isStartDate(date) && !this.isEndDate(date);\n }\n\n private isRange(): this is CalendarWithRange {\n return this.range;\n }\n\n private get isSelectingRange(): boolean {\n return Boolean(this.isRange() && this.value?.startDate && !this.value?.endDate);\n }\n\n private onDayHover = (event: MouseEvent) => {\n const day = (event.target as HTMLElement).dataset.date;\n if (!day) return;\n\n this.focusedDate = DateTime.fromISO(day);\n };\n\n private isStartDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.startDate && this.internalRangeValue.startDate.equals(date));\n\n private isEndDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.endDate && this.internalRangeValue.endDate.equals(date));\n\n private handleClearSelection = () => {\n this.value = { startDate: undefined, endDate: undefined };\n this.dispatchEvent(new DateRangeSelectionEvent({ startDate: undefined, endDate: undefined }));\n };\n\n private handleToggle(e: Event) {\n const details = e.target as HTMLDetailsElement;\n if (details.open) {\n details.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n }\n }\n\n render() {\n const weeks = this.getDaysInMonth(this.focusedDate);\n const monthYear = this.focusedDate.toLocaleString({\n month: 'long',\n year: 'numeric',\n });\n\n return html`\n <div class=\"calendar-panel\" @keydown=${this.handleKeyDown} role=\"application\" aria-label=\"${monthYear}\">\n <div class=\"calendar-header\">\n <button\n @click=${this.previousYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Previous year\"\n class=\"compact\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n <button\n @click=${this.previousMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Previous month\"\n class=\"compact\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <h2>${monthYear}</h2>\n <button\n @click=${this.nextMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Next month\"\n class=\"compact right\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <button\n @click=${this.nextYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Next year\"\n class=\"compact right\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n </div>\n <div class=\"calendar-grid\">\n <table\n role=\"grid\"\n aria-labelledby=\"month-year\"\n data-range=\"${this.range}\"\n class=\"${this.isSelectingRange ? 'selecting' : ''}\"\n >\n <thead>\n <tr>\n ${this.getWeekdayLabels().map((label) => html` <th>${label}</th>`)}\n </tr>\n </thead>\n\n <tbody>\n ${weeks.map(\n (week) =>\n html` <tr>\n ${week.map((day) => {\n if (!day) {\n return html` <td></td>`;\n }\n\n const isDisabled = this.dayIsDisabled(day);\n\n return html` <td\n class=\"${classMap({\n day: true,\n 'in-range': this.isInRange(day),\n 'start-date': this.isStartDate(day),\n 'end-date': this.isEndDate(day),\n })}\"\n @click=${() => this.handleDayClick(day)}\n role=\"gridcell\"\n data-date=\"${day.toISODate()}\"\n aria-label=\"${day.toLocaleString({ dateStyle: 'long' })}\"\n aria-selected=\"${this.isSelected(day)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"-1\"\n @mouseenter=\"${this.onDayHover}\"\n >\n ${day.day}\n </td>`;\n })}\n </tr>`\n )}\n </tbody>\n </table>\n </div>\n\n <div class=\"calendar-footer\">\n <div class=\"actions\" @keydown=\"${this.handleButtonKeyDown}\">\n ${this.isRange()\n ? html`\n <button @click=${() => this.handleClearSelection()} data-theme=\"secondary\" id=\"clear-selection\">\n Clear selection\n </button>\n `\n : html` <button @click=${() => this.handleDayClick(this.today)} data-theme=\"secondary\">Today</button> `}\n </div>\n <div>\n <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>\n <summary>${unsafeSVG(keyboard)} Keyboard commands ${unsafeSVG(chevronDown)}</summary>\n <p>Arrow keys: navigate the calendar</p>\n <p>Enter or Space: select the date</p>\n <p>Escape: close the calendar without selecting a date</p>\n <p>Tab: navigate between the calendar and the presets</p>\n <p>Home: move to first day of week</p>\n <p>End: move to last day of week</p>\n <p>Page Up: move to previous month</p>\n <p>Page Down: move to next month</p>\n <p>Shift + Page Up: move to next year</p>\n <p>Shift + Page Down: move to previous year</p>\n </details>\n </div>\n </div>\n </div>\n `;\n }\n\n private dayIsDisabled(day: DateTime) {\n if (this.maxDate && day > this.maxDate) return true;\n\n if (this.minDate && day < this.minDate) return true;\n\n if (this.range && this.isSelectingRange && this.internalRangeValue?.startDate) {\n if (day < this.internalRangeValue.startDate) return true;\n\n if (this.maxDays && day > this.internalRangeValue.startDate.plus({ days: this.maxDays })) return true;\n }\n\n return false;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'tt-calendar': Calendar;\n }\n}\n"]}
1
+ {"version":3,"file":"TtCalendar.js","sourceRoot":"","sources":["../../../src/TtCalendar.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing, PropertyValues } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { unsafeSVG } from 'lit/directives/unsafe-svg.js';\nimport { DateTime, Interval } from 'luxon';\nimport { DateRange, DateRangeSelectionEvent, DateSelectionEvent } from './DateSelectionContext.js';\nimport { chevron, chevronDown, doubleChevron, keyboard } from '@triptease/icons';\nimport { styles } from './Styles.js';\nimport { dateTimeConverter } from './helpers.js';\n\ntype WeekdayList = [\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n DateTime | null,\n];\n\ninterface CalendarWithRange {\n value?: DateRange;\n range: true;\n}\n\ninterface InternalDateRange {\n startDate?: DateTime;\n endDate?: DateTime;\n}\n\nexport class Calendar extends LitElement {\n static styles = styles;\n\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n // Start public properties\n\n @property({ type: String })\n public value?: string | DateRange;\n\n @property({ type: Boolean })\n public range = false;\n\n @property({ attribute: 'max-date', converter: dateTimeConverter })\n public maxDate?: DateTime;\n\n @property({ type: Number, attribute: 'max-days' })\n public maxDays?: number;\n\n @property({ attribute: 'min-date', converter: dateTimeConverter })\n public minDate?: DateTime;\n\n @property({ type: Number, attribute: 'min-days' })\n public minDays?: number;\n\n @property({ type: Boolean, reflect: true, attribute: 'display-only' })\n public displayOnly: boolean = false;\n\n @property({ type: String })\n public month?: string;\n\n @property({ attribute: false })\n public highlightedRanges: Required<DateRange>[] = [];\n\n private _parsedHighlights: { start: DateTime; end: DateTime }[] = [];\n\n get internalRangeValue(): InternalDateRange {\n if (this.range && this.value) {\n const startDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : undefined;\n const endDate = (this.value as DateRange)?.endDate\n ? DateTime.fromISO((this.value as DateRange).endDate!)\n : undefined;\n return { startDate, endDate };\n }\n return { startDate: undefined, endDate: undefined };\n }\n\n getRange(): Interval {\n if (this.range && this.internalRangeValue.startDate && this.internalRangeValue.endDate) {\n return Interval.fromDateTimes(\n this.internalRangeValue.startDate,\n this.internalRangeValue.endDate.plus({ days: 1 })\n );\n }\n return Interval.invalid('Invalid range');\n }\n\n protected override willUpdate(changedProperties: PropertyValues) {\n if (changedProperties.has('highlightedRanges')) {\n this._parsedHighlights = this.highlightedRanges.map((range) => ({\n start: DateTime.fromISO(range.startDate),\n end: DateTime.fromISO(range.endDate),\n }));\n }\n }\n\n public updated(changedProperties: PropertyValues) {\n if (changedProperties.has('value') && this.value) {\n super.updateComplete.then(() => {\n if (!this.range) {\n const parsedDate = DateTime.fromISO(this.value as string);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = this.internalRangeValue?.startDate || this.today;\n }\n });\n }\n super.updated(changedProperties);\n }\n\n public toggleVisibility() {\n if (this.visible) {\n this.visible = false;\n } else {\n this.visible = true;\n this.updateComplete.then(() => {\n this.calendarDiv.focus();\n this.calendarDiv.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n });\n if (!this.range) {\n const parsedDate = DateTime.fromISO((this.value as string) ?? this.today);\n this.focusedDate = parsedDate.isValid ? parsedDate : this.today;\n } else {\n this.focusedDate = (this.value as DateRange)?.startDate\n ? DateTime.fromISO((this.value as DateRange).startDate!)\n : this.today;\n }\n }\n }\n\n // end public properties\n\n @query('.calendar-panel')\n private calendarDiv!: HTMLElement;\n\n @state()\n private focusedDate: DateTime = this.today;\n\n @state()\n private visible: boolean = false;\n\n private handleKeyDown(event: KeyboardEvent) {\n if (this.displayOnly) return;\n const currentDate = this.focusedDate;\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n this.focusDay(currentDate.minus({ day: 1 }));\n break;\n case 'ArrowRight':\n event.preventDefault();\n this.focusDay(currentDate.plus({ day: 1 }));\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusDay(currentDate.minus({ week: 1 }));\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.focusDay(currentDate.plus({ week: 1 }));\n break;\n case 'Home':\n event.preventDefault();\n // Move to first day of week\n this.focusDay(currentDate.startOf('week'));\n break;\n case 'End':\n event.preventDefault();\n // Move to last day of week\n this.focusDay(currentDate.endOf('week'));\n break;\n case 'PageUp':\n event.preventDefault();\n if (event.shiftKey) {\n // Previous year\n this.focusDay(currentDate.minus({ year: 1 }));\n } else {\n // Previous month\n this.focusDay(currentDate.minus({ month: 1 }));\n }\n break;\n case 'PageDown':\n event.preventDefault();\n if (event.shiftKey) {\n // Next year\n this.focusDay(currentDate.plus({ year: 1 }));\n } else {\n // Next month\n this.focusDay(currentDate.plus({ month: 1 }));\n }\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.handleDayClick(this.focusedDate);\n return;\n\n default:\n return;\n }\n\n event.preventDefault();\n }\n\n public focusDay(date: DateTime) {\n this.focusedDate = date;\n this.updateComplete.then(() => {\n const dayElement = <HTMLElement | undefined>(\n this.shadowRoot?.querySelector(`.day[data-date=\"${date.toISODate()}\"]`)\n );\n if (dayElement) {\n dayElement.focus();\n }\n });\n }\n\n private newWeek = () => new Array(7).fill(null) as WeekdayList;\n\n private getDaysInMonth(date: DateTime): WeekdayList[] {\n const startOfMonth = date.startOf('month');\n const endOfMonth = date.endOf('month');\n\n const weeks: WeekdayList[] = [];\n let currentWeek: WeekdayList = this.newWeek();\n\n let currentDay = startOfMonth;\n\n while (currentDay <= endOfMonth) {\n // Get the day of week (0-6, Sunday=0, Saturday=6)\n const dayOfWeek = currentDay.weekday === 7 ? 0 : currentDay.weekday;\n\n currentWeek[dayOfWeek] = currentDay;\n\n const isWeekComplete = dayOfWeek === 6; // Saturday (last day of week)\n const isLastDayOfMonth = currentDay.hasSame(endOfMonth, 'day');\n\n if (isWeekComplete || isLastDayOfMonth) {\n weeks.push(currentWeek);\n\n if (!isLastDayOfMonth) {\n currentWeek = this.newWeek();\n }\n }\n\n currentDay = currentDay.plus({ days: 1 });\n }\n\n return weeks;\n }\n\n private previousYear() {\n this.focusedDate = this.focusedDate.minus({ year: 1 });\n }\n\n private previousMonth() {\n this.focusedDate = this.focusedDate.minus({ month: 1 });\n }\n\n private nextMonth() {\n this.focusedDate = this.focusedDate.plus({ month: 1 });\n }\n\n private nextYear() {\n this.focusedDate = this.focusedDate.plus({ year: 1 });\n }\n\n private get today(): DateTime {\n return DateTime.local();\n }\n\n private handleDayClick(day: DateTime) {\n if (this.displayOnly) return;\n if (this.isRange()) {\n if (!this.value?.startDate || this.value?.endDate) {\n this.value = { startDate: day.toISODate()! };\n this.focusedDate = day;\n return;\n }\n\n if (!this.value.endDate) {\n this.value = { ...(this.value as DateRange), endDate: day.toISODate()! };\n this.focusedDate = day;\n this.dispatchEvent(new DateRangeSelectionEvent(this.value));\n return;\n }\n }\n\n if (day.isValid) {\n this.dispatchEvent(new DateSelectionEvent(day.toISODate()!));\n }\n }\n\n private handleButtonKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.stopPropagation();\n }\n };\n\n private getWeekdayLabels(): string[] {\n const monday = DateTime.fromISO('2024-06-02T00:00:00Z').startOf('week'); //Weeks start on Monday in Luxon https://moment.github.io/luxon/api-docs/index.html#datetimestartof\n const sunday = monday.plus({ days: 6 });\n return Array.from({ length: 7 }, (_, i) => {\n const date = sunday.plus({ days: i });\n return date.toLocaleString({ weekday: 'short' });\n });\n }\n\n private isSelected(date: DateTime): boolean {\n if (date.equals(this.focusedDate)) return true;\n\n if (this.isRange() && this.internalRangeValue.startDate) {\n if (!this.internalRangeValue.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate.plus({ days: 1 }));\n return range.contains(date);\n }\n\n const range = this.getRange();\n return range.contains(date);\n }\n\n return false;\n }\n\n private isInRange(date: DateTime): boolean {\n if (!this.isRange() || !this.internalRangeValue?.startDate) {\n return false;\n }\n\n if (!this.internalRangeValue?.endDate) {\n const range = Interval.fromDateTimes(this.internalRangeValue.startDate, this.focusedDate);\n return range.contains(date) && !this.isStartDate(date) && !date.equals(this.focusedDate);\n }\n\n const range = this.getRange();\n return range.contains(date) && !this.isStartDate(date) && !this.isEndDate(date);\n }\n\n private isRange(): this is CalendarWithRange {\n return this.range;\n }\n\n private get isSelectingRange(): boolean {\n return Boolean(this.isRange() && this.value?.startDate && !this.value?.endDate);\n }\n\n private onDayHover = (event: MouseEvent) => {\n if (this.displayOnly) return;\n const day = (event.target as HTMLElement).dataset.date;\n if (!day) return;\n\n this.focusedDate = DateTime.fromISO(day);\n };\n\n private isStartDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.startDate && this.internalRangeValue.startDate.equals(date));\n\n private isEndDate = (date: DateTime): boolean =>\n Boolean(this.isRange() && this.internalRangeValue?.endDate && this.internalRangeValue.endDate.equals(date));\n\n private handleClearSelection = () => {\n this.value = { startDate: undefined, endDate: undefined };\n this.dispatchEvent(new DateRangeSelectionEvent({ startDate: undefined, endDate: undefined }));\n };\n\n private isHighlighted(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date >= start && date <= end);\n }\n\n private isHighlightedStart(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date.equals(start) && !start.equals(end));\n }\n\n private isHighlightedEnd(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date.equals(end) && !start.equals(end));\n }\n\n private isHighlightedInRange(date: DateTime): boolean {\n return this._parsedHighlights.some(({ start, end }) => date > start && date < end);\n }\n\n private handleToggle(e: Event) {\n const details = e.target as HTMLDetailsElement;\n if (details.open) {\n details.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n }\n }\n\n render() {\n const displayDate = this.month ? DateTime.fromISO(this.month + '-01') : this.focusedDate;\n const weeks = this.getDaysInMonth(displayDate);\n const monthYear = displayDate.toLocaleString({\n month: 'long',\n year: 'numeric',\n });\n\n return html`\n <div class=\"calendar-panel\" @keydown=${this.handleKeyDown} role=\"application\" aria-label=\"${monthYear}\">\n ${this.displayOnly\n ? nothing\n : html`<div class=\"calendar-header\">\n <button\n @click=${this.previousYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Previous year\"\n class=\"compact\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n <button\n @click=${this.previousMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Previous month\"\n class=\"compact\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <h2>${monthYear}</h2>\n <button\n @click=${this.nextMonth}\n @keydown=\"${this.handleButtonKeyDown}\"\n aria-label=\"Next month\"\n class=\"compact right\"\n >\n ${unsafeSVG(chevron)}\n </button>\n <button\n @click=${this.nextYear}\n @keydown=${this.handleButtonKeyDown}\n aria-label=\"Next year\"\n class=\"compact right\"\n >\n ${unsafeSVG(doubleChevron)}\n </button>\n </div>`}\n <div class=\"calendar-grid\">\n <table\n role=\"grid\"\n aria-labelledby=\"month-year\"\n data-range=\"${this.range}\"\n class=\"${this.isSelectingRange ? 'selecting' : ''}\"\n >\n <thead>\n <tr>\n ${this.getWeekdayLabels().map((label) => html` <th>${label}</th>`)}\n </tr>\n </thead>\n\n <tbody>\n ${weeks.map(\n (week) =>\n html` <tr>\n ${week.map((day) => {\n if (!day) {\n return html` <td></td>`;\n }\n\n const isDisabled = this.dayIsDisabled(day);\n\n return html` <td\n class=\"${classMap({\n day: true,\n 'in-range': this.isInRange(day) || this.isHighlightedInRange(day),\n 'start-date': this.isStartDate(day) || this.isHighlightedStart(day),\n 'end-date': this.isEndDate(day) || this.isHighlightedEnd(day),\n })}\"\n @click=${() => this.handleDayClick(day)}\n role=\"gridcell\"\n data-date=\"${day.toISODate()}\"\n aria-label=\"${day.toLocaleString({ dateStyle: 'long' })}\"\n aria-selected=\"${this.isSelected(day) || this.isHighlighted(day)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"-1\"\n @mouseenter=\"${this.onDayHover}\"\n >\n ${day.day}\n </td>`;\n })}\n </tr>`\n )}\n </tbody>\n </table>\n </div>\n\n ${this.displayOnly\n ? nothing\n : html`<div class=\"calendar-footer\">\n <div class=\"actions\" @keydown=\"${this.handleButtonKeyDown}\">\n ${this.isRange()\n ? html`\n <button @click=${() => this.handleClearSelection()} data-theme=\"secondary\" id=\"clear-selection\">\n Clear selection\n </button>\n `\n : html`\n <button @click=${() => this.handleDayClick(this.today)} data-theme=\"secondary\">Today</button>\n `}\n </div>\n <div>\n <details @keydown=${this.handleButtonKeyDown} @toggle=${this.handleToggle}>\n <summary>${unsafeSVG(keyboard)} Keyboard commands ${unsafeSVG(chevronDown)}</summary>\n <p>Arrow keys: navigate the calendar</p>\n <p>Enter or Space: select the date</p>\n <p>Escape: close the calendar without selecting a date</p>\n <p>Tab: navigate between the calendar and the presets</p>\n <p>Home: move to first day of week</p>\n <p>End: move to last day of week</p>\n <p>Page Up: move to previous month</p>\n <p>Page Down: move to next month</p>\n <p>Shift + Page Up: move to next year</p>\n <p>Shift + Page Down: move to previous year</p>\n </details>\n </div>\n </div>`}\n </div>\n `;\n }\n\n private dayIsDisabled(day: DateTime) {\n if (this.maxDate && day > this.maxDate) return true;\n\n if (this.minDate && day < this.minDate) return true;\n\n if (this.range && this.isSelectingRange && this.internalRangeValue?.startDate) {\n if (day < this.internalRangeValue.startDate) return true;\n\n if (this.maxDays && day > this.internalRangeValue.startDate.plus({ days: this.maxDays })) return true;\n }\n\n return false;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'tt-calendar': Calendar;\n }\n}\n"]}
@@ -175,6 +175,68 @@ describe('Calendar', () => {
175
175
  expect(detail.endDate).to.be.undefined;
176
176
  });
177
177
  });
178
+ describe('display-only mode', () => {
179
+ it('does not render navigation controls when display-only', async () => {
180
+ const el = await fixture(html `<tt-calendar display-only></tt-calendar>`);
181
+ const buttons = el.shadowRoot.querySelectorAll('.calendar-header button');
182
+ expect(buttons.length).to.equal(0);
183
+ });
184
+ it('does not emit date-selection event on click when display-only', async () => {
185
+ const el = await fixture(html `<tt-calendar display-only></tt-calendar>`);
186
+ let eventFired = false;
187
+ el.addEventListener('date-selection', () => {
188
+ eventFired = true;
189
+ });
190
+ const day = el.shadowRoot.querySelector('.day:not([aria-disabled="true"])');
191
+ day?.click();
192
+ await el.updateComplete;
193
+ expect(eventFired).to.be.false;
194
+ });
195
+ it('does not process keyboard events when display-only', async () => {
196
+ const el = await fixture(html `<tt-calendar display-only></tt-calendar>`);
197
+ const initialFocusedDate = el.focusedDate.toISODate();
198
+ const panel = el.shadowRoot.querySelector('.calendar-panel');
199
+ panel.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
200
+ await el.updateComplete;
201
+ expect(el.focusedDate.toISODate()).to.equal(initialFocusedDate);
202
+ });
203
+ });
204
+ describe('month property', () => {
205
+ it('displays the specified month when month is set', async () => {
206
+ const el = await fixture(html `<tt-calendar month="2026-06"></tt-calendar>`);
207
+ const header = el.shadowRoot.querySelector('h2');
208
+ expect(header.textContent).to.include('June');
209
+ expect(header.textContent).to.include('2026');
210
+ });
211
+ });
212
+ describe('highlighted-ranges', () => {
213
+ it('applies aria-selected to dates within highlighted ranges', async () => {
214
+ const el = await fixture(html `<tt-calendar month="2026-03"></tt-calendar>`);
215
+ el.highlightedRanges = [{ startDate: '2026-03-05', endDate: '2026-03-05' }];
216
+ await el.updateComplete;
217
+ const day5 = el.shadowRoot.querySelector('.day[data-date="2026-03-05"]');
218
+ expect(day5?.getAttribute('aria-selected')).to.equal('true');
219
+ });
220
+ it('applies in-range class for multi-day ranges', async () => {
221
+ const el = await fixture(html `<tt-calendar month="2026-03"></tt-calendar>`);
222
+ el.highlightedRanges = [{ startDate: '2026-03-10', endDate: '2026-03-15' }];
223
+ await el.updateComplete;
224
+ const day10 = el.shadowRoot.querySelector('.day[data-date="2026-03-10"]');
225
+ const day12 = el.shadowRoot.querySelector('.day[data-date="2026-03-12"]');
226
+ const day15 = el.shadowRoot.querySelector('.day[data-date="2026-03-15"]');
227
+ expect(day10?.classList.contains('start-date')).to.be.true;
228
+ expect(day12?.classList.contains('in-range')).to.be.true;
229
+ expect(day15?.classList.contains('end-date')).to.be.true;
230
+ });
231
+ it('does not apply in-range for single-date highlights', async () => {
232
+ const el = await fixture(html `<tt-calendar month="2026-03"></tt-calendar>`);
233
+ el.highlightedRanges = [{ startDate: '2026-03-05', endDate: '2026-03-05' }];
234
+ await el.updateComplete;
235
+ const day5 = el.shadowRoot.querySelector('.day[data-date="2026-03-05"]');
236
+ expect(day5?.classList.contains('in-range')).to.be.false;
237
+ expect(day5?.classList.contains('start-date')).to.be.false;
238
+ });
239
+ });
178
240
  describe('a11y', () => {
179
241
  it('should have proper ARIA attributes', async () => {
180
242
  const el = await fixture(html ` <tt-calendar></tt-calendar>`);
@@ -1 +1 @@
1
- {"version":3,"file":"tt-calendar.test.js","sourceRoot":"","sources":["../../../test/tt-calendar.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { elementUpdated, expect, fixture, html, oneEvent } from '@open-wc/testing';\nimport { DateTime, Settings } from 'luxon';\nimport '../src/tt-calendar.js'; // This handles the registration\nimport { Calendar } from '../src/TtCalendar.js';\n\ndescribe('Calendar', () => {\n describe('initialization', () => {\n const originalNow = DateTime.now().toMillis();\n\n afterEach(() => {\n Settings.defaultZone = 'system';\n Settings.now = () => originalNow;\n });\n\n it('should render with default props', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n expect(el).to.exist;\n expect(el.range).to.be.false;\n expect(el.value).to.be.undefined;\n });\n\n ['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {\n it(`should render the correct days of the week in ${timezone} timezone`, async () => {\n Settings.defaultZone = timezone;\n const now = DateTime.local(2025, 6, 4, 22, 0, 0).toMillis();\n Settings.now = () => now;\n const today = DateTime.now().toISO()!;\n const el = await fixture<Calendar>(html` <tt-calendar value=\"${today}\"></tt-calendar>`);\n\n const sunday = DateTime.fromISO(today).startOf('week').plus({ days: 6 }).toFormat('ccc');\n\n const headers = el.shadowRoot!.querySelectorAll('th');\n expect(headers[0].textContent?.trim()).to.equal(sunday);\n\n const dayRows = el.shadowRoot!.querySelectorAll('tr');\n const secondRowOfDays = dayRows[2].querySelectorAll('td');\n\n expect(secondRowOfDays[0].textContent?.trim()).to.equal('8');\n });\n });\n });\n\n describe('visibility', () => {\n xit('should toggle visibility when calling toggleVisibility', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n\n expect(el).to.be.instanceOf(Calendar);\n\n el.toggleVisibility();\n await elementUpdated(el);\n\n await expect(el.shadowRoot!.querySelector('[part=\"dialog\"]')?.getAttribute('inert')).not.to.exist;\n\n el.toggleVisibility();\n await elementUpdated(el);\n await expect(el.shadowRoot!.querySelector('[part=\"dialog\"]')?.getAttribute('inert')).to.exist;\n });\n\n xit('should close on outside click', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const focusOutEvent = new FocusEvent('focusout', {\n relatedTarget: document.body,\n });\n el.shadowRoot!.querySelector('[part=\"calendar\"]')?.dispatchEvent(focusOutEvent);\n await elementUpdated(el);\n\n await expect(el.shadowRoot!.querySelector('[part=\"calendar\"]')?.getAttribute('inert')).to.exist;\n });\n\n xit('should focus calendar div when opened', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n el.toggleVisibility();\n\n await elementUpdated(el);\n\n const calendar = el.shadowRoot!.querySelector('[part=\"calendar\"]');\n expect(calendar).to.exist;\n expect(el.shadowRoot!.activeElement === calendar).to.be.true;\n });\n });\n\n ['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {\n describe(`single date selection in ${timezone} timezone`, () => {\n const originalNow = DateTime.now().toMillis();\n\n afterEach(() => {\n Settings.defaultZone = 'system';\n Settings.now = () => originalNow;\n });\n\n const selectDay = (day: string, el: HTMLElement): void => {\n if (!el.shadowRoot) {\n throw new Error('Shadow root not found');\n }\n\n const allCells = el.shadowRoot.querySelectorAll('td[role=\"gridcell\"]');\n const dayCell = Array.from(allCells).filter((cell) => cell.textContent?.trim() === day)[0] as HTMLElement;\n dayCell.click();\n };\n\n it('should emit date-selection event when selecting a date', async () => {\n Settings.defaultZone = timezone;\n const el = await fixture<Calendar>(html` <tt-calendar value=\"2025-01-09\"></tt-calendar>`);\n const listener = oneEvent(el, 'date-selection');\n await elementUpdated(el);\n selectDay('4', el);\n\n await elementUpdated(el);\n\n const { detail } = await listener;\n const actual = detail as Date;\n const expected = '2025-01-04';\n expect(actual).to.equal(expected);\n });\n });\n });\n ['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {\n describe('date range selection', () => {\n it(`should emit date-range-selection event when selecting range in ${timezone} timezone`, async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n const listener = oneEvent(el, 'date-range-selection');\n\n el.toggleVisibility();\n await elementUpdated(el);\n\n const days = el.shadowRoot!.querySelectorAll('.day');\n const firstDay = days[0] as HTMLElement;\n const lastDay = days[5] as HTMLElement;\n\n firstDay.click();\n lastDay.click();\n\n await elementUpdated(el);\n\n const { detail } = await listener;\n\n expect(detail).to.have.property('startDate');\n expect(detail).to.have.property('endDate');\n\n const { startDate, endDate } = detail;\n const expectedStartDate = '2025-07-01';\n const expectedEndDate = '2025-07-06';\n await expect(startDate).to.equal(expectedStartDate);\n await expect(endDate).to.equal(expectedEndDate);\n });\n\n it('should disable dates before the start of the range when selecting', async () => {\n Settings.defaultZone = timezone;\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const days = el.shadowRoot!.querySelectorAll('.day');\n (days[5] as HTMLElement).click();\n await elementUpdated(el);\n\n await expect(days[4].getAttribute('aria-disabled')).to.equal('true');\n });\n\n it('should disable dates before min-date', async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar min-date=\"2025-07-05\"></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const disabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-04\"]') as HTMLElement;\n const enabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-05\"]') as HTMLElement;\n\n await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');\n await expect(enabledDate.getAttribute('aria-disabled')).to.equal('false');\n });\n\n it('should disable dates before max-date', async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar max-date=\"2025-07-05\"></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const disabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-06\"]') as HTMLElement;\n const enabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-05\"]') as HTMLElement;\n\n await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');\n await expect(enabledDate.getAttribute('aria-disabled')).to.equal('false');\n });\n\n it('should disable dates after selected date + max days', async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar range max-days=\"1\"></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const dateStart = el.shadowRoot!.querySelector('[data-date=\"2025-07-06\"]') as HTMLElement;\n dateStart.click();\n await elementUpdated(el);\n\n const disabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-08\"]') as HTMLElement;\n\n await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');\n });\n });\n });\n\n describe('clear selection', () => {\n it('should clear selection', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n const listener = oneEvent(el, 'date-range-selection');\n\n el.toggleVisibility();\n await elementUpdated(el);\n\n const clearButton = el.shadowRoot!.querySelector('button#clear-selection') as HTMLElement;\n expect(clearButton).to.exist;\n clearButton.click();\n\n const { detail } = await listener;\n expect(detail.startDate).to.be.undefined;\n expect(detail.endDate).to.be.undefined;\n });\n });\n\n describe('a11y', () => {\n it('should have proper ARIA attributes', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const days = el.shadowRoot!.querySelectorAll('.day');\n days.forEach((day) => {\n expect(day.getAttribute('role')).to.equal('gridcell');\n expect(day.getAttribute('aria-label')).to.exist;\n });\n });\n\n it('should have proper ARIA selected states', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const firstDay = el.shadowRoot!.querySelector('.day') as HTMLElement;\n firstDay.click();\n\n await elementUpdated(el);\n\n await expect(firstDay?.getAttribute('aria-selected')).to.equal('true');\n });\n });\n});\n"]}
1
+ {"version":3,"file":"tt-calendar.test.js","sourceRoot":"","sources":["../../../test/tt-calendar.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { elementUpdated, expect, fixture, html, oneEvent } from '@open-wc/testing';\nimport { DateTime, Settings } from 'luxon';\nimport '../src/tt-calendar.js'; // This handles the registration\nimport { Calendar } from '../src/TtCalendar.js';\n\ndescribe('Calendar', () => {\n describe('initialization', () => {\n const originalNow = DateTime.now().toMillis();\n\n afterEach(() => {\n Settings.defaultZone = 'system';\n Settings.now = () => originalNow;\n });\n\n it('should render with default props', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n expect(el).to.exist;\n expect(el.range).to.be.false;\n expect(el.value).to.be.undefined;\n });\n\n ['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {\n it(`should render the correct days of the week in ${timezone} timezone`, async () => {\n Settings.defaultZone = timezone;\n const now = DateTime.local(2025, 6, 4, 22, 0, 0).toMillis();\n Settings.now = () => now;\n const today = DateTime.now().toISO()!;\n const el = await fixture<Calendar>(html` <tt-calendar value=\"${today}\"></tt-calendar>`);\n\n const sunday = DateTime.fromISO(today).startOf('week').plus({ days: 6 }).toFormat('ccc');\n\n const headers = el.shadowRoot!.querySelectorAll('th');\n expect(headers[0].textContent?.trim()).to.equal(sunday);\n\n const dayRows = el.shadowRoot!.querySelectorAll('tr');\n const secondRowOfDays = dayRows[2].querySelectorAll('td');\n\n expect(secondRowOfDays[0].textContent?.trim()).to.equal('8');\n });\n });\n });\n\n describe('visibility', () => {\n xit('should toggle visibility when calling toggleVisibility', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n\n expect(el).to.be.instanceOf(Calendar);\n\n el.toggleVisibility();\n await elementUpdated(el);\n\n await expect(el.shadowRoot!.querySelector('[part=\"dialog\"]')?.getAttribute('inert')).not.to.exist;\n\n el.toggleVisibility();\n await elementUpdated(el);\n await expect(el.shadowRoot!.querySelector('[part=\"dialog\"]')?.getAttribute('inert')).to.exist;\n });\n\n xit('should close on outside click', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const focusOutEvent = new FocusEvent('focusout', {\n relatedTarget: document.body,\n });\n el.shadowRoot!.querySelector('[part=\"calendar\"]')?.dispatchEvent(focusOutEvent);\n await elementUpdated(el);\n\n await expect(el.shadowRoot!.querySelector('[part=\"calendar\"]')?.getAttribute('inert')).to.exist;\n });\n\n xit('should focus calendar div when opened', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n el.toggleVisibility();\n\n await elementUpdated(el);\n\n const calendar = el.shadowRoot!.querySelector('[part=\"calendar\"]');\n expect(calendar).to.exist;\n expect(el.shadowRoot!.activeElement === calendar).to.be.true;\n });\n });\n\n ['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {\n describe(`single date selection in ${timezone} timezone`, () => {\n const originalNow = DateTime.now().toMillis();\n\n afterEach(() => {\n Settings.defaultZone = 'system';\n Settings.now = () => originalNow;\n });\n\n const selectDay = (day: string, el: HTMLElement): void => {\n if (!el.shadowRoot) {\n throw new Error('Shadow root not found');\n }\n\n const allCells = el.shadowRoot.querySelectorAll('td[role=\"gridcell\"]');\n const dayCell = Array.from(allCells).filter((cell) => cell.textContent?.trim() === day)[0] as HTMLElement;\n dayCell.click();\n };\n\n it('should emit date-selection event when selecting a date', async () => {\n Settings.defaultZone = timezone;\n const el = await fixture<Calendar>(html` <tt-calendar value=\"2025-01-09\"></tt-calendar>`);\n const listener = oneEvent(el, 'date-selection');\n await elementUpdated(el);\n selectDay('4', el);\n\n await elementUpdated(el);\n\n const { detail } = await listener;\n const actual = detail as Date;\n const expected = '2025-01-04';\n expect(actual).to.equal(expected);\n });\n });\n });\n ['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {\n describe('date range selection', () => {\n it(`should emit date-range-selection event when selecting range in ${timezone} timezone`, async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n const listener = oneEvent(el, 'date-range-selection');\n\n el.toggleVisibility();\n await elementUpdated(el);\n\n const days = el.shadowRoot!.querySelectorAll('.day');\n const firstDay = days[0] as HTMLElement;\n const lastDay = days[5] as HTMLElement;\n\n firstDay.click();\n lastDay.click();\n\n await elementUpdated(el);\n\n const { detail } = await listener;\n\n expect(detail).to.have.property('startDate');\n expect(detail).to.have.property('endDate');\n\n const { startDate, endDate } = detail;\n const expectedStartDate = '2025-07-01';\n const expectedEndDate = '2025-07-06';\n await expect(startDate).to.equal(expectedStartDate);\n await expect(endDate).to.equal(expectedEndDate);\n });\n\n it('should disable dates before the start of the range when selecting', async () => {\n Settings.defaultZone = timezone;\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const days = el.shadowRoot!.querySelectorAll('.day');\n (days[5] as HTMLElement).click();\n await elementUpdated(el);\n\n await expect(days[4].getAttribute('aria-disabled')).to.equal('true');\n });\n\n it('should disable dates before min-date', async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar min-date=\"2025-07-05\"></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const disabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-04\"]') as HTMLElement;\n const enabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-05\"]') as HTMLElement;\n\n await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');\n await expect(enabledDate.getAttribute('aria-disabled')).to.equal('false');\n });\n\n it('should disable dates before max-date', async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar max-date=\"2025-07-05\"></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const disabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-06\"]') as HTMLElement;\n const enabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-05\"]') as HTMLElement;\n\n await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');\n await expect(enabledDate.getAttribute('aria-disabled')).to.equal('false');\n });\n\n it('should disable dates after selected date + max days', async () => {\n Settings.defaultZone = timezone;\n Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();\n const el = await fixture<Calendar>(html` <tt-calendar range max-days=\"1\"></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const dateStart = el.shadowRoot!.querySelector('[data-date=\"2025-07-06\"]') as HTMLElement;\n dateStart.click();\n await elementUpdated(el);\n\n const disabledDate = el.shadowRoot!.querySelector('[data-date=\"2025-07-08\"]') as HTMLElement;\n\n await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');\n });\n });\n });\n\n describe('clear selection', () => {\n it('should clear selection', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n const listener = oneEvent(el, 'date-range-selection');\n\n el.toggleVisibility();\n await elementUpdated(el);\n\n const clearButton = el.shadowRoot!.querySelector('button#clear-selection') as HTMLElement;\n expect(clearButton).to.exist;\n clearButton.click();\n\n const { detail } = await listener;\n expect(detail.startDate).to.be.undefined;\n expect(detail.endDate).to.be.undefined;\n });\n });\n\n describe('display-only mode', () => {\n it('does not render navigation controls when display-only', async () => {\n const el = await fixture<Calendar>(html`<tt-calendar display-only></tt-calendar>`);\n const buttons = el.shadowRoot!.querySelectorAll('.calendar-header button');\n expect(buttons.length).to.equal(0);\n });\n\n it('does not emit date-selection event on click when display-only', async () => {\n const el = await fixture<Calendar>(html`<tt-calendar display-only></tt-calendar>`);\n let eventFired = false;\n el.addEventListener('date-selection', () => {\n eventFired = true;\n });\n\n const day = el.shadowRoot!.querySelector('.day:not([aria-disabled=\"true\"])') as HTMLElement;\n day?.click();\n await el.updateComplete;\n\n expect(eventFired).to.be.false;\n });\n\n it('does not process keyboard events when display-only', async () => {\n const el = await fixture<Calendar>(html`<tt-calendar display-only></tt-calendar>`);\n const initialFocusedDate = (el as any).focusedDate.toISODate();\n\n const panel = el.shadowRoot!.querySelector('.calendar-panel') as HTMLElement;\n panel.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));\n await el.updateComplete;\n\n expect((el as any).focusedDate.toISODate()).to.equal(initialFocusedDate);\n });\n });\n\n describe('month property', () => {\n it('displays the specified month when month is set', async () => {\n const el = await fixture<Calendar>(html`<tt-calendar month=\"2026-06\"></tt-calendar>`);\n const header = el.shadowRoot!.querySelector('h2')!;\n expect(header.textContent).to.include('June');\n expect(header.textContent).to.include('2026');\n });\n });\n\n describe('highlighted-ranges', () => {\n it('applies aria-selected to dates within highlighted ranges', async () => {\n const el = await fixture<Calendar>(html`<tt-calendar month=\"2026-03\"></tt-calendar>`);\n el.highlightedRanges = [{ startDate: '2026-03-05', endDate: '2026-03-05' }];\n await el.updateComplete;\n\n const day5 = el.shadowRoot!.querySelector('.day[data-date=\"2026-03-05\"]');\n expect(day5?.getAttribute('aria-selected')).to.equal('true');\n });\n\n it('applies in-range class for multi-day ranges', async () => {\n const el = await fixture<Calendar>(html`<tt-calendar month=\"2026-03\"></tt-calendar>`);\n el.highlightedRanges = [{ startDate: '2026-03-10', endDate: '2026-03-15' }];\n await el.updateComplete;\n\n const day10 = el.shadowRoot!.querySelector('.day[data-date=\"2026-03-10\"]');\n const day12 = el.shadowRoot!.querySelector('.day[data-date=\"2026-03-12\"]');\n const day15 = el.shadowRoot!.querySelector('.day[data-date=\"2026-03-15\"]');\n\n expect(day10?.classList.contains('start-date')).to.be.true;\n expect(day12?.classList.contains('in-range')).to.be.true;\n expect(day15?.classList.contains('end-date')).to.be.true;\n });\n\n it('does not apply in-range for single-date highlights', async () => {\n const el = await fixture<Calendar>(html`<tt-calendar month=\"2026-03\"></tt-calendar>`);\n el.highlightedRanges = [{ startDate: '2026-03-05', endDate: '2026-03-05' }];\n await el.updateComplete;\n\n const day5 = el.shadowRoot!.querySelector('.day[data-date=\"2026-03-05\"]');\n expect(day5?.classList.contains('in-range')).to.be.false;\n expect(day5?.classList.contains('start-date')).to.be.false;\n });\n });\n\n describe('a11y', () => {\n it('should have proper ARIA attributes', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const days = el.shadowRoot!.querySelectorAll('.day');\n days.forEach((day) => {\n expect(day.getAttribute('role')).to.equal('gridcell');\n expect(day.getAttribute('aria-label')).to.exist;\n });\n });\n\n it('should have proper ARIA selected states', async () => {\n const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);\n el.toggleVisibility();\n await elementUpdated(el);\n\n const firstDay = el.shadowRoot!.querySelector('.day') as HTMLElement;\n firstDay.click();\n\n await elementUpdated(el);\n\n await expect(firstDay?.getAttribute('aria-selected')).to.equal('true');\n });\n });\n});\n"]}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent tt-calendar following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "@triptease",
6
- "version": "6.1.2",
6
+ "version": "6.2.0",
7
7
  "type": "module",
8
8
  "files": [
9
9
  "dist/esm",