@nanahoshi/mona-ui 0.19.0 → 0.20.1

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.
Files changed (41) hide show
  1. package/THIRD_PARTY_NOTICES.md +60 -0
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +46 -36
  3. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +120 -99
  4. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +109 -99
  5. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +19 -13
  6. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +27 -17
  7. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +37 -27
  8. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +5 -4
  9. package/fesm2022/nanahoshi-mona-ui-editor.mjs +3 -3
  10. package/fesm2022/nanahoshi-mona-ui-filter.mjs +1 -1
  11. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-cell.component-Bg7rckst.mjs → nanahoshi-mona-ui-grid-grid-footer-cell.component-DLqCAee3.mjs} +2 -2
  12. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-BSSpaCLL.mjs → nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-Bd2twji1.mjs} +2 -2
  13. package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-D9AwQFDV.mjs → nanahoshi-mona-ui-grid-grid-list.component-hakVMhqu.mjs} +5 -5
  14. package/fesm2022/{nanahoshi-mona-ui-grid-grid-toggle.component-Byb9iTes.mjs → nanahoshi-mona-ui-grid-grid-toggle.component-CtEs5t9x.mjs} +28 -17
  15. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-CBmdtrXm.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-DoAGYLzr.mjs} +5 -5
  16. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-DPmJmCap.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-BIK61ieq.mjs} +19 -10
  17. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  18. package/fesm2022/nanahoshi-mona-ui-i18n.mjs +3722 -16
  19. package/fesm2022/nanahoshi-mona-ui-list-view.mjs +2 -2
  20. package/fesm2022/nanahoshi-mona-ui-locales.mjs +4973 -0
  21. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +46 -38
  22. package/fesm2022/nanahoshi-mona-ui-pager.mjs +23 -13
  23. package/fesm2022/nanahoshi-mona-ui-sheet.mjs +1 -1
  24. package/fesm2022/nanahoshi-mona-ui-stepper.mjs +14 -5
  25. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +25 -16
  26. package/locales/package.json +4 -0
  27. package/package.json +5 -1
  28. package/types/nanahoshi-mona-ui-auto-complete.d.ts +19 -18
  29. package/types/nanahoshi-mona-ui-calendar.d.ts +25 -21
  30. package/types/nanahoshi-mona-ui-combo-box.d.ts +23 -22
  31. package/types/nanahoshi-mona-ui-date-picker.d.ts +7 -4
  32. package/types/nanahoshi-mona-ui-datetime-picker.d.ts +8 -5
  33. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +18 -17
  34. package/types/nanahoshi-mona-ui-dropdowns.d.ts +6 -4
  35. package/types/nanahoshi-mona-ui-grid.d.ts +12 -1
  36. package/types/nanahoshi-mona-ui-i18n.d.ts +49 -2
  37. package/types/nanahoshi-mona-ui-locales.d.ts +4889 -0
  38. package/types/nanahoshi-mona-ui-multi-select.d.ts +20 -19
  39. package/types/nanahoshi-mona-ui-pager.d.ts +1 -0
  40. package/types/nanahoshi-mona-ui-stepper.d.ts +2 -1
  41. package/types/nanahoshi-mona-ui-time-picker.d.ts +4 -2
@@ -11,7 +11,7 @@ import { themeRaisedBackdropClasses, createElementControlId, rxTimeout } from '@
11
11
  import { DateTime } from 'luxon';
12
12
  import { skip, fromEvent } from 'rxjs';
13
13
  import { twMerge } from 'tailwind-merge';
14
- import { MonaI18nService, injectComponentDirection, gregorianDateTime, formatGregorianDateToLocaleString, gregorianDateTimeFromObject } from '@nanahoshi/mona-ui/i18n';
14
+ import { MonaI18nService, injectComponentDirection, gregorianDateTime, formatGregorianDateToLocaleString, getLocaleFirstDayOfWeek, gregorianDateTimeFromObject, formatNumber } from '@nanahoshi/mona-ui/i18n';
15
15
  import { cva } from 'class-variance-authority';
16
16
 
17
17
  const CALENDAR_DEFAULT_MESSAGES = {
@@ -496,6 +496,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
496
496
  }]
497
497
  }], propDecorators: { month: [{ type: i0.Input, args: [{ isSignal: true, alias: "month", required: true }] }], monthName: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthName", required: true }] }], navigatedDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigatedDate", required: true }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: true }] }], selectedDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedDate", required: false }] }] } });
498
498
 
499
+ const FIRST_DAY_OF_WEEK_TO_ISO = {
500
+ monday: 1,
501
+ tuesday: 2,
502
+ wednesday: 3,
503
+ thursday: 4,
504
+ friday: 5,
505
+ saturday: 6,
506
+ sunday: 7
507
+ };
499
508
  class CalendarComponent {
500
509
  #calendarService;
501
510
  #destroyRef;
@@ -510,30 +519,16 @@ class CalendarComponent {
510
519
  this.#direction = injectComponentDirection();
511
520
  this.#hostElementRef = inject(ElementRef);
512
521
  this.#i18n = inject(MonaI18nService);
513
- this.messages = this.#i18n.componentMessages("calendar", CALENDAR_DEFAULT_MESSAGES);
514
522
  this.#monthDict = computed(() => {
515
523
  const day = this.navigatedDate();
516
524
  const firstDayOfMonth = gregorianDateTime(day, this.#i18n.localeId()).startOf("month");
517
525
  const lastDayOfMonth = gregorianDateTime(day, this.#i18n.localeId()).endOf("month");
518
- const firstDayOfWeek = this.firstDay() === "monday" ? 1 : 0;
519
- let firstDayOfCalendar;
520
- const monthStartWeekday = firstDayOfMonth.weekday;
521
- if (firstDayOfWeek === 0) {
522
- const daysToSubtract = monthStartWeekday === 7 ? 0 : monthStartWeekday;
523
- firstDayOfCalendar = firstDayOfMonth.minus({ days: daysToSubtract });
524
- }
525
- else {
526
- firstDayOfCalendar = firstDayOfMonth.startOf("week");
527
- }
528
- let lastDayOfCalendar;
529
- const monthEndWeekday = lastDayOfMonth.weekday;
530
- if (firstDayOfWeek === 0) {
531
- const daysToAdd = monthEndWeekday === 7 ? 6 : 6 - monthEndWeekday;
532
- lastDayOfCalendar = lastDayOfMonth.plus({ days: daysToAdd });
533
- }
534
- else {
535
- lastDayOfCalendar = lastDayOfMonth.endOf("week");
536
- }
526
+ const firstDayIso = FIRST_DAY_OF_WEEK_TO_ISO[this.effectiveFirstDay()];
527
+ const daysToSubtract = (firstDayOfMonth.weekday - firstDayIso + 7) % 7;
528
+ const firstDayOfCalendar = firstDayOfMonth.minus({ days: daysToSubtract });
529
+ const lastDayOfWeekIso = ((firstDayIso + 5) % 7) + 1;
530
+ const daysToAdd = (lastDayOfWeekIso - lastDayOfMonth.weekday + 7) % 7;
531
+ const lastDayOfCalendar = lastDayOfMonth.plus({ days: daysToAdd });
537
532
  const dictionary = new Dictionary();
538
533
  for (let i = firstDayOfCalendar; i <= lastDayOfCalendar; i = i.plus({ days: 1 })) {
539
534
  dictionary.add(i.toJSDate(), i.day);
@@ -613,13 +608,33 @@ class CalendarComponent {
613
608
  .toArray();
614
609
  }, /* @ts-ignore */
615
610
  ...(ngDevMode ? [{ debugName: "decadeYears" }] : /* istanbul ignore next */ []));
611
+ this.effectiveFirstDay = computed(() => {
612
+ return this.firstDay() ?? getLocaleFirstDayOfWeek(this.#i18n.localeId());
613
+ }, /* @ts-ignore */
614
+ ...(ngDevMode ? [{ debugName: "effectiveFirstDay" }] : /* istanbul ignore next */ []));
616
615
  this.gridId = createElementControlId();
617
616
  this.headerClass = computed(() => {
618
617
  return calendarHeaderThemeVariants({});
619
618
  }, /* @ts-ignore */
620
619
  ...(ngDevMode ? [{ debugName: "headerClass" }] : /* istanbul ignore next */ []));
620
+ this.headerMonthYear = computed(() => {
621
+ const locale = this.#i18n.localeId();
622
+ return formatGregorianDateToLocaleString(this.navigatedDate(), locale, {
623
+ year: "numeric",
624
+ month: "long"
625
+ });
626
+ }, /* @ts-ignore */
627
+ ...(ngDevMode ? [{ debugName: "headerMonthYear" }] : /* istanbul ignore next */ []));
628
+ this.headerYear = computed(() => {
629
+ const locale = this.#i18n.localeId();
630
+ return formatGregorianDateToLocaleString(this.navigatedDate(), locale, {
631
+ year: "numeric"
632
+ });
633
+ }, /* @ts-ignore */
634
+ ...(ngDevMode ? [{ debugName: "headerYear" }] : /* istanbul ignore next */ []));
621
635
  this.invalidState = computed(() => this.touched() && (this.invalid() || (this.required() && this.isEmptyValue())), /* @ts-ignore */
622
636
  ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
637
+ this.messages = this.#i18n.componentMessages("calendar", CALENDAR_DEFAULT_MESSAGES);
623
638
  this.monthBounds = computed(() => {
624
639
  const navigatedDate = this.navigatedDate();
625
640
  const firstDayOfMonth = gregorianDateTime(navigatedDate, this.#i18n.localeId()).startOf("month");
@@ -645,21 +660,6 @@ class CalendarComponent {
645
660
  return calendarMonthViewGridHeaderThemeVariants();
646
661
  }, /* @ts-ignore */
647
662
  ...(ngDevMode ? [{ debugName: "monthGridHeaderClass" }] : /* istanbul ignore next */ []));
648
- this.headerMonthYear = computed(() => {
649
- const locale = this.#i18n.localeId();
650
- return formatGregorianDateToLocaleString(this.navigatedDate(), locale, {
651
- year: "numeric",
652
- month: "long"
653
- });
654
- }, /* @ts-ignore */
655
- ...(ngDevMode ? [{ debugName: "headerMonthYear" }] : /* istanbul ignore next */ []));
656
- this.headerYear = computed(() => {
657
- const locale = this.#i18n.localeId();
658
- return formatGregorianDateToLocaleString(this.navigatedDate(), locale, {
659
- year: "numeric"
660
- });
661
- }, /* @ts-ignore */
662
- ...(ngDevMode ? [{ debugName: "headerYear" }] : /* istanbul ignore next */ []));
663
663
  this.months = computed(() => {
664
664
  const locale = this.#i18n.localeId();
665
665
  const names = range(1, 12)
@@ -686,6 +686,8 @@ class CalendarComponent {
686
686
  }
687
687
  }, /* @ts-ignore */
688
688
  ...(ngDevMode ? [{ debugName: "nextButtonLabel" }] : /* istanbul ignore next */ []));
689
+ this.pendingRangeStart = signal(null, /* @ts-ignore */
690
+ ...(ngDevMode ? [{ debugName: "pendingRangeStart" }] : /* istanbul ignore next */ []));
689
691
  this.prevButtonLabel = computed(() => {
690
692
  const view = this.calendarView();
691
693
  const messages = this.messages();
@@ -699,8 +701,6 @@ class CalendarComponent {
699
701
  }
700
702
  }, /* @ts-ignore */
701
703
  ...(ngDevMode ? [{ debugName: "prevButtonLabel" }] : /* istanbul ignore next */ []));
702
- this.pendingRangeStart = signal(null, /* @ts-ignore */
703
- ...(ngDevMode ? [{ debugName: "pendingRangeStart" }] : /* istanbul ignore next */ []));
704
704
  this.rangePreviewDate = signal(null, /* @ts-ignore */
705
705
  ...(ngDevMode ? [{ debugName: "rangePreviewDate" }] : /* istanbul ignore next */ []));
706
706
  this.rangePreviewDates = computed(() => {
@@ -760,19 +760,26 @@ class CalendarComponent {
760
760
  }, /* @ts-ignore */
761
761
  ...(ngDevMode ? [{ debugName: "viewSwitchButtonLabel" }] : /* istanbul ignore next */ []));
762
762
  this.weekdays = computed(() => {
763
- const firstDayOfWeek = this.firstDay();
763
+ const firstDayIso = FIRST_DAY_OF_WEEK_TO_ISO[this.effectiveFirstDay()];
764
764
  const locale = this.#i18n.localeId();
765
- // 2024-01-07 was a Sunday
765
+ // 2024-01-01 was a Monday (ISO 1)
766
766
  const days = range(0, 7)
767
767
  .select(i => {
768
- const dt = gregorianDateTimeFromObject({ year: 2024, month: 1, day: 7 + i }, locale);
768
+ const dt = gregorianDateTimeFromObject({ year: 2024, month: 1, day: 1 + i }, locale);
769
+ const short = dt.toFormat("ccc");
770
+ const full = dt.toFormat("cccc");
771
+ const narrow = dt.toFormat("ccccc");
772
+ const display = short.length > 4 || (short === full && short.length > 3) ? narrow : short;
769
773
  return {
770
- short: dt.toFormat("ccc"),
771
- full: dt.toFormat("cccc")
774
+ display,
775
+ short,
776
+ narrow,
777
+ full
772
778
  };
773
779
  })
774
780
  .toArray();
775
- return firstDayOfWeek === "monday" ? [...days.slice(1), days[0]] : days;
781
+ const startIndex = firstDayIso - 1;
782
+ return [...days.slice(startIndex), ...days.slice(0, startIndex)];
776
783
  }, /* @ts-ignore */
777
784
  ...(ngDevMode ? [{ debugName: "weekdays" }] : /* istanbul ignore next */ []));
778
785
  this.yearCellTemplate = contentChild(CalendarYearCellTemplateDirective, /* @ts-ignore */
@@ -793,10 +800,10 @@ class CalendarComponent {
793
800
  this.disabledDates = input(/* @ts-ignore */
794
801
  ...(ngDevMode ? [undefined, { debugName: "disabledDates" }] : /* istanbul ignore next */ []));
795
802
  /**
796
- * @description Sets the first day of the week.
797
- * @default "monday"
803
+ * @description Sets the first day of the week. If not specified, derives from the active locale.
804
+ * @default null
798
805
  */
799
- this.firstDay = input("monday", /* @ts-ignore */
806
+ this.firstDay = input(null, /* @ts-ignore */
800
807
  ...(ngDevMode ? [{ debugName: "firstDay" }] : /* istanbul ignore next */ []));
801
808
  /**
802
809
  * @description Marks the calendar as invalid. When bound to a signal form field via `[formField]`,
@@ -821,6 +828,13 @@ class CalendarComponent {
821
828
  */
822
829
  this.readonly = input(false, /* @ts-ignore */
823
830
  ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
831
+ /**
832
+ * @description Sets whether the calendar is required. When bound to a signal form field via `[formField]`,
833
+ * this is written by the `FormField` directive.
834
+ * @default false
835
+ */
836
+ this.required = input(false, /* @ts-ignore */
837
+ ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
824
838
  /**
825
839
  * @description Sets the border radius of the calendar.
826
840
  * @default "medium"
@@ -838,13 +852,6 @@ class CalendarComponent {
838
852
  * The `FormField` directive listens to this to mark the field as touched.
839
853
  */
840
854
  this.touch = output();
841
- /**
842
- * @description Sets whether the calendar is required. When bound to a signal form field via `[formField]`,
843
- * this is written by the `FormField` directive.
844
- * @default false
845
- */
846
- this.required = input(false, /* @ts-ignore */
847
- ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
848
855
  /**
849
856
  * @description Sets the touched state of the calendar. When bound to a signal form field via `[formField]`,
850
857
  * this is written by the `FormField` directive.
@@ -901,6 +908,21 @@ class CalendarComponent {
901
908
  .pipe(skip(1))
902
909
  .subscribe(() => this.focusActiveCell());
903
910
  }
911
+ formatInteger(value) {
912
+ if (value == null) {
913
+ return "";
914
+ }
915
+ return formatNumber(value, this.#i18n.localeId(), {
916
+ maximumFractionDigits: 0,
917
+ useGrouping: false
918
+ });
919
+ }
920
+ getWeekNumber(date) {
921
+ const dt = gregorianDateTime(date, this.#i18n.localeId());
922
+ const firstDayIso = FIRST_DAY_OF_WEEK_TO_ISO[this.effectiveFirstDay()];
923
+ const daysToThursday = (4 - firstDayIso + 7) % 7;
924
+ return dt.plus({ days: daysToThursday }).weekNumber;
925
+ }
904
926
  onDayClick(date, event) {
905
927
  event.preventDefault();
906
928
  if (this.disabled() || this.readonly()) {
@@ -955,15 +977,6 @@ class CalendarComponent {
955
977
  }
956
978
  this.navigatedDate.set(direction === "prev" ? date.minus(unit).toJSDate() : date.plus(unit).toJSDate());
957
979
  }
958
- getWeekNumber(date) {
959
- let dt = gregorianDateTime(date, this.#i18n.localeId());
960
- if (this.firstDay() === "sunday") {
961
- // In Sunday-first calendar, date is Sunday (day 0 of [Sun..Sat] row).
962
- // Thursday (day 4 of row) represents the majority of the row and defines its ISO 8601 week number.
963
- dt = dt.plus({ days: 4 });
964
- }
965
- return dt.weekNumber;
966
- }
967
980
  onTodayButtonClick() {
968
981
  if (this.disabled() || this.readonly()) {
969
982
  return;
@@ -987,6 +1000,14 @@ class CalendarComponent {
987
1000
  this.navigatedDate.set(DateTime.fromJSDate(this.navigatedDate()).set({ year }).toJSDate());
988
1001
  this.calendarView.set("year");
989
1002
  }
1003
+ clearPendingRange() {
1004
+ this.pendingRangeStart.set(null);
1005
+ this.rangePreviewDate.set(null);
1006
+ }
1007
+ commitUserSelection() {
1008
+ this.value.set(this.#outputValue());
1009
+ this.touch.emit();
1010
+ }
990
1011
  extendSelection(offset) {
991
1012
  const currentDate = this.navigatedDate();
992
1013
  const newDate = DateTime.fromJSDate(currentDate).plus({ days: offset }).toJSDate();
@@ -1001,14 +1022,6 @@ class CalendarComponent {
1001
1022
  }
1002
1023
  this.navigatedDate.set(newDate);
1003
1024
  }
1004
- clearPendingRange() {
1005
- this.pendingRangeStart.set(null);
1006
- this.rangePreviewDate.set(null);
1007
- }
1008
- commitUserSelection() {
1009
- this.value.set(this.#outputValue());
1010
- this.touch.emit();
1011
- }
1012
1025
  focusActiveCell() {
1013
1026
  rxTimeout(this.#destroyRef, () => {
1014
1027
  const calendarView = this.calendarView();
@@ -1256,6 +1269,20 @@ class CalendarComponent {
1256
1269
  this.setCurrentDate(date);
1257
1270
  }
1258
1271
  }
1272
+ horizontalCellDelta(key) {
1273
+ const isRtl = this.#direction() === "rtl";
1274
+ if (key === "ArrowLeft") {
1275
+ return isRtl ? 1 : -1;
1276
+ }
1277
+ return isRtl ? -1 : 1;
1278
+ }
1279
+ horizontalPeriodDirection(key) {
1280
+ const isRtl = this.#direction() === "rtl";
1281
+ if (key === "ArrowLeft") {
1282
+ return isRtl ? "next" : "prev";
1283
+ }
1284
+ return isRtl ? "prev" : "next";
1285
+ }
1259
1286
  isDateDisabled(date) {
1260
1287
  const disabledDates = this.disabledDates();
1261
1288
  const max = this.maxDate();
@@ -1273,20 +1300,6 @@ class CalendarComponent {
1273
1300
  const value = this.value();
1274
1301
  return value == null || (Array.isArray(value) && value.length === 0);
1275
1302
  }
1276
- horizontalCellDelta(key) {
1277
- const isRtl = this.#direction() === "rtl";
1278
- if (key === "ArrowLeft") {
1279
- return isRtl ? 1 : -1;
1280
- }
1281
- return isRtl ? -1 : 1;
1282
- }
1283
- horizontalPeriodDirection(key) {
1284
- const isRtl = this.#direction() === "rtl";
1285
- if (key === "ArrowLeft") {
1286
- return isRtl ? "next" : "prev";
1287
- }
1288
- return isRtl ? "prev" : "next";
1289
- }
1290
1303
  navigateByDaysOrCells(offset, view) {
1291
1304
  const currentDate = this.navigatedDate();
1292
1305
  const dateTime = DateTime.fromJSDate(currentDate);
@@ -1369,11 +1382,14 @@ class CalendarComponent {
1369
1382
  const dateTime = DateTime.fromJSDate(currentDate);
1370
1383
  let newDate;
1371
1384
  switch (view) {
1372
- case "month":
1373
- newDate = dateTime.endOf("month").toJSDate();
1385
+ case "month": {
1386
+ const firstDayIso = FIRST_DAY_OF_WEEK_TO_ISO[this.effectiveFirstDay()];
1387
+ const lastDayOfWeekIso = ((firstDayIso + 5) % 7) + 1;
1388
+ const daysToAdd = (lastDayOfWeekIso - dateTime.weekday + 7) % 7;
1389
+ newDate = dateTime.plus({ days: daysToAdd }).toJSDate();
1374
1390
  if (this.isDateDisabled(newDate)) {
1375
- for (let i = newDate.getDate() - 1; i >= 1; i--) {
1376
- const testDate = dateTime.set({ day: i }).toJSDate();
1391
+ for (let i = 1; i <= 6; i++) {
1392
+ const testDate = DateTime.fromJSDate(newDate).minus({ days: i }).toJSDate();
1377
1393
  if (!this.isDateDisabled(testDate)) {
1378
1394
  newDate = testDate;
1379
1395
  break;
@@ -1381,13 +1397,15 @@ class CalendarComponent {
1381
1397
  }
1382
1398
  }
1383
1399
  break;
1400
+ }
1384
1401
  case "year":
1385
1402
  newDate = dateTime.set({ month: 12 }).toJSDate();
1386
1403
  break;
1387
- case "decade":
1404
+ case "decade": {
1388
1405
  const yearEnd = this.decadeEnd();
1389
1406
  newDate = dateTime.set({ year: yearEnd }).toJSDate();
1390
1407
  break;
1408
+ }
1391
1409
  }
1392
1410
  this.rangePreviewDate.set(null);
1393
1411
  this.navigatedDate.set(newDate);
@@ -1397,12 +1415,13 @@ class CalendarComponent {
1397
1415
  const dateTime = DateTime.fromJSDate(currentDate);
1398
1416
  let newDate;
1399
1417
  switch (view) {
1400
- case "month":
1401
- newDate = dateTime.startOf("month").toJSDate();
1418
+ case "month": {
1419
+ const firstDayIso = FIRST_DAY_OF_WEEK_TO_ISO[this.effectiveFirstDay()];
1420
+ const daysToSubtract = (dateTime.weekday - firstDayIso + 7) % 7;
1421
+ newDate = dateTime.minus({ days: daysToSubtract }).toJSDate();
1402
1422
  if (this.isDateDisabled(newDate)) {
1403
- const daysInMonth = dateTime.daysInMonth ?? 31;
1404
- for (let i = 2; i <= daysInMonth; i++) {
1405
- const testDate = dateTime.set({ day: i }).toJSDate();
1423
+ for (let i = 1; i <= 6; i++) {
1424
+ const testDate = DateTime.fromJSDate(newDate).plus({ days: i }).toJSDate();
1406
1425
  if (!this.isDateDisabled(testDate)) {
1407
1426
  newDate = testDate;
1408
1427
  break;
@@ -1410,13 +1429,15 @@ class CalendarComponent {
1410
1429
  }
1411
1430
  }
1412
1431
  break;
1432
+ }
1413
1433
  case "year":
1414
1434
  newDate = dateTime.set({ month: 1 }).toJSDate();
1415
1435
  break;
1416
- case "decade":
1436
+ case "decade": {
1417
1437
  const yearStart = this.decadeStart();
1418
1438
  newDate = dateTime.set({ year: yearStart }).toJSDate();
1419
1439
  break;
1440
+ }
1420
1441
  }
1421
1442
  this.rangePreviewDate.set(null);
1422
1443
  this.navigatedDate.set(newDate);
@@ -1511,7 +1532,7 @@ class CalendarComponent {
1511
1532
  }
1512
1533
  }
1513
1534
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: CalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1514
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: CalendarComponent, isStandalone: true, selector: "mona-calendar", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, firstDay: { classPropertyName: "firstDay", publicName: "firstDay", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, weekNumber: { classPropertyName: "weekNumber", publicName: "weekNumber", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", touch: "touch", value: "valueChange" }, host: { attributes: { "role": "application" }, properties: { "attr.aria-label": "ariaLabel()", "attr.aria-invalid": "invalidState() ? 'true' : null", "attr.data-invalid": "invalidState() || null", "attr.data-required": "required() || null", "attr.tabindex": "disabled() ? -1 : 0", "class": "baseClass()" } }, queries: [{ propertyName: "decadeCellTemplate", first: true, predicate: CalendarDecadeCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "monthCellTemplate", first: true, predicate: CalendarMonthCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "yearCellTemplate", first: true, predicate: CalendarYearCellTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"headerClass()\">\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [size]=\"'small'\"\n (click)=\"onTodayButtonClick()\"\n [attr.aria-label]=\"todayButtonLabel()\">\n <span>{{ messages().today }}</span>\n </button>\n @switch (calendarView()) {\n @case (\"month\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('year')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerMonthYear()\n }}</span>\n </button>\n }\n @case (\"year\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('decade')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerYear()\n }}</span>\n </button>\n }\n @case (\"decade\") {\n <button monaButton look=\"ghost\" [rounded]=\"rounded()\" [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\"\n >{{ decadeStart() }} - {{ decadeEnd() }}</span\n >\n </button>\n }\n }\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('prev')\"\n [attr.aria-label]=\"prevButtonLabel()\">\n <svg lucideChevronLeft class=\"rtl:rotate-180\"></svg>\n </button>\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('next')\"\n [attr.aria-label]=\"nextButtonLabel()\">\n <svg lucideChevronRight class=\"rtl:rotate-180\"></svg>\n </button>\n</div>\n\n<div aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">{{ ariaLabel() }}</div>\n\n@if (calendarView() === \"month\") {\n @let columnCount = weekNumber() ? 8 : 7;\n <div [class]=\"monthGridHeaderClass()\" [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @if (weekNumber()) {\n <div></div>\n }\n @for (day of weekdays(); track day.short) {\n <div>{{ day.short }}</div>\n }\n </div>\n <div\n [class]=\"monthGridClass()\"\n [attr.aria-labelledby]=\"gridId + '-heading'\"\n (pointerleave)=\"onMonthGridPointerLeave()\"\n [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @for (row of monthDictChunked(); track $index) {\n @if (weekNumber()) {\n @let firstEntry = row | monaTakeFirst;\n @if (firstEntry) {\n @let week = getWeekNumber(firstEntry.key);\n <div>{{ week }}</div>\n }\n }\n @for (entry of row; track entry.key) {\n <div\n (dayPointerEnter)=\"onDayPointerEnter($event)\"\n (daySelect)=\"onDayClick($event.date, $event.event)\"\n monaMonthDay\n [disabled]=\"disabled()\"\n [disabledDates]=\"disabledDates()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [monthBounds]=\"[monthBounds().start, monthBounds().end]\"\n [navigatedDate]=\"navigatedDate()\"\n [rangePreview]=\"rangePreviewDates()\"\n [rounded]=\"rounded()\"\n [value]=\"selectedDates()\"\n [entry]=\"entry\">\n @if (monthCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.value, date: entry.key }\"></ng-container>\n } @else {\n <span>{{ entry.value }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"year\") {\n <div [class]=\"yearGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of months(); track $index) {\n @for (monthItem of row; track monthItem) {\n <div\n (click)=\"onMonthClick(monthItem[0])\"\n monaYearMonth\n [month]=\"monthItem[0]\"\n [monthName]=\"monthItem[1]\"\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (yearCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: monthItem[0], text: monthItem[1] }\">\n </ng-container>\n } @else {\n <span>{{ monthItem[1] }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"decade\") {\n <div [class]=\"decadeGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of decadeYears(); track $index) {\n @for (year of row; track year) {\n <div\n (click)=\"onYearClick(year)\"\n monaDecadeYear\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [year]=\"year\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (decadeCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\">\n </ng-container>\n } @else {\n <span>{{ year }}</span>\n }\n </div>\n }\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "type", "toggleable", "class"], outputs: ["disabledChange", "loadingChange", "lookChange", "selectedChange"] }, { kind: "directive", type: MonthDayDirective, selector: "[monaMonthDay]", inputs: ["disabled", "disabledDates", "entry", "max", "min", "monthBounds", "navigatedDate", "rangePreview", "rounded", "value"], outputs: ["dayPointerEnter", "daySelect"] }, { kind: "directive", type: DecadeYearDirective, selector: "[monaDecadeYear]", inputs: ["navigatedDate", "rounded", "selectedDate", "year"] }, { kind: "directive", type: YearMonthDirective, selector: "[monaYearMonth]", inputs: ["month", "monthName", "navigatedDate", "rounded", "selectedDate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideChevronLeft, selector: "svg[lucideChevronLeft]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "pipe", type: TakeFirstPipe, name: "monaTakeFirst" }] }); }
1535
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: CalendarComponent, isStandalone: true, selector: "mona-calendar", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, firstDay: { classPropertyName: "firstDay", publicName: "firstDay", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, weekNumber: { classPropertyName: "weekNumber", publicName: "weekNumber", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", touch: "touch", value: "valueChange" }, host: { attributes: { "role": "application" }, properties: { "attr.aria-label": "ariaLabel()", "attr.aria-invalid": "invalidState() ? 'true' : null", "attr.data-invalid": "invalidState() || null", "attr.data-required": "required() || null", "attr.tabindex": "disabled() ? -1 : 0", "class": "baseClass()" } }, queries: [{ propertyName: "decadeCellTemplate", first: true, predicate: CalendarDecadeCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "monthCellTemplate", first: true, predicate: CalendarMonthCellTemplateDirective, descendants: true, isSignal: true }, { propertyName: "yearCellTemplate", first: true, predicate: CalendarYearCellTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"headerClass()\">\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [size]=\"'small'\"\n (click)=\"onTodayButtonClick()\"\n [attr.aria-label]=\"todayButtonLabel()\">\n <span>{{ messages().today }}</span>\n </button>\n @switch (calendarView()) {\n @case (\"month\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('year')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerMonthYear()\n }}</span>\n </button>\n }\n @case (\"year\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('decade')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerYear()\n }}</span>\n </button>\n }\n @case (\"decade\") {\n <button monaButton look=\"ghost\" [rounded]=\"rounded()\" [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\"\n >{{ formatInteger(decadeStart()) }} - {{ formatInteger(decadeEnd()) }}</span\n >\n </button>\n }\n }\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('prev')\"\n [attr.aria-label]=\"prevButtonLabel()\">\n <svg lucideChevronLeft class=\"rtl:rotate-180\"></svg>\n </button>\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('next')\"\n [attr.aria-label]=\"nextButtonLabel()\">\n <svg lucideChevronRight class=\"rtl:rotate-180\"></svg>\n </button>\n</div>\n\n<div aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">{{ ariaLabel() }}</div>\n\n@if (calendarView() === \"month\") {\n @let columnCount = weekNumber() ? 8 : 7;\n <div [class]=\"monthGridHeaderClass()\" [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @if (weekNumber()) {\n <div></div>\n }\n @for (day of weekdays(); track day.full) {\n <div>\n <span aria-hidden=\"true\">{{ day.display }}</span>\n <span class=\"sr-only\">{{ day.full }}</span>\n </div>\n }\n </div>\n <div\n [class]=\"monthGridClass()\"\n [attr.aria-labelledby]=\"gridId + '-heading'\"\n (pointerleave)=\"onMonthGridPointerLeave()\"\n [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @for (row of monthDictChunked(); track $index) {\n @if (weekNumber()) {\n @let firstEntry = row | monaTakeFirst;\n @if (firstEntry) {\n @let week = getWeekNumber(firstEntry.key);\n <div>{{ formatInteger(week) }}</div>\n }\n }\n @for (entry of row; track entry.key) {\n <div\n (dayPointerEnter)=\"onDayPointerEnter($event)\"\n (daySelect)=\"onDayClick($event.date, $event.event)\"\n monaMonthDay\n [disabled]=\"disabled()\"\n [disabledDates]=\"disabledDates()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [monthBounds]=\"[monthBounds().start, monthBounds().end]\"\n [navigatedDate]=\"navigatedDate()\"\n [rangePreview]=\"rangePreviewDates()\"\n [rounded]=\"rounded()\"\n [value]=\"selectedDates()\"\n [entry]=\"entry\">\n @if (monthCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.value, date: entry.key }\"></ng-container>\n } @else {\n <span>{{ formatInteger(entry.value) }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"year\") {\n <div [class]=\"yearGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of months(); track $index) {\n @for (monthItem of row; track monthItem) {\n <div\n (click)=\"onMonthClick(monthItem[0])\"\n monaYearMonth\n [month]=\"monthItem[0]\"\n [monthName]=\"monthItem[1]\"\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (yearCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: monthItem[0], text: monthItem[1] }\">\n </ng-container>\n } @else {\n <span>{{ monthItem[1] }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"decade\") {\n <div [class]=\"decadeGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of decadeYears(); track $index) {\n @for (year of row; track year) {\n <div\n (click)=\"onYearClick(year)\"\n monaDecadeYear\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [year]=\"year\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (decadeCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\">\n </ng-container>\n } @else {\n <span>{{ formatInteger(year) }}</span>\n }\n </div>\n }\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "type", "toggleable", "class"], outputs: ["disabledChange", "loadingChange", "lookChange", "selectedChange"] }, { kind: "directive", type: MonthDayDirective, selector: "[monaMonthDay]", inputs: ["disabled", "disabledDates", "entry", "max", "min", "monthBounds", "navigatedDate", "rangePreview", "rounded", "value"], outputs: ["dayPointerEnter", "daySelect"] }, { kind: "directive", type: DecadeYearDirective, selector: "[monaDecadeYear]", inputs: ["navigatedDate", "rounded", "selectedDate", "year"] }, { kind: "directive", type: YearMonthDirective, selector: "[monaYearMonth]", inputs: ["month", "monthName", "navigatedDate", "rounded", "selectedDate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideChevronLeft, selector: "svg[lucideChevronLeft]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "pipe", type: TakeFirstPipe, name: "monaTakeFirst" }] }); }
1515
1536
  }
1516
1537
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: CalendarComponent, decorators: [{
1517
1538
  type: Component,
@@ -1532,8 +1553,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
1532
1553
  "[attr.data-required]": "required() || null",
1533
1554
  "[attr.tabindex]": "disabled() ? -1 : 0",
1534
1555
  "[class]": "baseClass()"
1535
- }, template: "<div [class]=\"headerClass()\">\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [size]=\"'small'\"\n (click)=\"onTodayButtonClick()\"\n [attr.aria-label]=\"todayButtonLabel()\">\n <span>{{ messages().today }}</span>\n </button>\n @switch (calendarView()) {\n @case (\"month\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('year')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerMonthYear()\n }}</span>\n </button>\n }\n @case (\"year\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('decade')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerYear()\n }}</span>\n </button>\n }\n @case (\"decade\") {\n <button monaButton look=\"ghost\" [rounded]=\"rounded()\" [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\"\n >{{ decadeStart() }} - {{ decadeEnd() }}</span\n >\n </button>\n }\n }\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('prev')\"\n [attr.aria-label]=\"prevButtonLabel()\">\n <svg lucideChevronLeft class=\"rtl:rotate-180\"></svg>\n </button>\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('next')\"\n [attr.aria-label]=\"nextButtonLabel()\">\n <svg lucideChevronRight class=\"rtl:rotate-180\"></svg>\n </button>\n</div>\n\n<div aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">{{ ariaLabel() }}</div>\n\n@if (calendarView() === \"month\") {\n @let columnCount = weekNumber() ? 8 : 7;\n <div [class]=\"monthGridHeaderClass()\" [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @if (weekNumber()) {\n <div></div>\n }\n @for (day of weekdays(); track day.short) {\n <div>{{ day.short }}</div>\n }\n </div>\n <div\n [class]=\"monthGridClass()\"\n [attr.aria-labelledby]=\"gridId + '-heading'\"\n (pointerleave)=\"onMonthGridPointerLeave()\"\n [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @for (row of monthDictChunked(); track $index) {\n @if (weekNumber()) {\n @let firstEntry = row | monaTakeFirst;\n @if (firstEntry) {\n @let week = getWeekNumber(firstEntry.key);\n <div>{{ week }}</div>\n }\n }\n @for (entry of row; track entry.key) {\n <div\n (dayPointerEnter)=\"onDayPointerEnter($event)\"\n (daySelect)=\"onDayClick($event.date, $event.event)\"\n monaMonthDay\n [disabled]=\"disabled()\"\n [disabledDates]=\"disabledDates()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [monthBounds]=\"[monthBounds().start, monthBounds().end]\"\n [navigatedDate]=\"navigatedDate()\"\n [rangePreview]=\"rangePreviewDates()\"\n [rounded]=\"rounded()\"\n [value]=\"selectedDates()\"\n [entry]=\"entry\">\n @if (monthCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.value, date: entry.key }\"></ng-container>\n } @else {\n <span>{{ entry.value }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"year\") {\n <div [class]=\"yearGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of months(); track $index) {\n @for (monthItem of row; track monthItem) {\n <div\n (click)=\"onMonthClick(monthItem[0])\"\n monaYearMonth\n [month]=\"monthItem[0]\"\n [monthName]=\"monthItem[1]\"\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (yearCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: monthItem[0], text: monthItem[1] }\">\n </ng-container>\n } @else {\n <span>{{ monthItem[1] }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"decade\") {\n <div [class]=\"decadeGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of decadeYears(); track $index) {\n @for (year of row; track year) {\n <div\n (click)=\"onYearClick(year)\"\n monaDecadeYear\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [year]=\"year\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (decadeCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\">\n </ng-container>\n } @else {\n <span>{{ year }}</span>\n }\n </div>\n }\n }\n </div>\n}\n" }]
1536
- }], ctorParameters: () => [], propDecorators: { decadeCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarDecadeCellTemplateDirective), { isSignal: true }] }], monthCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarMonthCellTemplateDirective), { isSignal: true }] }], yearCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarYearCellTemplateDirective), { isSignal: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], disabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDates", required: false }] }], firstDay: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDay", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], weekNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekNumber", required: false }] }] } });
1556
+ }, template: "<div [class]=\"headerClass()\">\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [size]=\"'small'\"\n (click)=\"onTodayButtonClick()\"\n [attr.aria-label]=\"todayButtonLabel()\">\n <span>{{ messages().today }}</span>\n </button>\n @switch (calendarView()) {\n @case (\"month\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('year')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerMonthYear()\n }}</span>\n </button>\n }\n @case (\"year\") {\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n (click)=\"onViewChangeClick('decade')\"\n [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\">{{\n headerYear()\n }}</span>\n </button>\n }\n @case (\"decade\") {\n <button monaButton look=\"ghost\" [rounded]=\"rounded()\" [attr.aria-label]=\"viewSwitchButtonLabel()\">\n <span class=\"text-primary font-semibold\" [id]=\"gridId + '-heading'\"\n >{{ formatInteger(decadeStart()) }} - {{ formatInteger(decadeEnd()) }}</span\n >\n </button>\n }\n }\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('prev')\"\n [attr.aria-label]=\"prevButtonLabel()\">\n <svg lucideChevronLeft class=\"rtl:rotate-180\"></svg>\n </button>\n <button\n monaButton\n look=\"ghost\"\n [rounded]=\"rounded()\"\n [iconOnly]=\"true\"\n [size]=\"'small'\"\n (click)=\"onNavigationClick('next')\"\n [attr.aria-label]=\"nextButtonLabel()\">\n <svg lucideChevronRight class=\"rtl:rotate-180\"></svg>\n </button>\n</div>\n\n<div aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">{{ ariaLabel() }}</div>\n\n@if (calendarView() === \"month\") {\n @let columnCount = weekNumber() ? 8 : 7;\n <div [class]=\"monthGridHeaderClass()\" [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @if (weekNumber()) {\n <div></div>\n }\n @for (day of weekdays(); track day.full) {\n <div>\n <span aria-hidden=\"true\">{{ day.display }}</span>\n <span class=\"sr-only\">{{ day.full }}</span>\n </div>\n }\n </div>\n <div\n [class]=\"monthGridClass()\"\n [attr.aria-labelledby]=\"gridId + '-heading'\"\n (pointerleave)=\"onMonthGridPointerLeave()\"\n [style.grid-template-columns]=\"`repeat(${columnCount}, 32px)`\">\n @for (row of monthDictChunked(); track $index) {\n @if (weekNumber()) {\n @let firstEntry = row | monaTakeFirst;\n @if (firstEntry) {\n @let week = getWeekNumber(firstEntry.key);\n <div>{{ formatInteger(week) }}</div>\n }\n }\n @for (entry of row; track entry.key) {\n <div\n (dayPointerEnter)=\"onDayPointerEnter($event)\"\n (daySelect)=\"onDayClick($event.date, $event.event)\"\n monaMonthDay\n [disabled]=\"disabled()\"\n [disabledDates]=\"disabledDates()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [monthBounds]=\"[monthBounds().start, monthBounds().end]\"\n [navigatedDate]=\"navigatedDate()\"\n [rangePreview]=\"rangePreviewDates()\"\n [rounded]=\"rounded()\"\n [value]=\"selectedDates()\"\n [entry]=\"entry\">\n @if (monthCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"monthCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.value, date: entry.key }\"></ng-container>\n } @else {\n <span>{{ formatInteger(entry.value) }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"year\") {\n <div [class]=\"yearGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of months(); track $index) {\n @for (monthItem of row; track monthItem) {\n <div\n (click)=\"onMonthClick(monthItem[0])\"\n monaYearMonth\n [month]=\"monthItem[0]\"\n [monthName]=\"monthItem[1]\"\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (yearCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"yearCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: monthItem[0], text: monthItem[1] }\">\n </ng-container>\n } @else {\n <span>{{ monthItem[1] }}</span>\n }\n </div>\n }\n }\n </div>\n} @else if (calendarView() === \"decade\") {\n <div [class]=\"decadeGridClass()\" [attr.aria-labelledby]=\"gridId + '-heading'\">\n @for (row of decadeYears(); track $index) {\n @for (year of row; track year) {\n <div\n (click)=\"onYearClick(year)\"\n monaDecadeYear\n [navigatedDate]=\"navigatedDate()\"\n [rounded]=\"rounded()\"\n [year]=\"year\"\n [selectedDate]=\"selectedDates()[0]\">\n @if (decadeCellTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"decadeCellTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: year }\">\n </ng-container>\n } @else {\n <span>{{ formatInteger(year) }}</span>\n }\n </div>\n }\n }\n </div>\n}\n" }]
1557
+ }], ctorParameters: () => [], propDecorators: { decadeCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarDecadeCellTemplateDirective), { isSignal: true }] }], monthCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarMonthCellTemplateDirective), { isSignal: true }] }], yearCellTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CalendarYearCellTemplateDirective), { isSignal: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], disabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDates", required: false }] }], firstDay: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDay", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], weekNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekNumber", required: false }] }] } });
1537
1558
 
1538
1559
  /*
1539
1560
  * Public API Surface of @nanahoshi/mona-ui/calendar