@k2b/ui 0.22.0 → 0.23.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.
Files changed (98) hide show
  1. package/dist/browser/content/Calendar.js +1086 -1049
  2. package/dist/browser/content/Calendar.js.map +1 -1
  3. package/dist/browser/content/CalendarDayView.js +1187 -0
  4. package/dist/browser/content/CalendarDayView.js.map +1 -0
  5. package/dist/browser/content/CalendarWeekView.js +1571 -0
  6. package/dist/browser/content/CalendarWeekView.js.map +1 -0
  7. package/dist/browser/content/ChartExplorer.js +174 -82
  8. package/dist/browser/content/ChartExplorer.js.map +1 -1
  9. package/dist/browser/content/ChartFilterControls.js +90 -33
  10. package/dist/browser/content/ChartFilterControls.js.map +1 -1
  11. package/dist/browser/content/DataTable.js +199 -171
  12. package/dist/browser/content/DataTable.js.map +1 -1
  13. package/dist/browser/content/calendar-day-scroll.js +98 -0
  14. package/dist/browser/content/calendar-day-scroll.js.map +1 -0
  15. package/dist/browser/content/calendar-days.js +408 -0
  16. package/dist/browser/content/calendar-days.js.map +1 -0
  17. package/dist/browser/content/calendar-dialogs.js +236 -0
  18. package/dist/browser/content/calendar-dialogs.js.map +1 -0
  19. package/dist/browser/content/calendar-messages.js +210 -2
  20. package/dist/browser/content/calendar-messages.js.map +1 -1
  21. package/dist/browser/content/calendar-pointer.js +15 -3
  22. package/dist/browser/content/calendar-pointer.js.map +1 -1
  23. package/dist/browser/content/calendar-shared.js +328 -0
  24. package/dist/browser/content/calendar-shared.js.map +1 -0
  25. package/dist/browser/content/calendar-time-view.js +1649 -0
  26. package/dist/browser/content/calendar-time-view.js.map +1 -0
  27. package/dist/browser/content/chart-messages.js +10 -0
  28. package/dist/browser/content/chart-messages.js.map +1 -1
  29. package/dist/browser/content/index.js.map +1 -1
  30. package/dist/browser/inputs/Combobox.js +0 -1
  31. package/dist/browser/inputs/Combobox.js.map +1 -1
  32. package/dist/browser/layout/AppWorkspace.js +123 -97
  33. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  34. package/dist/browser/layout/PageTitle.js +4 -1
  35. package/dist/browser/layout/PageTitle.js.map +1 -1
  36. package/dist/browser/layout/app-workspace-controller.js +164 -86
  37. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  38. package/dist/browser/surfaces/StatCell.js +18 -6
  39. package/dist/browser/surfaces/StatCell.js.map +1 -1
  40. package/dist/ssr/content/Calendar.js +524 -335
  41. package/dist/ssr/content/Calendar.js.map +1 -1
  42. package/dist/ssr/content/CalendarDayView.js +800 -0
  43. package/dist/ssr/content/CalendarDayView.js.map +1 -0
  44. package/dist/ssr/content/CalendarWeekView.js +1069 -0
  45. package/dist/ssr/content/CalendarWeekView.js.map +1 -0
  46. package/dist/ssr/content/ChartExplorer.js +93 -34
  47. package/dist/ssr/content/ChartExplorer.js.map +1 -1
  48. package/dist/ssr/content/ChartFilterControls.js +49 -7
  49. package/dist/ssr/content/ChartFilterControls.js.map +1 -1
  50. package/dist/ssr/content/DataTable.js +69 -51
  51. package/dist/ssr/content/DataTable.js.map +1 -1
  52. package/dist/ssr/content/calendar-day-scroll.js +98 -0
  53. package/dist/ssr/content/calendar-day-scroll.js.map +1 -0
  54. package/dist/ssr/content/calendar-days.js +408 -0
  55. package/dist/ssr/content/calendar-days.js.map +1 -0
  56. package/dist/ssr/content/calendar-dialogs.js +159 -0
  57. package/dist/ssr/content/calendar-dialogs.js.map +1 -0
  58. package/dist/ssr/content/calendar-messages.js +210 -2
  59. package/dist/ssr/content/calendar-messages.js.map +1 -1
  60. package/dist/ssr/content/calendar-pointer.js +15 -3
  61. package/dist/ssr/content/calendar-pointer.js.map +1 -1
  62. package/dist/ssr/content/calendar-shared.js +261 -0
  63. package/dist/ssr/content/calendar-shared.js.map +1 -0
  64. package/dist/ssr/content/calendar-time-view.js +1306 -0
  65. package/dist/ssr/content/calendar-time-view.js.map +1 -0
  66. package/dist/ssr/content/chart-messages.js +10 -0
  67. package/dist/ssr/content/chart-messages.js.map +1 -1
  68. package/dist/ssr/content/index.js.map +1 -1
  69. package/dist/ssr/inputs/Combobox.js.map +1 -1
  70. package/dist/ssr/layout/AppWorkspace.js +38 -29
  71. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  72. package/dist/ssr/layout/PageTitle.js +4 -1
  73. package/dist/ssr/layout/PageTitle.js.map +1 -1
  74. package/dist/ssr/layout/app-workspace-controller.js +164 -86
  75. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  76. package/dist/ssr/surfaces/StatCell.js +2 -2
  77. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  78. package/dist/styles.css +1 -1
  79. package/dist/types/content/Calendar.d.ts +91 -0
  80. package/dist/types/content/CalendarDayView.d.ts +7 -0
  81. package/dist/types/content/CalendarWeekView.d.ts +7 -0
  82. package/dist/types/content/ChartExplorer.d.ts +36 -1
  83. package/dist/types/content/ChartFilterControls.d.ts +6 -1
  84. package/dist/types/content/DataTable.d.ts +5 -0
  85. package/dist/types/content/calendar-day-scroll.d.ts +42 -0
  86. package/dist/types/content/calendar-days.d.ts +192 -0
  87. package/dist/types/content/calendar-dialogs.d.ts +22 -0
  88. package/dist/types/content/calendar-messages.d.ts +99 -0
  89. package/dist/types/content/calendar-pointer.d.ts +9 -0
  90. package/dist/types/content/calendar-shared.d.ts +69 -0
  91. package/dist/types/content/calendar-time-view.d.ts +252 -0
  92. package/dist/types/content/chart-messages.d.ts +5 -0
  93. package/dist/types/content/index.d.ts +2 -2
  94. package/dist/types/layout/AppWorkspace.d.ts +25 -3
  95. package/dist/types/layout/PageTitle.d.ts +2 -1
  96. package/dist/types/layout/app-workspace-controller.d.ts +9 -1
  97. package/dist/types/surfaces/StatCell.d.ts +5 -0
  98. package/package.json +1 -1
@@ -1,77 +1,70 @@
1
+ import { ssrStyle as _$ssrStyle } from "solid-js/web";
1
2
  import { ssrStyleProperty as _$ssrStyleProperty } from "solid-js/web";
2
3
  import { memo as _$memo } from "solid-js/web";
3
- import { ssrElement as _$ssrElement } from "solid-js/web";
4
- import { mergeProps as _$mergeProps } from "solid-js/web";
5
- import { ssrStyle as _$ssrStyle } from "solid-js/web";
4
+ import { ssr as _$ssr } from "solid-js/web";
6
5
  import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
7
6
  import { createComponent as _$createComponent } from "solid-js/web";
8
- import { ssr as _$ssr } from "solid-js/web";
7
+ import { ssrElement as _$ssrElement } from "solid-js/web";
8
+ import { mergeProps as _$mergeProps } from "solid-js/web";
9
9
  import { escape as _$escape } from "solid-js/web";
10
- var _tmpl$ = ["<span class=\"k2b-calendar-event__time\">", "</span>"],
11
- _tmpl$2 = "<span class=\"k2b-calendar-event__marker\" aria-hidden=\"true\"></span>",
12
- _tmpl$3 = ["<span class=\"k2b-calendar-event__title\">", "", "</span>"],
13
- _tmpl$4 = ["<span class=\"k2b-calendar-event__meta\">", "</span>"],
14
- _tmpl$5 = ["<span class=\"k2b-calendar-event__description\">", "</span>"],
15
- _tmpl$6 = ["<span class=\"k2b-calendar-event__hint\" data-edge=\"start\" aria-hidden=\"true\">", "</span>"],
16
- _tmpl$7 = ["<span class=\"k2b-calendar-event__hint\" data-edge=\"end\" aria-hidden=\"true\">", "</span>"],
17
- _tmpl$8 = ["<a", " class=\"k2b-calendar-event\" data-calendar-event", " style=\"", "\"", ">", "</a>"],
18
- _tmpl$9 = ["<button type=\"button\" class=\"k2b-calendar-event\" data-calendar-event", " data-interactive=\"true\"", " style=\"", "\"", ">", "</button>"],
19
- _tmpl$0 = ["<div class=\"k2b-calendar-event\" role=\"group\" data-calendar-event", " style=\"", "\"", ">", "</div>"],
20
- _tmpl$1 = ["<div role=\"radiogroup\"", " aria-orientation=\"horizontal\" class=\"k2b-segmented-control k2b-calendar-view-switcher\">", "</div>"],
21
- _tmpl$10 = ["<i class=\"", "\"></i>"],
22
- _tmpl$11 = ["<button type=\"button\"", " class=\"k2b-calendar-header__nav-button\"><i class=\"", "\"></i></button>"],
23
- _tmpl$12 = ["<span class=\"k2b-button__label\">", "</span>"],
24
- _tmpl$13 = ["<div class=\"k2b-calendar-header__content\">", "</div>"],
25
- _tmpl$14 = "<span class=\"k2b-calendar-header__progress\" aria-hidden=\"true\"></span>",
26
- _tmpl$15 = ["<header class=\"k2b-calendar-header\"><div class=\"k2b-calendar-header__navigation\">", "", "<div class=\"k2b-calendar-header__title\"><span>", "</span>", "</div></div>", "<div class=\"k2b-calendar-header__actions\">", "", "", "</div>", "</header>"],
27
- _tmpl$16 = ["<span class=\"k2b-calendar-header__title-size\" aria-hidden=\"true\">", "</span>"],
28
- _tmpl$17 = ["<div class=\"k2b-calendar-month__weekday\">", "</div>"],
29
- _tmpl$18 = ["<div class=\"k2b-calendar-month\" style=\"", "\"><div class=\"k2b-calendar-month__weekdays\"", ">", "", "</div>", "</div>"],
30
- _tmpl$19 = ["<div class=\"k2b-calendar-month__week-number\">", "</div>"],
31
- _tmpl$20 = ["<div class=\"k2b-calendar-month__week\"", ">", "", "</div>"],
32
- _tmpl$21 = ["<div class=\"k2b-calendar-preview\">", "</div>"],
33
- _tmpl$22 = ["<div class=\"k2b-calendar-month__day\"", ">", "<div class=\"k2b-calendar-month__day-header\">", "", "</div><div class=\"k2b-calendar-month__events\">", "", "", "</div><div class=\"k2b-calendar-month__dots\">", "</div></div>"],
34
- _tmpl$23 = ["<span class=\"k2b-calendar-month__day-number\"", ">", "</span>"],
35
- _tmpl$24 = ["<span class=\"k2b-calendar-month__badge\">", "", "</span>"],
36
- _tmpl$25 = ["<span class=\"k2b-calendar-dot\"", " style=\"", "\"></span>"],
37
- _tmpl$26 = ["<div class=\"k2b-calendar-month__weekday\" role=\"columnheader\">", "</div>"],
38
- _tmpl$27 = ["<div class=\"k2b-calendar-month\" role=\"grid\"", " aria-multiselectable=\"true\" data-lanes=\"true\" style=\"", "\"><div class=\"k2b-calendar-month__weekdays\" role=\"row\"", ">", "", "</div>", "</div>"],
39
- _tmpl$28 = ["<div class=\"k2b-calendar-month__weekday\" role=\"columnheader\"", ">", "</div>"],
40
- _tmpl$29 = ["<div class=\"k2b-calendar-month__week-number\" role=\"rowheader\">", "</div>"],
41
- _tmpl$30 = ["<div class=\"k2b-calendar-month__week\" role=\"row\"", ">", "", "</div>"],
42
- _tmpl$31 = ["<button type=\"button\" class=\"k2b-calendar-month__week-link\" tabindex=\"-1\"", ">", "</button>"],
43
- _tmpl$32 = ["<button type=\"button\" class=\"k2b-calendar-month__more\" tabindex=\"-1\" style=\"", "\"", " aria-haspopup=\"dialog\"", "><span class=\"k2b-calendar-month__more-long\">", "</span><span class=\"k2b-calendar-month__more-short\">+", "</span></button>"],
44
- _tmpl$33 = ["<div class=\"k2b-calendar-month__day\" role=\"gridcell\"", "><div class=\"k2b-calendar-month__day-header\"><span class=\"k2b-calendar-month__day-number\"", ">", "</span>", "</div><div class=\"k2b-calendar-month__lanes\">", "", "", "</div></div>"],
45
- _tmpl$34 = ["<div class=\"k2b-calendar-month__segment\" style=\"", "\">", "</div>"],
46
- _tmpl$35 = ["<ul class=\"k2b-calendar-day-list__events\">", "</ul>"],
47
- _tmpl$36 = "<i class=\"ti ti-plus\" aria-hidden=\"true\"></i>",
48
- _tmpl$37 = ["<div class=\"k2b-calendar-day-list\"><div class=\"k2b-calendar-day-list__title\">", "</div>", "<div class=\"k2b-calendar-day-list__actions\">", "", "</div></div>"],
49
- _tmpl$38 = ["<p class=\"k2b-calendar-day-list__empty\">", "</p>"],
50
- _tmpl$39 = ["<li>", "</li>"],
51
- _tmpl$40 = "<i class=\"ti ti-zoom-in\" aria-hidden=\"true\"></i>",
52
- _tmpl$41 = ["<div class=\"k2b-calendar-popover\" popover=\"auto\" role=\"dialog\"", ">", "</div>"],
53
- _tmpl$42 = ["<div class=\"k2b-calendar-time-grid__all-day\" style=\"", "\"><div class=\"k2b-calendar-time-grid__all-day-label\">", "</div>", "</div>"],
54
- _tmpl$43 = ["<div class=\"k2b-calendar-time-grid\"><div class=\"k2b-calendar-time-grid__days\" style=\"", "\"><div></div>", "</div>", "<div class=\"k2b-calendar-time-grid__scroll\"><div class=\"k2b-calendar-time-grid__grid\" style=\"", "\"><div class=\"k2b-calendar-time-grid__gutter\" style=\"", "\">", "</div>", "</div></div></div>"],
55
- _tmpl$44 = ["<span class=\"k2b-calendar-time-grid__day-label\"", ">", "</span>"],
56
- _tmpl$45 = ["<span class=\"k2b-calendar-time-grid__badge\">", "", "</span>"],
57
- _tmpl$46 = ["<div class=\"k2b-calendar-time-grid__all-day-events\">", "", "</div>"],
58
- _tmpl$47 = ["<div class=\"k2b-calendar-time-grid__hour\"", ">", ":00</div>"],
59
- _tmpl$48 = ["<div class=\"k2b-calendar-time-grid__now\" style=\"", "\"></div>"],
60
- _tmpl$49 = ["<div class=\"k2b-calendar-time-grid__column\" style=\"", "\">", "", "", "", "", "</div>"],
61
- _tmpl$50 = ["<div class=\"k2b-calendar-preview__title\">", "</div>"],
62
- _tmpl$51 = ["<div class=\"k2b-calendar-preview k2b-calendar-preview--timed\"", " style=\"", "\"><div class=\"k2b-calendar-preview__content\">", "<div class=\"k2b-calendar-preview__label\">", " - ", "</div></div></div>"],
63
- _tmpl$52 = ["<button type=\"button\"", " draggable=\"false\" class=\"k2b-calendar-time-grid__resize\"><span class=\"k2b-calendar-time-grid__resize-icon\" aria-hidden=\"true\"></span></button>"],
64
- _tmpl$53 = ["<div class=\"k2b-calendar-time-grid__event-position\" style=\"", "\"><div class=\"k2b-calendar-time-grid__event-frame\">", "", "</div></div>"],
65
- _tmpl$54 = ["<button type=\"button\" class=\"k2b-calendar-time-grid__overflow\" style=\"", "\"", "><span class=\"k2b-calendar-time-grid__overflow-count\">+", "</span></button>"],
66
- _tmpl$55 = ["<div class=\"k2b-calendar-time-grid__overflow-menu\" style=\"", "\"><div class=\"k2b-calendar-time-grid__overflow-title\">", " - ", "</div>", "</div>"],
67
- _tmpl$56 = ["<div class=\"k2b-calendar-year\">", "</div>"],
68
- _tmpl$57 = ["<div class=\"k2b-calendar-year__month\"><div class=\"k2b-calendar-year__title\">", "</div><div class=\"k2b-calendar-year__grid\">", "</div></div>"],
69
- _tmpl$58 = ["<span class=\"k2b-calendar-year__indicator\"", " style=\"", "\"></span>"],
70
- _tmpl$59 = ["<div class=\"k2b-calendar-mobile-month__events\">", "</div>"],
71
- _tmpl$60 = ["<div class=\"k2b-calendar-mobile-month\">", "<div class=\"k2b-calendar-mobile-month__agenda\"><div class=\"k2b-calendar-mobile-month__title\">", "</div>", "</div></div>"],
72
- _tmpl$61 = ["<div class=\"k2b-calendar-mobile-month__empty\">", "</div>"],
73
- _tmpl$62 = ["<div class=\"k2b-calendar-body\">", "</div>"],
74
- _tmpl$63 = ["<section class=\"", "\"", ">", "", "</section>"];
10
+ var _tmpl$ = ["<div role=\"radiogroup\"", " aria-orientation=\"horizontal\" class=\"k2b-segmented-control k2b-calendar-view-switcher\">", "</div>"],
11
+ _tmpl$2 = ["<i class=\"", "\"></i>"],
12
+ _tmpl$3 = ["<button type=\"button\"", " class=\"k2b-calendar-header__nav-button\"><i class=\"", "\"></i></button>"],
13
+ _tmpl$4 = "<i class=\"ti ti-arrow-narrow-right k2b-calendar-header__today-direction\" aria-hidden=\"true\"></i>",
14
+ _tmpl$5 = "<i class=\"ti ti-point k2b-calendar-header__today-direction\" aria-hidden=\"true\"></i>",
15
+ _tmpl$6 = ["<span class=\"k2b-button__label\">", "</span>"],
16
+ _tmpl$7 = ["<div class=\"k2b-calendar-header__content\">", "</div>"],
17
+ _tmpl$8 = ["<button type=\"button\" class=\"k2b-calendar-header__shortcuts\"", "><i class=\"ti ti-keyboard\" aria-hidden=\"true\"></i></button>"],
18
+ _tmpl$9 = "<span class=\"k2b-calendar-header__progress\" aria-hidden=\"true\"></span>",
19
+ _tmpl$0 = ["<header class=\"k2b-calendar-header\"><div class=\"k2b-calendar-header__navigation\">", "", "<div class=\"k2b-calendar-header__title\"><span>", "</span>", "</div></div>", "<div class=\"k2b-calendar-header__actions\">", "", "", "", "</div>", "</header>"],
20
+ _tmpl$1 = ["<span class=\"k2b-calendar-header__title-size\" aria-hidden=\"true\">", "</span>"],
21
+ _tmpl$10 = ["<div class=\"k2b-calendar-month__weekday\">", "</div>"],
22
+ _tmpl$11 = ["<div class=\"k2b-calendar-month\" style=\"", "\"><div class=\"k2b-calendar-month__weekdays\"", ">", "", "</div>", "</div>"],
23
+ _tmpl$12 = ["<div class=\"k2b-calendar-month__week-number\">", "</div>"],
24
+ _tmpl$13 = ["<div class=\"k2b-calendar-month__week\"", ">", "", "</div>"],
25
+ _tmpl$14 = ["<div class=\"k2b-calendar-preview\">", "</div>"],
26
+ _tmpl$15 = ["<div class=\"k2b-calendar-month__day\"", ">", "<div class=\"k2b-calendar-month__day-header\">", "", "</div><div class=\"k2b-calendar-month__events\">", "", "", "</div><div class=\"k2b-calendar-month__dots\">", "</div></div>"],
27
+ _tmpl$16 = ["<span class=\"k2b-calendar-month__day-number\"", ">", "</span>"],
28
+ _tmpl$17 = ["<span class=\"k2b-calendar-month__badge\">", "", "</span>"],
29
+ _tmpl$18 = ["<span class=\"k2b-calendar-dot\"", " style=\"", "\"></span>"],
30
+ _tmpl$19 = ["<div class=\"k2b-calendar-month__weekday\" role=\"columnheader\">", "</div>"],
31
+ _tmpl$20 = ["<div class=\"k2b-calendar-month\" role=\"grid\"", " aria-multiselectable=\"true\" data-lanes=\"true\" style=\"", "\"><div class=\"k2b-calendar-month__weekdays\" role=\"row\"", ">", "", "</div>", "</div>"],
32
+ _tmpl$21 = ["<div class=\"k2b-calendar-month__weekday\" role=\"columnheader\"", ">", "</div>"],
33
+ _tmpl$22 = ["<div class=\"k2b-calendar-month__week-number\" role=\"rowheader\">", "</div>"],
34
+ _tmpl$23 = ["<div class=\"k2b-calendar-month__week\" role=\"row\"", ">", "", "</div>"],
35
+ _tmpl$24 = ["<button type=\"button\" class=\"k2b-calendar-month__week-link\" tabindex=\"-1\"", ">", "</button>"],
36
+ _tmpl$25 = ["<button type=\"button\" class=\"k2b-calendar-month__more\" tabindex=\"-1\" style=\"", "\"", " aria-haspopup=\"dialog\"", "><span class=\"k2b-calendar-month__more-long\">", "</span><span class=\"k2b-calendar-month__more-short\">+", "</span></button>"],
37
+ _tmpl$26 = ["<div class=\"k2b-calendar-month__day\" role=\"gridcell\"", "><div class=\"k2b-calendar-month__day-header\"><span class=\"k2b-calendar-month__day-number\"", ">", "</span>", "</div><div class=\"k2b-calendar-month__lanes\">", "", "", "</div></div>"],
38
+ _tmpl$27 = ["<div class=\"k2b-calendar-month__segment\" style=\"", "\">", "</div>"],
39
+ _tmpl$28 = ["<ul class=\"k2b-calendar-day-list__events\">", "</ul>"],
40
+ _tmpl$29 = "<i class=\"ti ti-plus\" aria-hidden=\"true\"></i>",
41
+ _tmpl$30 = ["<div class=\"k2b-calendar-day-list\"><div class=\"k2b-calendar-day-list__title\">", "</div>", "<div class=\"k2b-calendar-day-list__actions\">", "", "</div></div>"],
42
+ _tmpl$31 = ["<p class=\"k2b-calendar-day-list__empty\">", "</p>"],
43
+ _tmpl$32 = ["<li>", "</li>"],
44
+ _tmpl$33 = "<i class=\"ti ti-zoom-in\" aria-hidden=\"true\"></i>",
45
+ _tmpl$34 = ["<div class=\"k2b-calendar-popover\" popover=\"auto\" role=\"dialog\"", ">", "</div>"],
46
+ _tmpl$35 = ["<div class=\"k2b-calendar-time-grid__all-day\" style=\"", "\"><div class=\"k2b-calendar-time-grid__all-day-label\">", "</div>", "</div>"],
47
+ _tmpl$36 = ["<div class=\"k2b-calendar-time-grid k2b-detail-trail\"", "><div class=\"k2b-calendar-time-grid__days\" style=\"", "\"><div></div>", "</div>", "<div class=\"k2b-calendar-time-grid__scroll\"><div class=\"k2b-calendar-time-grid__grid\" style=\"", "\"><div class=\"k2b-calendar-time-grid__gutter\" style=\"", "\">", "</div>", "</div></div></div>"],
48
+ _tmpl$37 = ["<span class=\"k2b-calendar-time-grid__day-label\"", ">", "</span>"],
49
+ _tmpl$38 = ["<span class=\"k2b-calendar-time-grid__badge\">", "", "</span>"],
50
+ _tmpl$39 = ["<div class=\"k2b-calendar-time-grid__all-day-events\">", "", "</div>"],
51
+ _tmpl$40 = ["<div class=\"k2b-calendar-time-grid__hour\"", ">", ":00</div>"],
52
+ _tmpl$41 = ["<div class=\"k2b-calendar-time-grid__now\" style=\"", "\"></div>"],
53
+ _tmpl$42 = ["<div class=\"k2b-calendar-time-grid__column\" style=\"", "\">", "", "", "", "", "</div>"],
54
+ _tmpl$43 = ["<div class=\"k2b-calendar-preview__title\">", "</div>"],
55
+ _tmpl$44 = ["<div class=\"k2b-calendar-preview k2b-calendar-preview--timed\"", " style=\"", "\"><div class=\"k2b-calendar-preview__content\">", "<div class=\"k2b-calendar-preview__label\">", " - ", "</div></div></div>"],
56
+ _tmpl$45 = ["<button type=\"button\"", " draggable=\"false\" class=\"k2b-calendar-time-grid__resize\"><span class=\"k2b-calendar-time-grid__resize-icon\" aria-hidden=\"true\"></span></button>"],
57
+ _tmpl$46 = ["<div class=\"k2b-calendar-time-grid__event-position\" style=\"", "\"><div class=\"k2b-calendar-time-grid__event-frame\">", "", "</div></div>"],
58
+ _tmpl$47 = ["<button type=\"button\" class=\"k2b-calendar-time-grid__overflow\" style=\"", "\"", "><span class=\"k2b-calendar-time-grid__overflow-count\">+", "</span></button>"],
59
+ _tmpl$48 = ["<div class=\"k2b-calendar-time-grid__overflow-menu\" style=\"", "\"><div class=\"k2b-calendar-time-grid__overflow-title\">", " - ", "</div>", "</div>"],
60
+ _tmpl$49 = ["<div class=\"k2b-calendar-year\">", "</div>"],
61
+ _tmpl$50 = ["<div class=\"k2b-calendar-year__month\"><div class=\"k2b-calendar-year__title\">", "</div><div class=\"k2b-calendar-year__grid\">", "</div></div>"],
62
+ _tmpl$51 = ["<span class=\"k2b-calendar-year__indicator\"", " style=\"", "\"></span>"],
63
+ _tmpl$52 = ["<div class=\"k2b-calendar-mobile-month__events\">", "</div>"],
64
+ _tmpl$53 = ["<div class=\"k2b-calendar-mobile-month\">", "<div class=\"k2b-calendar-mobile-month__agenda\"><div class=\"k2b-calendar-mobile-month__title\">", "</div>", "</div></div>"],
65
+ _tmpl$54 = ["<div class=\"k2b-calendar-mobile-month__empty\">", "</div>"],
66
+ _tmpl$55 = ["<div class=\"k2b-calendar-body\">", "</div>"],
67
+ _tmpl$56 = ["<section class=\"", "\"", ">", "", "</section>"];
75
68
  import { Link } from "@k2b/ssr/nav";
76
69
  import { dates as calendar } from "@k2b/stdlib";
77
70
  import { createEffect, createMemo, createSignal, For, mergeProps, on, onCleanup, onMount, Show, untrack } from "solid-js";
@@ -80,31 +73,29 @@ import { GestureMenu } from "../actions/GestureMenu";
80
73
  import SegmentedControl from "../actions/SegmentedControl";
81
74
  import { useDateConfigLocale } from "../intl/locale";
82
75
  import { useUiMessages } from "../intl/messages";
76
+ import { CalendarDayView } from "./CalendarDayView";
77
+ import { CalendarWeekView } from "./CalendarWeekView";
78
+ import { openCalendarGoTo, openCalendarShortcuts } from "./calendar-dialogs";
83
79
  import { layoutCalendarIntervals } from "./calendar-event-layout";
84
80
  import { useCalendarMessages } from "./calendar-messages";
85
81
  import { fitMonthWeek, layoutMonthWeek, monthLaneCapacity } from "./calendar-month-layout";
86
82
  import { calendarDayIndexAtPoint, calendarMinuteAtPoint, startCalendarPointerSession } from "./calendar-pointer";
83
+ import { EventChip, eventHref, followCalendarHref, formatTime, ownerDateConfig, parseDate, placeCalendarPopover, textWidth, validDate } from "./calendar-shared";
84
+ import { compactGermanDate } from "./calendar-time-view";
87
85
 
88
- /** A view the application adds to the switcher; the calendar shows its header and toolbar, the application the body. */
86
+ /** The days a host loaded events for, from the first day `from` up to `to`, both `YYYY-MM-DD` or dates. */
89
87
 
90
- /** What the built-in views read from the props: they only ever link to built-in views. */
88
+ /**
89
+ * An action the calendar offers for keyboard shortcuts, the command palette, and its shortcuts dialog. The calendar
90
+ * publishes its own through `onCommandsChange`; the host registers them with its shortcut dispatcher.
91
+ */
92
+
93
+ /** An entry dragged into the day or week view from outside the calendar, such as a task from a list below it. */
94
+
95
+ /** Actions of the calendar that the host starts from its own controls. */
96
+
97
+ /** A view the application adds to the switcher; the calendar shows its header and toolbar, the application the body. */
91
98
 
92
- const ownerDateConfig = owner => ({
93
- ...owner.dateConfig,
94
- timeZone: owner.timeZone ?? owner.dateConfig?.timeZone,
95
- firstDayOfWeek: owner.firstDayOfWeek ?? owner.dateConfig?.firstDayOfWeek ?? owner.dateConfig?.weekStartsOn ?? 1
96
- });
97
- const dateOnlyPattern = /^\d{4}-\d{2}-\d{2}$/;
98
- const parseDate = (value, context) => {
99
- if (value instanceof Date) return new Date(value);
100
- if (dateOnlyPattern.test(value)) return calendar.parseCalendarDate(value, context);
101
- const normalized = value.includes("T") ? value : value.replace(" ", "T");
102
- const parsed = new Date(normalized);
103
- if (!Number.isNaN(parsed.getTime())) return parsed;
104
- const [year, month = "1", day = "1"] = value.split("-");
105
- return new Date(Number(year), Number(month) - 1, Number(day), 12);
106
- };
107
- const validDate = value => !Number.isNaN(value.getTime());
108
99
  const weekNumber = date => {
109
100
  const target = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
110
101
  const day = target.getUTCDay() || 7;
@@ -117,7 +108,6 @@ const zonedWeekNumber = (date, context) => {
117
108
  const [year = "1970", month = "1", day = "1"] = calendar.formatDateKey(date, context).split("-");
118
109
  return weekNumber(new Date(Date.UTC(Number(year), Number(month) - 1, Number(day))));
119
110
  };
120
- const formatTime = (date, context) => calendar.formatTime(date, context);
121
111
  const formatDay = (date, context) => date.toLocaleDateString(context?.locale ?? "en", {
122
112
  weekday: "short",
123
113
  day: "numeric",
@@ -196,7 +186,6 @@ const normalizeEvents = (events, context) => events.flatMap(event => {
196
186
  }
197
187
  return days;
198
188
  });
199
- const eventHref = (props, event) => props.getEventHref?.(event) ?? event.href;
200
189
  const moveEventTo = (event, target, allDay = false, context) => {
201
190
  const duration = Math.max(30 * 60 * 1000, event.sourceEndDate.getTime() - event.sourceStartDate.getTime());
202
191
  const start = allDay ? startOfDay(target, context) : new Date(target);
@@ -243,123 +232,6 @@ const timedEventLayouts = events => {
243
232
  groupEndDate: new Date(groupEnd)
244
233
  }));
245
234
  };
246
- const EventChip = props => {
247
- const calendarMessages = useCalendarMessages();
248
- const dateConfig = createMemo(() => ownerDateConfig(props.owner));
249
- const color = () => props.event.color ?? "blue";
250
- const selected = () => Boolean(props.owner.selectedEventId) && props.owner.selectedEventId === props.event.id;
251
- const style = () => props.event.colorHex ? {
252
- "--k2b-calendar-accent": props.event.colorHex
253
- } : undefined;
254
- const isInteractive = () => Boolean(props.owner.onEventActivate);
255
- const durationHours = () => (props.event.endDate.getTime() - props.event.startDate.getTime()) / 3_600_000;
256
- const short = () => Boolean(props.fill && !props.event.allDay && durationHours() < 0.75);
257
- const showTime = () => !props.event.allDay && !props.compact && durationHours() >= 0.75;
258
- const showLocation = () => Boolean(props.event.location && !props.compact && durationHours() >= 1.25);
259
- const showDescription = () => Boolean(props.event.description?.trim() && props.fill && !props.event.allDay && !props.compact && durationHours() >= 1.5);
260
- const timeLabel = () => `${formatTime(props.event.startDate, dateConfig())} - ${formatTime(props.event.endDate, dateConfig())}`;
261
- const ariaLabel = () => {
262
- const label = props.label ? props.label : props.event.allDay ? props.event.title : calendarMessages().calendarEventTime({
263
- title: props.event.title,
264
- start: formatTime(props.event.startDate, dateConfig()),
265
- end: formatTime(props.event.endDate, dateConfig())
266
- });
267
- return props.event.accessibleDetail ? `${label}, ${props.event.accessibleDetail}` : label;
268
- };
269
- const renderedEvent = () => props.owner.renderEvent?.(props.event, {
270
- compact: props.compact ?? false,
271
- fill: props.fill ?? false,
272
- start: props.event.startDate,
273
- end: props.event.endDate,
274
- allDay: props.event.allDay ?? false,
275
- durationHours: durationHours(),
276
- timeLabel: timeLabel(),
277
- leadingTime: props.leadingTime
278
- });
279
- const defaultContent = [_$createComponent(Show, {
280
- get when() {
281
- return props.leadingTime;
282
- },
283
- get children() {
284
- return _$ssr(_tmpl$, _$escape(props.leadingTime));
285
- }
286
- }), _$ssr(_tmpl$3, _$escape(_$createComponent(Show, {
287
- get when() {
288
- return props.event.display === "marker";
289
- },
290
- get children() {
291
- return _$ssr(_tmpl$2);
292
- }
293
- })), _$escape(props.event.title)), _$createComponent(Show, {
294
- get when() {
295
- return showTime();
296
- },
297
- get children() {
298
- return _$ssr(_tmpl$4, _$escape(timeLabel()));
299
- }
300
- }), _$createComponent(Show, {
301
- get when() {
302
- return showLocation();
303
- },
304
- get children() {
305
- return _$ssr(_tmpl$4, _$escape(props.event.location));
306
- }
307
- }), _$createComponent(Show, {
308
- get when() {
309
- return showDescription();
310
- },
311
- get children() {
312
- return _$ssr(_tmpl$5, _$escape(props.event.description));
313
- }
314
- })];
315
- const content = () => [_$createComponent(Show, {
316
- get when() {
317
- return props.hintStart;
318
- },
319
- get children() {
320
- return _$ssr(_tmpl$6, _$escape(props.hintStart));
321
- }
322
- }), renderedEvent() ?? defaultContent, _$createComponent(Show, {
323
- get when() {
324
- return props.hintEnd;
325
- },
326
- get children() {
327
- return _$ssr(_tmpl$7, _$escape(props.hintEnd));
328
- }
329
- })];
330
- const isActionable = () => isInteractive() || Boolean(props.onMovePointerDown);
331
- let suppressClickUntil = 0;
332
- const onClick = event => {
333
- if (performance.now() < suppressClickUntil) {
334
- event.preventDefault();
335
- event.stopPropagation();
336
- return;
337
- }
338
- if (!props.owner.onEventActivate || props.owner.eventActivation === "double") return;
339
- event.preventDefault();
340
- event.stopPropagation();
341
- props.owner.onEventActivate(props.event);
342
- };
343
- const onDoubleClick = event => {
344
- if (!props.owner.onEventActivate || props.owner.eventActivation !== "double") return;
345
- event.preventDefault();
346
- event.stopPropagation();
347
- props.owner.onEventActivate(props.event);
348
- };
349
- const onButtonKeyDown = event => {
350
- if (!isInteractive() || event.key !== "Enter" && event.key !== " ") return;
351
- event.preventDefault();
352
- props.owner.onEventActivate?.(props.event);
353
- };
354
- const onPointerDown = event => {
355
- if (event.pointerType === "touch") return;
356
- if (props.onMovePointerDown) event.stopPropagation();
357
- props.onMovePointerDown?.(event, () => {
358
- suppressClickUntil = performance.now() + 400;
359
- });
360
- };
361
- return props.href ? _$ssr(_tmpl$8, _$ssrAttribute("href", _$escape(props.href, true), false), _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-continues-before", props.continuesBefore ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-continues-after", props.continuesAfter ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-bar", props.bar ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-interactive", isInteractive() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-display", _$escape(props.event.display, true), false) + _$ssrAttribute("data-space-item-id", _$escape(props.event.dataSpaceItemId, true), false), _$ssrStyle(style()), _$ssrAttribute("draggable", props.onMovePointerDown ? _$escape(false, true) : _$escape(undefined, true), false) + _$ssrAttribute("aria-label", _$escape(ariaLabel(), true), false), _$escape(content())) : isActionable() ? _$ssr(_tmpl$9, _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-continues-before", props.continuesBefore ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-continues-after", props.continuesAfter ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-bar", props.bar ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-display", _$escape(props.event.display, true), false), _$ssrStyle(style()), _$ssrAttribute("aria-label", _$escape(ariaLabel(), true), false), _$escape(content())) : _$ssr(_tmpl$0, _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-continues-before", props.continuesBefore ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-continues-after", props.continuesAfter ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-bar", props.bar ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-interactive", _$escape(undefined, true), false) + _$ssrAttribute("data-display", _$escape(props.event.display, true), false), _$ssrStyle(style()), _$ssrAttribute("aria-label", _$escape(ariaLabel(), true), false), _$escape(content()));
362
- };
363
235
  const slotInteractionProps = (owner, slot, suppressed, nativeControl = false) => {
364
236
  const isSlotChild = event => {
365
237
  if (!(event.target instanceof Element)) return false;
@@ -388,12 +260,20 @@ const slotInteractionProps = (owner, slot, suppressed, nativeControl = false) =>
388
260
  }
389
261
  };
390
262
  };
263
+ const plainClick = event => !event.defaultPrevented && event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
264
+
391
265
  /** A real anchor is the baseline; the optional handler only enhances it after hydration. */
392
266
  const CalendarNavigationLink = props => {
393
267
  const preload = () => props.owner.onPrefetch?.(props.href);
268
+ const intercepted = event => {
269
+ if (!props.intercept || !plainClick(event) || !props.intercept()) return false;
270
+ event.preventDefault();
271
+ return true;
272
+ };
394
273
  const navigateHref = event => {
274
+ if (intercepted(event)) return;
395
275
  const anchor = event.currentTarget;
396
- if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || anchor.target && anchor.target !== "_self" || anchor.hasAttribute("download") || new URL(anchor.href).origin !== window.location.origin) {
276
+ if (!plainClick(event) || anchor.target && anchor.target !== "_self" || anchor.hasAttribute("download") || new URL(anchor.href).origin !== window.location.origin) {
397
277
  return;
398
278
  }
399
279
  event.preventDefault();
@@ -411,6 +291,7 @@ const CalendarNavigationLink = props => {
411
291
  get onNavigate() {
412
292
  return props.owner.onNavigate;
413
293
  },
294
+ onClick: event => void intercepted(event),
414
295
  onPointerEnter: preload,
415
296
  onFocus: preload,
416
297
  get children() {
@@ -441,7 +322,7 @@ const CalendarViewLinks = props => {
441
322
  refs[event.key === "Home" ? 0 : props.options.length - 1]?.click();
442
323
  }
443
324
  };
444
- return _$ssr(_tmpl$1, _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarView, true), false), _$escape(_$createComponent(For, {
325
+ return _$ssr(_tmpl$, _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarView, true), false), _$escape(_$createComponent(For, {
445
326
  get each() {
446
327
  return props.options;
447
328
  },
@@ -502,12 +383,62 @@ const openViewAt = (owner, date, view) => {
502
383
  owner.onViewChange?.(view);
503
384
  owner.onDateChange?.(date, view);
504
385
  };
386
+
387
+ /** What the header reads from the active view beyond the props: the days a day or week view shows, and its moves. */
388
+
389
+ const dayTitleOptions = {
390
+ weekday: "short",
391
+ day: "numeric",
392
+ month: "short",
393
+ year: "numeric"
394
+ };
395
+ const weekTitleOptions = {
396
+ day: "numeric",
397
+ month: "short",
398
+ year: "numeric"
399
+ };
400
+
401
+ /** Where today lies from the shown day or week before its view measured: the arrow of the Today button, or nothing. */
402
+ const todayDirectionOf = (view, date, context) => {
403
+ const today = calendar.formatDateKey(new Date(), context);
404
+ if (view === "week") {
405
+ const start = calendar.formatDateKey(calendar.startOfWeek(date, context), context);
406
+ const end = calendar.formatDateKey(calendar.addDays(calendar.startOfWeek(date, context), 6, context), context);
407
+ return today < start ? "left" : today > end ? "right" : "";
408
+ }
409
+ const shown = calendar.formatDateKey(date, context);
410
+ return today < shown ? "up" : today > shown ? "down" : "";
411
+ };
505
412
  const CalendarHeader = props => {
506
413
  const calendarMessages = useCalendarMessages();
507
414
  const dateConfig = () => ownerDateConfig(props.owner);
508
- const previous = () => adjacentCalendarDate(props.date, props.view, -1, dateConfig());
509
- const next = () => adjacentCalendarDate(props.date, props.view, 1, dateConfig());
415
+ const timeView = () => props.nav.timeView();
416
+ const parseKey = key => calendar.parseCalendarDate(key, dateConfig());
417
+ /** The date the header pages from: the first day a day or week view shows, else the date. */
418
+ const base = () => {
419
+ const shown = timeView()?.visibleKeys().first;
420
+ return shown ? parseKey(shown) : props.date;
421
+ };
422
+ const previous = () => adjacentCalendarDate(base(), props.view, -1, dateConfig());
423
+ const next = () => adjacentCalendarDate(base(), props.view, 1, dateConfig());
424
+ /** The day view's title, such as "Fri, Oct 9, 2026" or "Fr, 9. Okt 2026". */
425
+ const formatDayTitle = date => compactGermanDate(new Intl.DateTimeFormat(dateConfig().locale ?? "en", {
426
+ ...dayTitleOptions,
427
+ timeZone: dateConfig().timeZone
428
+ }).format(date), dateConfig().locale, true);
429
+ const formatRange = (from, to) => compactGermanDate(new Intl.DateTimeFormat(dateConfig().locale ?? "en", {
430
+ ...weekTitleOptions,
431
+ timeZone: dateConfig().timeZone
432
+ }).formatRange(from, to), dateConfig().locale);
433
+ /** The day and week views with `dayHours` name the days they show, also on the server before they measured. */
434
+ const timeMode = () => Boolean(props.owner.dayHours) && (props.view === "day" || props.view === "week");
510
435
  const title = () => {
436
+ const shown = timeView()?.visibleKeys();
437
+ if (timeMode() && props.view === "day") return formatDayTitle(shown ? parseKey(shown.first) : props.date);
438
+ if (timeMode()) {
439
+ const start = shown ? parseKey(shown.first) : calendar.startOfWeek(props.date, dateConfig());
440
+ return formatRange(start, shown ? parseKey(shown.last) : calendar.addDays(start, 6, dateConfig()));
441
+ }
511
442
  if (props.view === "year") return new Intl.DateTimeFormat(dateConfig().locale ?? "en", {
512
443
  year: "numeric",
513
444
  timeZone: dateConfig().timeZone
@@ -523,8 +454,8 @@ const CalendarHeader = props => {
523
454
  return formatMonth(props.date, dateConfig());
524
455
  };
525
456
  /**
526
- * The titles this view can show around the current date: the months of the year, the weeks of the month, or a day
527
- * of each weekday in every month. Their widest one sets the title's width.
457
+ * The titles this view can show around the current date: the months of the year, the weeks of the month and across
458
+ * each month boundary, or a day of each weekday in every month. Their widest one sets the title's width.
528
459
  */
529
460
  const titleWidths = createMemo(() => {
530
461
  const context = dateConfig();
@@ -537,12 +468,22 @@ const CalendarHeader = props => {
537
468
  }, (_, month) => formatMonth(zonedMonthDate(year, month, context), context));
538
469
  if (props.view === "week") {
539
470
  const first = calendar.startOfWeek(calendar.startOfMonth(props.date, context), context);
540
- return Array.from({
471
+ const weeks = Array.from({
541
472
  length: 6
542
473
  }, (_, week) => {
543
474
  const start = calendar.addDays(first, week * 7, context);
475
+ if (timeMode()) return formatRange(start, calendar.addDays(start, 6, context));
544
476
  return `${formatDay(start, context)} - ${formatDay(calendar.addDays(start, 6, context), context)}`;
545
477
  });
478
+ if (timeMode()) {
479
+ return [...weeks, ...Array.from({
480
+ length: 12
481
+ }, (_, month) => {
482
+ const day28 = calendar.addDays(zonedMonthDate(year, month, context), 27, context);
483
+ return formatRange(day28, calendar.addDays(day28, 6, context));
484
+ })];
485
+ }
486
+ return weeks;
546
487
  }
547
488
  return Array.from({
548
489
  length: 12
@@ -550,7 +491,7 @@ const CalendarHeader = props => {
550
491
  const first = zonedMonthDate(year, month, context);
551
492
  return Array.from({
552
493
  length: 7
553
- }, (_, offset) => calendar.addDays(first, 21 + offset, context).toLocaleDateString(context.locale ?? "en", {
494
+ }, (_, offset) => timeMode() ? formatDayTitle(calendar.addDays(first, 21 + offset, context)) : calendar.addDays(first, 21 + offset, context).toLocaleDateString(context.locale ?? "en", {
554
495
  weekday: "long",
555
496
  month: "long",
556
497
  day: "numeric",
@@ -574,49 +515,82 @@ const CalendarHeader = props => {
574
515
  const href = props.owner.getViewHref?.(view);
575
516
  if (href) window.location.href = href;
576
517
  };
577
- const navButton = (date, icon, label) => {
518
+ const navButton = (date, icon, label, direction) => {
578
519
  const href = props.owner.getDateHref?.(date, props.view);
520
+ const step = () => timeView()?.step(direction) ?? false;
521
+ const title = props.nav.commands().length > 0 ? `${label} (${direction > 0 ? "J" : "K"})` : label;
579
522
  return (props.owner.onNavigateHref || props.owner.onNavigate) && href ? _$createComponent(CalendarNavigationLink, {
580
523
  get owner() {
581
524
  return props.owner;
582
525
  },
583
526
  href: href,
527
+ intercept: step,
584
528
  anchorProps: {
585
529
  "aria-label": label,
586
- title: label,
530
+ title,
587
531
  class: "k2b-calendar-header__nav-button"
588
532
  },
589
533
  get children() {
590
- return _$ssr(_tmpl$10, `ti ${_$escape(icon, true)}`);
534
+ return _$ssr(_tmpl$2, `ti ${_$escape(icon, true)}`);
591
535
  }
592
- }) : props.owner.onDateChange ? _$ssr(_tmpl$11, _$ssrAttribute("aria-label", _$escape(label, true), false), `ti ${_$escape(icon, true)}`) : _$createComponent(CalendarNavigationLink, {
536
+ }) : props.owner.onDateChange ? _$ssr(_tmpl$3, _$ssrAttribute("aria-label", _$escape(label, true), false) + _$ssrAttribute("title", _$escape(title, true), false), `ti ${_$escape(icon, true)}`) : _$createComponent(CalendarNavigationLink, {
593
537
  get owner() {
594
538
  return props.owner;
595
539
  },
596
540
  href: href ?? "#",
541
+ intercept: step,
597
542
  anchorProps: {
598
543
  "aria-label": label,
599
- title: label,
544
+ title,
600
545
  class: "k2b-calendar-header__nav-button"
601
546
  },
602
547
  get children() {
603
- return _$ssr(_tmpl$10, `ti ${_$escape(icon, true)}`);
548
+ return _$ssr(_tmpl$2, `ti ${_$escape(icon, true)}`);
604
549
  }
605
550
  });
606
551
  };
552
+ /**
553
+ * In the day and week views that scroll through their days, Today points where today lies, or shows a calm dot while
554
+ * it is on screen; the icon keeps its place either way. The other views name their period in the title.
555
+ */
556
+ const direction = () => timeMode() ? (timeView()?.todayDirection() ?? todayDirectionOf(String(props.view), props.date, dateConfig())) || "here" : undefined;
557
+ /** One arrow that the stylesheet turns toward today, or the dot while today shows. */
558
+ const todayIcon = () => _$createComponent(Show, {
559
+ get when() {
560
+ return direction();
561
+ },
562
+ children: current => _$createComponent(Show, {
563
+ get when() {
564
+ return current() !== "here";
565
+ },
566
+ get fallback() {
567
+ return _$ssr(_tmpl$5);
568
+ },
569
+ get children() {
570
+ return _$ssr(_tmpl$4);
571
+ }
572
+ })
573
+ });
607
574
  const todayButton = () => {
608
575
  const today = calendar.today(dateConfig());
609
576
  const href = props.owner.getDateHref?.(today, props.view);
610
- const label = _$ssr(_tmpl$12, _$escape(props.labels.today));
577
+ const intercept = () => timeView()?.today() ?? false;
578
+ const title = () => props.nav.commands().length > 0 ? `${props.labels.today} (H)` : undefined;
579
+ const label = [todayIcon(), _$ssr(_tmpl$6, _$escape(props.labels.today))];
611
580
  return (props.owner.onNavigateHref || props.owner.onNavigate) && href ? _$createComponent(CalendarNavigationLink, {
612
581
  get owner() {
613
582
  return props.owner;
614
583
  },
615
584
  href: href,
616
- anchorProps: {
617
- class: "k2b-button k2b-calendar-header__today",
618
- "data-size": "sm",
619
- "data-variant": "input"
585
+ intercept: intercept,
586
+ get anchorProps() {
587
+ return {
588
+ class: "k2b-button k2b-calendar-header__today",
589
+ "data-size": "sm",
590
+ "data-variant": "input",
591
+ "data-direction": direction(),
592
+ title: title()
593
+ };
620
594
  },
621
595
  children: label
622
596
  }) : props.owner.onDateChange ? _$createComponent(Button, {
@@ -624,19 +598,32 @@ const CalendarHeader = props => {
624
598
  variant: "input",
625
599
  size: "sm",
626
600
  "class": "k2b-calendar-header__today",
627
- onClick: () => goDate(today),
601
+ get ["data-direction"]() {
602
+ return direction();
603
+ },
604
+ get title() {
605
+ return title();
606
+ },
607
+ onClick: () => {
608
+ if (!intercept()) goDate(today);
609
+ },
628
610
  get children() {
629
- return props.labels.today;
611
+ return [todayIcon(), props.labels.today];
630
612
  }
631
613
  }) : _$createComponent(CalendarNavigationLink, {
632
614
  get owner() {
633
615
  return props.owner;
634
616
  },
635
617
  href: href ?? "#",
636
- anchorProps: {
637
- class: "k2b-button k2b-calendar-header__today",
638
- "data-size": "sm",
639
- "data-variant": "input"
618
+ intercept: intercept,
619
+ get anchorProps() {
620
+ return {
621
+ class: "k2b-button k2b-calendar-header__today",
622
+ "data-size": "sm",
623
+ "data-variant": "input",
624
+ "data-direction": direction(),
625
+ title: title()
626
+ };
640
627
  },
641
628
  children: label
642
629
  });
@@ -654,17 +641,17 @@ const CalendarHeader = props => {
654
641
  value: "year",
655
642
  label: props.labels.year
656
643
  }].filter(option => !props.owner.views || props.owner.views.includes(option.value)), ...(props.owner.customViews ?? [])]);
657
- return _$ssr(_tmpl$15, _$escape(navButton(previous(), "ti-chevron-left", props.labels.previous)), _$escape(navButton(next(), "ti-chevron-right", props.labels.next)), _$escape(title()), _$escape(_$createComponent(For, {
644
+ return _$ssr(_tmpl$0, _$escape(navButton(previous(), "ti-chevron-left", props.labels.previous, -1)), _$escape(navButton(next(), "ti-chevron-right", props.labels.next, 1)), _$escape(title()), _$escape(_$createComponent(For, {
658
645
  get each() {
659
646
  return titleWidths();
660
647
  },
661
- children: candidate => _$ssr(_tmpl$16, _$escape(candidate))
648
+ children: candidate => _$ssr(_tmpl$1, _$escape(candidate))
662
649
  })), _$escape(_$createComponent(Show, {
663
650
  get when() {
664
651
  return props.owner.toolbarContent;
665
652
  },
666
653
  get children() {
667
- return _$ssr(_tmpl$13, _$escape(props.owner.toolbarContent));
654
+ return _$ssr(_tmpl$7, _$escape(props.owner.toolbarContent));
668
655
  }
669
656
  })), _$escape(todayButton()), _$escape(_$createComponent(Show, {
670
657
  get when() {
@@ -672,6 +659,7 @@ const CalendarHeader = props => {
672
659
  },
673
660
  get fallback() {
674
661
  return _$createComponent(SegmentedControl, {
662
+ "class": "k2b-calendar-view-switcher",
675
663
  value: () => props.view === "mobile-month" ? "month" : props.view,
676
664
  onValueChange: goView,
677
665
  get ariaLabel() {
@@ -699,11 +687,18 @@ const CalendarHeader = props => {
699
687
  });
700
688
  }
701
689
  })), _$escape(props.owner.toolbarActions), _$escape(_$createComponent(Show, {
690
+ get when() {
691
+ return props.nav.commands().length > 0;
692
+ },
693
+ get children() {
694
+ return _$ssr(_tmpl$8, _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarShortcuts, true), false) + _$ssrAttribute("title", _$escape(calendarMessages().calendarShortcuts, true), false));
695
+ }
696
+ })), _$escape(_$createComponent(Show, {
702
697
  get when() {
703
698
  return props.owner.navigationPending;
704
699
  },
705
700
  get children() {
706
- return _$ssr(_tmpl$14);
701
+ return _$ssr(_tmpl$9);
707
702
  }
708
703
  })));
709
704
  };
@@ -763,28 +758,28 @@ const MonthPickerView = props => {
763
758
  });
764
759
  };
765
760
  onCleanup(() => cancelInteraction?.());
766
- return _$ssr(_tmpl$18, _$ssrStyleProperty("grid-template-rows:", `auto repeat(${_$escape(weeks().length, true)}, ${props.compact ? "minmax(2.75rem, auto)" : "minmax(5rem, 1fr)"})`), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
761
+ return _$ssr(_tmpl$11, _$ssrStyleProperty("grid-template-rows:", `auto repeat(${_$escape(weeks().length, true)}, ${props.compact ? "minmax(2.75rem, auto)" : "minmax(5rem, 1fr)"})`), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
767
762
  get when() {
768
763
  return props.owner.withWeekNumbers;
769
764
  },
770
765
  get children() {
771
- return _$ssr(_tmpl$17, _$escape(calendarMessages().weekShort));
766
+ return _$ssr(_tmpl$10, _$escape(calendarMessages().weekShort));
772
767
  }
773
768
  })), _$escape(_$createComponent(For, {
774
769
  get each() {
775
770
  return weekdays();
776
771
  },
777
- children: day => _$ssr(_tmpl$17, _$escape(day))
772
+ children: day => _$ssr(_tmpl$10, _$escape(day))
778
773
  })), _$escape(_$createComponent(For, {
779
774
  get each() {
780
775
  return weeks();
781
776
  },
782
- children: week => _$ssr(_tmpl$20, _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
777
+ children: week => _$ssr(_tmpl$13, _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
783
778
  get when() {
784
779
  return props.owner.withWeekNumbers;
785
780
  },
786
781
  get children() {
787
- return _$ssr(_tmpl$19, _$escape(zonedWeekNumber(week[0], dateConfig())));
782
+ return _$ssr(_tmpl$12, _$escape(zonedWeekNumber(week[0], dateConfig())));
788
783
  }
789
784
  })), _$escape(_$createComponent(For, {
790
785
  each: week,
@@ -813,7 +808,7 @@ const MonthPickerView = props => {
813
808
  hiddenCount: Math.max(0, candidates.length - visibleLimit)
814
809
  };
815
810
  });
816
- return _$ssr(_tmpl$22, _$ssrAttribute("data-calendar-day-key", _$escape(dayKey, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-drop-preview", movePreview()?.start && calendar.formatDateKey(movePreview().start, dateConfig()) === dayKey ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
811
+ return _$ssr(_tmpl$15, _$ssrAttribute("data-calendar-day-key", _$escape(dayKey, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-drop-preview", movePreview()?.start && calendar.formatDateKey(movePreview().start, dateConfig()) === dayKey ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
817
812
  get when() {
818
813
  return props.owner.onSlotActivate;
819
814
  },
@@ -862,7 +857,7 @@ const MonthPickerView = props => {
862
857
  return props.owner.onSlotActivate && href;
863
858
  },
864
859
  get fallback() {
865
- return _$ssr(_tmpl$23, _$ssrAttribute("data-today", isToday ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false), _$escape(calendar.formatDayNumber(day, dateConfig())));
860
+ return _$ssr(_tmpl$16, _$ssrAttribute("data-today", isToday ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false), _$escape(calendar.formatDayNumber(day, dateConfig())));
866
861
  },
867
862
  children: dayHref => _$createComponent(CalendarNavigationLink, {
868
863
  get owner() {
@@ -887,18 +882,18 @@ const MonthPickerView = props => {
887
882
  })
888
883
  })), _$escape(_$createComponent(Show, {
889
884
  when: dayBadge,
890
- children: badge => _$ssr(_tmpl$24, _$escape(_$createComponent(Show, {
885
+ children: badge => _$ssr(_tmpl$17, _$escape(_$createComponent(Show, {
891
886
  get when() {
892
887
  return badge().icon;
893
888
  },
894
- children: icon => _$ssr(_tmpl$10, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
889
+ children: icon => _$ssr(_tmpl$2, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
895
890
  })), _$escape(badge().label))
896
891
  })), _$escape(_$createComponent(Show, {
897
892
  get when() {
898
893
  return eventStack().preview;
899
894
  },
900
895
  get children() {
901
- return _$ssr(_tmpl$21, _$escape(props.events.find(event => event.id === eventStack().preview.id)?.title ?? calendarMessages().moveEvent));
896
+ return _$ssr(_tmpl$14, _$escape(props.events.find(event => event.id === eventStack().preview.id)?.title ?? calendarMessages().moveEvent));
902
897
  }
903
898
  })), _$escape(_$createComponent(For, {
904
899
  get each() {
@@ -944,7 +939,7 @@ const MonthPickerView = props => {
944
939
  get each() {
945
940
  return events.slice(0, 4);
946
941
  },
947
- children: event => _$ssr(_tmpl$25, _$ssrAttribute("data-color", event.colorHex ? _$escape(undefined, true) : _$escape(event.color ?? "blue", true), false), _$ssrStyle(event.colorHex ? {
942
+ children: event => _$ssr(_tmpl$18, _$ssrAttribute("data-color", event.colorHex ? _$escape(undefined, true) : _$escape(event.color ?? "blue", true), false), _$ssrStyle(event.colorHex ? {
948
943
  "background-color": event.colorHex
949
944
  } : undefined))
950
945
  })));
@@ -955,6 +950,8 @@ const MonthPickerView = props => {
955
950
 
956
951
  /** One entry of the month grid: its whole range, and the days it covers as `YYYY-MM-DD` keys. */
957
952
 
953
+ /** What the calendar's controller asks of the month view. */
954
+
958
955
  /** Lane height and gap of the month entries, in rem; the stylesheet reads both from the grid's custom properties. */
959
956
  const MONTH_LANE_REM = 1.25;
960
957
  const MONTH_LANE_GAP_REM = 0.125;
@@ -1002,34 +999,6 @@ const monthItems = events => {
1002
999
  for (const item of items.values()) item.bar = item.firstKey !== item.lastKey || Boolean(item.event.allDay && item.event.display !== "marker");
1003
1000
  return [...items.values()].sort((left, right) => Number(right.bar) - Number(left.bar) || left.event.sourceStartDate.getTime() - right.event.sourceStartDate.getTime() || left.event.title.localeCompare(right.event.title));
1004
1001
  };
1005
-
1006
- /** Places a calendar popover below its anchor when there is room and above it otherwise, inside the viewport. */
1007
- const placeCalendarPopover = (anchor, popover) => {
1008
- const margin = 8;
1009
- const gap = 4;
1010
- const rect = anchor.getBoundingClientRect();
1011
- const width = Math.min(popover.offsetWidth || 288, window.innerWidth - margin * 2);
1012
- const height = popover.offsetHeight;
1013
- const left = Math.max(margin, Math.min(rect.left, window.innerWidth - width - margin));
1014
- const roomBelow = window.innerHeight - rect.bottom - gap - margin;
1015
- const above = height > roomBelow && rect.top - gap - margin > roomBelow;
1016
- const top = above ? Math.max(margin, rect.top - height - gap) : Math.min(rect.bottom + gap, window.innerHeight - height - margin);
1017
- popover.style.left = `${left}px`;
1018
- popover.style.top = `${Math.max(margin, top)}px`;
1019
- };
1020
- let measureContext;
1021
- /** The width of a text in a font, from a canvas, so a bar can tell whether its title leaves room for a date hint. */
1022
- const textWidth = (text, font) => {
1023
- measureContext ??= typeof document === "undefined" ? null : document.createElement("canvas").getContext("2d");
1024
- if (!measureContext) return Number.POSITIVE_INFINITY;
1025
- measureContext.font = font;
1026
- return measureContext.measureText(text).width;
1027
- };
1028
-
1029
- /** Follows a calendar link the way the calendar's own links do: through the host's navigation when it has one. */
1030
- const followCalendarHref = (owner, href) => {
1031
- if (owner.onNavigateHref) owner.onNavigateHref(href);else window.location.assign(href);
1032
- };
1033
1002
  const PRINTABLE_KEY = /^.$/u;
1034
1003
 
1035
1004
  /**
@@ -1262,6 +1231,25 @@ const MonthView = props => {
1262
1231
  })) return;
1263
1232
  if (props.owner.onSlotActivate) props.owner.onSlotActivate(rangeOf(range));
1264
1233
  };
1234
+ onMount(() => props.register?.({
1235
+ quickCreate: create => {
1236
+ const range = selection() ?? {
1237
+ first: rovingKey(),
1238
+ last: rovingKey()
1239
+ };
1240
+ select(range.first, range.last);
1241
+ if (!openCreate(range, {
1242
+ active: true,
1243
+ create
1244
+ })) props.owner.onSlotActivate?.(rangeOf(range));
1245
+ },
1246
+ createTarget: () => rangeOf(selection() ?? {
1247
+ first: rovingKey(),
1248
+ last: rovingKey()
1249
+ }),
1250
+ typing: () => popover()?.kind === "create" && !createActive()
1251
+ }));
1252
+ onCleanup(() => props.register?.(null));
1265
1253
  const openDayList = key => {
1266
1254
  const anchor = cells.get(key);
1267
1255
  if (!anchor) return;
@@ -1582,18 +1570,18 @@ const MonthView = props => {
1582
1570
  if (linkedItem() === item.key) setLinkedItem("");
1583
1571
  }
1584
1572
  });
1585
- const grid = () => _$ssr(_tmpl$27, _$ssrAttribute("aria-label", _$escape(formatMonth(props.date, dateConfig()), true), false), _$ssrStyleProperty("grid-template-rows:", `auto repeat(${_$escape(weeks().length, true)}, minmax(5rem, 1fr))`) + _$ssrStyleProperty(";--k2b-calendar-lane:", "1.25rem") + _$ssrStyleProperty(";--k2b-calendar-lane-gap:", "0.125rem"), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
1573
+ const grid = () => _$ssr(_tmpl$20, _$ssrAttribute("aria-label", _$escape(formatMonth(props.date, dateConfig()), true), false), _$ssrStyleProperty("grid-template-rows:", `auto repeat(${_$escape(weeks().length, true)}, minmax(5rem, 1fr))`) + _$ssrStyleProperty(";--k2b-calendar-lane:", "1.25rem") + _$ssrStyleProperty(";--k2b-calendar-lane-gap:", "0.125rem"), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
1586
1574
  get when() {
1587
1575
  return props.owner.withWeekNumbers;
1588
1576
  },
1589
1577
  get children() {
1590
- return _$ssr(_tmpl$26, _$escape(calendarMessages().weekShort));
1578
+ return _$ssr(_tmpl$19, _$escape(calendarMessages().weekShort));
1591
1579
  }
1592
1580
  })), _$escape(_$createComponent(For, {
1593
1581
  get each() {
1594
1582
  return weekdays();
1595
1583
  },
1596
- children: (day, index) => _$ssr(_tmpl$28, _$ssrAttribute("data-weekend", index() > 4 ? "true" : _$escape(undefined, true), false), _$escape(day))
1584
+ children: (day, index) => _$ssr(_tmpl$21, _$ssrAttribute("data-weekend", index() > 4 ? "true" : _$escape(undefined, true), false), _$escape(day))
1597
1585
  })), _$escape(_$createComponent(For, {
1598
1586
  get each() {
1599
1587
  return weeks();
@@ -1605,12 +1593,12 @@ const MonthView = props => {
1605
1593
  }, capacities()[weekIndex()] ?? MONTH_DEFAULT_LANES));
1606
1594
  const weekHref = () => viewHref(week[0].key, "week");
1607
1595
  const weekNumber = () => zonedWeekNumber(week[0].day, dateConfig());
1608
- return _$ssr(_tmpl$30, _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
1596
+ return _$ssr(_tmpl$23, _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
1609
1597
  get when() {
1610
1598
  return props.owner.withWeekNumbers;
1611
1599
  },
1612
1600
  get children() {
1613
- return _$ssr(_tmpl$29, _$escape(_$createComponent(Show, {
1601
+ return _$ssr(_tmpl$22, _$escape(_$createComponent(Show, {
1614
1602
  get when() {
1615
1603
  return weekHref();
1616
1604
  },
@@ -1623,7 +1611,7 @@ const MonthView = props => {
1623
1611
  return weekNumber();
1624
1612
  },
1625
1613
  get children() {
1626
- return _$ssr(_tmpl$31, _$ssrAttribute("title", _$escape(calendarMessages().calendarOpenWeekNumber({
1614
+ return _$ssr(_tmpl$24, _$ssrAttribute("title", _$escape(calendarMessages().calendarOpenWeekNumber({
1627
1615
  week: weekNumber()
1628
1616
  }), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarOpenWeekNumber({
1629
1617
  week: weekNumber()
@@ -1671,13 +1659,13 @@ const MonthView = props => {
1671
1659
  shown: [],
1672
1660
  hidden: 0
1673
1661
  };
1674
- return _$ssr(_tmpl$33, _$ssrAttribute("tabindex", rovingKey() === key ? 0 : -1, false) + _$ssrAttribute("aria-label", _$escape(label, true), false) + _$ssrAttribute("aria-selected", within(selection(), key) ? "true" : "false", false) + _$ssrAttribute("aria-current", key === todayKey() ? "date" : _$escape(undefined, true), false) + _$ssrAttribute("data-calendar-day-key", _$escape(key, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-weekend", column() > 4 ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-past", key < todayKey() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-selected", _$escape(selectionPart(key), true), false) + _$ssrAttribute("data-drop-preview", within(dropRange(), key) ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-today", key === todayKey() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false), _$escape(calendar.formatDayNumber(day, dateConfig())), _$escape(_$createComponent(Show, {
1662
+ return _$ssr(_tmpl$26, _$ssrAttribute("tabindex", rovingKey() === key ? 0 : -1, false) + _$ssrAttribute("aria-label", _$escape(label, true), false) + _$ssrAttribute("aria-selected", within(selection(), key) ? "true" : "false", false) + _$ssrAttribute("aria-current", key === todayKey() ? "date" : _$escape(undefined, true), false) + _$ssrAttribute("data-calendar-day-key", _$escape(key, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-weekend", column() > 4 ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-past", key < todayKey() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-selected", _$escape(selectionPart(key), true), false) + _$ssrAttribute("data-drop-preview", within(dropRange(), key) ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-today", key === todayKey() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false), _$escape(calendar.formatDayNumber(day, dateConfig())), _$escape(_$createComponent(Show, {
1675
1663
  when: dayBadge,
1676
- children: badge => _$ssr(_tmpl$24, _$escape(_$createComponent(Show, {
1664
+ children: badge => _$ssr(_tmpl$17, _$escape(_$createComponent(Show, {
1677
1665
  get when() {
1678
1666
  return badge().icon;
1679
1667
  },
1680
- children: icon => _$ssr(_tmpl$10, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
1668
+ children: icon => _$ssr(_tmpl$2, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
1681
1669
  })), _$escape(badge().label))
1682
1670
  })), _$escape(_$createComponent(For, {
1683
1671
  get each() {
@@ -1752,7 +1740,7 @@ const MonthView = props => {
1752
1740
  get each() {
1753
1741
  return cell().shown;
1754
1742
  },
1755
- children: (item, index) => _$ssr(_tmpl$34, _$ssrStyleProperty("--k2b-calendar-span:", "1") + _$ssrStyleProperty(";--k2b-calendar-row:", _$escape(String(cell().top + index()), true)), _$escape(_$createComponent(EventChip, {
1743
+ children: (item, index) => _$ssr(_tmpl$27, _$ssrStyleProperty("--k2b-calendar-span:", "1") + _$ssrStyleProperty(";--k2b-calendar-row:", _$escape(String(cell().top + index()), true)), _$escape(_$createComponent(EventChip, {
1756
1744
  get event() {
1757
1745
  return item.event;
1758
1746
  },
@@ -1778,7 +1766,7 @@ const MonthView = props => {
1778
1766
  return cell().hidden > 0;
1779
1767
  },
1780
1768
  get children() {
1781
- return _$ssr(_tmpl$32, _$ssrStyleProperty("--k2b-calendar-row:", _$escape(String(cell().top + cell().shown.length), true)), _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarMoreEventsOn({
1769
+ return _$ssr(_tmpl$25, _$ssrStyleProperty("--k2b-calendar-row:", _$escape(String(cell().top + cell().shown.length), true)), _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarMoreEventsOn({
1782
1770
  count: cell().hidden,
1783
1771
  label
1784
1772
  }), true), false), _$ssrAttribute("aria-expanded", (() => {
@@ -1798,19 +1786,19 @@ const MonthView = props => {
1798
1786
  const href = viewHref(dayKey, "day");
1799
1787
  // Read where it renders, so a refresh while the list is open updates it as it does the grid.
1800
1788
  const entries = () => dayEntries(dayKey);
1801
- return _$ssr(_tmpl$37, _$escape(dayLabel(day)), _$escape(_$createComponent(Show, {
1789
+ return _$ssr(_tmpl$30, _$escape(dayLabel(day)), _$escape(_$createComponent(Show, {
1802
1790
  get when() {
1803
1791
  return entries().length > 0;
1804
1792
  },
1805
1793
  get fallback() {
1806
- return _$ssr(_tmpl$38, _$escape(calendarMessages().calendarNothingPlanned));
1794
+ return _$ssr(_tmpl$31, _$escape(calendarMessages().calendarNothingPlanned));
1807
1795
  },
1808
1796
  get children() {
1809
- return _$ssr(_tmpl$35, _$escape(_$createComponent(For, {
1797
+ return _$ssr(_tmpl$28, _$escape(_$createComponent(For, {
1810
1798
  get each() {
1811
1799
  return entries();
1812
1800
  },
1813
- children: item => _$ssr(_tmpl$39, _$escape(_$createComponent(EventChip, {
1801
+ children: item => _$ssr(_tmpl$32, _$escape(_$createComponent(EventChip, {
1814
1802
  get event() {
1815
1803
  return item.event;
1816
1804
  },
@@ -1847,7 +1835,7 @@ const MonthView = props => {
1847
1835
  size: "sm",
1848
1836
  onClick: () => openView(dayKey, "day"),
1849
1837
  get children() {
1850
- return [_$ssr(_tmpl$40), calendarMessages().calendarOpenDay];
1838
+ return [_$ssr(_tmpl$33), calendarMessages().calendarOpenDay];
1851
1839
  }
1852
1840
  });
1853
1841
  }
@@ -1866,7 +1854,7 @@ const MonthView = props => {
1866
1854
  "data-size": "sm"
1867
1855
  },
1868
1856
  get children() {
1869
- return [_$ssr(_tmpl$40), calendarMessages().calendarOpenDay];
1857
+ return [_$ssr(_tmpl$33), calendarMessages().calendarOpenDay];
1870
1858
  }
1871
1859
  })
1872
1860
  })), _$escape(_$createComponent(Show, {
@@ -1888,7 +1876,7 @@ const MonthView = props => {
1888
1876
  });
1889
1877
  },
1890
1878
  get children() {
1891
- return [_$ssr(_tmpl$36), calendarMessages().calendarNewEvent];
1879
+ return [_$ssr(_tmpl$29), calendarMessages().calendarNewEvent];
1892
1880
  }
1893
1881
  });
1894
1882
  }
@@ -1917,7 +1905,7 @@ const MonthView = props => {
1917
1905
  }
1918
1906
  });
1919
1907
  }
1920
- }), _$ssr(_tmpl$41, _$ssrAttribute("aria-label", (() => {
1908
+ }), _$ssr(_tmpl$34, _$ssrAttribute("aria-label", (() => {
1921
1909
  const current = popover();
1922
1910
  if (current?.kind === "day") return dayLabel(parseKey(current.dayKey));
1923
1911
  return _$escape(calendarMessages().calendarQuickCreate, true);
@@ -2106,10 +2094,12 @@ const TimeGridView = props => {
2106
2094
  }
2107
2095
  return [...groups.values()];
2108
2096
  };
2097
+ // 12 rem per lane. The 40 rem grid is wider than one or two lanes, so only
2098
+ // three or more make the day scroll, and one lane fits beside a tablet drawer.
2109
2099
  const dayColumnMinWidth = layouts => {
2110
2100
  if (!isDayView()) return undefined;
2111
2101
  const lanes = Math.max(1, ...layouts.map(layout => layout.lanes));
2112
- return `${Math.max(32, lanes * 12)}rem`;
2102
+ return `${lanes * 12}rem`;
2113
2103
  };
2114
2104
  const laneStyle = layoutItem => {
2115
2105
  if (isDayView()) {
@@ -2145,7 +2135,7 @@ const TimeGridView = props => {
2145
2135
  });
2146
2136
  });
2147
2137
  });
2148
- return _$ssr(_tmpl$43, _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`), _$escape(_$createComponent(For, {
2138
+ return _$ssr(_tmpl$36, _$ssrAttribute("data-view", isDayView() ? "day" : "week", false), _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`), _$escape(_$createComponent(For, {
2149
2139
  get each() {
2150
2140
  return props.days;
2151
2141
  },
@@ -2163,13 +2153,13 @@ const TimeGridView = props => {
2163
2153
  class: "k2b-calendar-time-grid__day"
2164
2154
  },
2165
2155
  get children() {
2166
- return [_$ssr(_tmpl$44, _$ssrAttribute("data-today", today() ? "true" : _$escape(undefined, true), false), _$escape(formatDay(day, dateConfig()))), _$createComponent(Show, {
2156
+ return [_$ssr(_tmpl$37, _$ssrAttribute("data-today", today() ? "true" : _$escape(undefined, true), false), _$escape(formatDay(day, dateConfig()))), _$createComponent(Show, {
2167
2157
  when: dayBadge,
2168
- children: badge => _$ssr(_tmpl$45, _$escape(_$createComponent(Show, {
2158
+ children: badge => _$ssr(_tmpl$38, _$escape(_$createComponent(Show, {
2169
2159
  get when() {
2170
2160
  return badge().icon;
2171
2161
  },
2172
- children: icon => _$ssr(_tmpl$10, `k2b-calendar-time-grid__badge-icon ti ti-${_$escape(icon(), true)}`)
2162
+ children: icon => _$ssr(_tmpl$2, `k2b-calendar-time-grid__badge-icon ti ti-${_$escape(icon(), true)}`)
2173
2163
  })), _$escape(badge().label))
2174
2164
  })];
2175
2165
  }
@@ -2180,7 +2170,7 @@ const TimeGridView = props => {
2180
2170
  return !props.owner.hideAllDay;
2181
2171
  },
2182
2172
  get children() {
2183
- return _$ssr(_tmpl$42, _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`) + _$ssrStyleProperty(";max-height:", `${_$escape(props.owner.allDayMaxHeightRem ?? 7, true)}rem`), _$escape(props.labels.allDay), _$escape(_$createComponent(For, {
2173
+ return _$ssr(_tmpl$35, _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`) + _$ssrStyleProperty(";max-height:", `${_$escape(props.owner.allDayMaxHeightRem ?? 7, true)}rem`), _$escape(props.labels.allDay), _$escape(_$createComponent(For, {
2184
2174
  get each() {
2185
2175
  return props.days;
2186
2176
  },
@@ -2204,9 +2194,9 @@ const TimeGridView = props => {
2204
2194
  end: calendar.addDays(start, 1, dateConfig()),
2205
2195
  allDay: true
2206
2196
  };
2207
- }, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$46, _$escape(_$createComponent(For, {
2197
+ }, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$39, _$escape(_$createComponent(For, {
2208
2198
  each: previewAllDay,
2209
- children: event => _$ssr(_tmpl$21, _$escape(event.title))
2199
+ children: event => _$ssr(_tmpl$14, _$escape(event.title))
2210
2200
  })), _$escape(_$createComponent(For, {
2211
2201
  get each() {
2212
2202
  return allDay();
@@ -2235,7 +2225,7 @@ const TimeGridView = props => {
2235
2225
  get each() {
2236
2226
  return hours();
2237
2227
  },
2238
- children: hour => _$ssr(_tmpl$47, _$ssrAttribute("data-outside-business", hour < businessStartHour() || hour > businessEndHour() ? "true" : _$escape(undefined, true), false), _$escape(`${hour}`.padStart(2, "0")))
2228
+ children: hour => _$ssr(_tmpl$40, _$ssrAttribute("data-outside-business", hour < businessStartHour() || hour > businessEndHour() ? "true" : _$escape(undefined, true), false), _$escape(`${hour}`.padStart(2, "0")))
2239
2229
  })), _$escape(_$createComponent(For, {
2240
2230
  get each() {
2241
2231
  return props.days;
@@ -2243,12 +2233,12 @@ const TimeGridView = props => {
2243
2233
  children: day => {
2244
2234
  const dayKey = calendar.formatDateKey(day, dateConfig());
2245
2235
  const layouts = createMemo(() => timedEventLayouts(eventsByDay().get(dayKey)?.timed ?? []));
2246
- return _$ssr(_tmpl$49, _$ssrStyleProperty("min-width:", _$escape(dayColumnMinWidth(layouts()), true)) + _$ssrStyleProperty(";grid-template-rows:", `repeat(${_$escape(hours().length, true)}, minmax(4rem, 1fr))`), _$escape(_$createComponent(Show, {
2236
+ return _$ssr(_tmpl$42, _$ssrStyleProperty("min-width:", _$escape(dayColumnMinWidth(layouts()), true)) + _$ssrStyleProperty(";grid-template-rows:", `repeat(${_$escape(hours().length, true)}, minmax(4rem, 1fr))`), _$escape(_$createComponent(Show, {
2247
2237
  get when() {
2248
2238
  return currentTimeLine(day) !== null;
2249
2239
  },
2250
2240
  get children() {
2251
- return _$ssr(_tmpl$48, _$ssrStyleProperty("top:", `${_$escape(currentTimeLine(day) ?? 0, true)}%`));
2241
+ return _$ssr(_tmpl$41, _$ssrStyleProperty("top:", `${_$escape(currentTimeLine(day) ?? 0, true)}%`));
2252
2242
  }
2253
2243
  })), _$escape(_$createComponent(For, {
2254
2244
  get each() {
@@ -2277,12 +2267,12 @@ const TimeGridView = props => {
2277
2267
  children: event => {
2278
2268
  const layout = eventLayout(event);
2279
2269
  const short = event.endDate.getTime() - event.startDate.getTime() < 60 * 60_000;
2280
- return _$ssr(_tmpl$51, _$ssrAttribute("data-short", short ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$escape(_$createComponent(Show, {
2270
+ return _$ssr(_tmpl$44, _$ssrAttribute("data-short", short ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$escape(_$createComponent(Show, {
2281
2271
  get when() {
2282
2272
  return event.title;
2283
2273
  },
2284
2274
  get children() {
2285
- return _$ssr(_tmpl$50, _$escape(event.title));
2275
+ return _$ssr(_tmpl$43, _$escape(event.title));
2286
2276
  }
2287
2277
  })), _$escape(formatTime(event.startDate, dateConfig())), _$escape(formatTime(event.endDate, dateConfig())));
2288
2278
  }
@@ -2328,7 +2318,7 @@ const TimeGridView = props => {
2328
2318
  onCancel: clearInteraction
2329
2319
  });
2330
2320
  };
2331
- return _$ssr(_tmpl$53, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`) + _$ssrStyleProperty(";left:", _$escape(position.left, true)) + _$ssrStyleProperty(";width:", _$escape(position.width, true)) + _$ssrStyleProperty(";z-index:", _$escape(String(20 + layoutItem.lane), true)), _$escape(_$createComponent(EventChip, {
2321
+ return _$ssr(_tmpl$46, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`) + _$ssrStyleProperty(";left:", _$escape(position.left, true)) + _$ssrStyleProperty(";width:", _$escape(position.width, true)) + _$ssrStyleProperty(";z-index:", _$escape(String(20 + layoutItem.lane), true)), _$escape(_$createComponent(EventChip, {
2332
2322
  event: event,
2333
2323
  get owner() {
2334
2324
  return props.owner;
@@ -2348,7 +2338,7 @@ const TimeGridView = props => {
2348
2338
  return props.owner.onEventResize;
2349
2339
  },
2350
2340
  get children() {
2351
- return _$ssr(_tmpl$52, _$ssrAttribute("aria-label", _$escape(calendarMessages().resizeEvent, true), false));
2341
+ return _$ssr(_tmpl$45, _$ssrAttribute("aria-label", _$escape(calendarMessages().resizeEvent, true), false));
2352
2342
  }
2353
2343
  })));
2354
2344
  }
@@ -2360,14 +2350,14 @@ const TimeGridView = props => {
2360
2350
  const layout = timeRangeLayout(overflow.groupStartDate, overflow.groupEndDate);
2361
2351
  const key = `${dayKey}-${overflow.groupId}`;
2362
2352
  const hiddenTitle = () => overflow.hiddenEvents.map(event => `${formatTime(event.startDate, dateConfig())} ${event.title}`).join("\n");
2363
- return [_$ssr(_tmpl$54, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$ssrAttribute("title", _$escape(hiddenTitle(), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().hiddenOverlappingEvents({
2353
+ return [_$ssr(_tmpl$47, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$ssrAttribute("title", _$escape(hiddenTitle(), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().hiddenOverlappingEvents({
2364
2354
  count: overflow.hiddenEvents.length
2365
2355
  }), true), false), _$escape(overflow.hiddenEvents.length)), _$createComponent(Show, {
2366
2356
  get when() {
2367
2357
  return expandedOverflow() === key;
2368
2358
  },
2369
2359
  get children() {
2370
- return _$ssr(_tmpl$55, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`), _$escape(formatTime(overflow.groupStartDate, dateConfig())), _$escape(formatTime(overflow.groupEndDate, dateConfig())), _$escape(_$createComponent(For, {
2360
+ return _$ssr(_tmpl$48, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`), _$escape(formatTime(overflow.groupStartDate, dateConfig())), _$escape(formatTime(overflow.groupEndDate, dateConfig())), _$escape(_$createComponent(For, {
2371
2361
  get each() {
2372
2362
  return overflow.hiddenEvents;
2373
2363
  },
@@ -2426,11 +2416,11 @@ const YearView = props => {
2426
2416
  };
2427
2417
  });
2428
2418
  });
2429
- return _$ssr(_tmpl$56, _$escape(_$createComponent(For, {
2419
+ return _$ssr(_tmpl$49, _$escape(_$createComponent(For, {
2430
2420
  get each() {
2431
2421
  return months();
2432
2422
  },
2433
- children: month => _$ssr(_tmpl$57, _$escape(month.label), _$escape(_$createComponent(For, {
2423
+ children: month => _$ssr(_tmpl$50, _$escape(month.label), _$escape(_$createComponent(For, {
2434
2424
  get each() {
2435
2425
  return month.days;
2436
2426
  },
@@ -2453,7 +2443,7 @@ const YearView = props => {
2453
2443
  get when() {
2454
2444
  return day.events[0];
2455
2445
  },
2456
- children: event => _$ssr(_tmpl$58, _$ssrAttribute("data-color", event().colorHex ? _$escape(undefined, true) : _$escape(event().color ?? "blue", true), false) + _$ssrAttribute("data-today", day.isToday ? "true" : _$escape(undefined, true), false), _$ssrStyle(event().colorHex ? {
2446
+ children: event => _$ssr(_tmpl$51, _$ssrAttribute("data-color", event().colorHex ? _$escape(undefined, true) : _$escape(event().color ?? "blue", true), false) + _$ssrAttribute("data-today", day.isToday ? "true" : _$escape(undefined, true), false), _$ssrStyle(event().colorHex ? {
2457
2447
  "background-color": day.isToday ? "white" : event().colorHex
2458
2448
  } : undefined))
2459
2449
  })];
@@ -2466,7 +2456,7 @@ const MobileMonthView = props => {
2466
2456
  const dateConfig = createMemo(() => ownerDateConfig(props.owner));
2467
2457
  const selectedDateKey = createMemo(() => calendar.formatDateKey(props.selectedDate, dateConfig()));
2468
2458
  const selectedEvents = createMemo(() => props.events.filter(event => event.dayKey === selectedDateKey()));
2469
- return _$ssr(_tmpl$60, _$escape(_$createComponent(MonthPickerView, {
2459
+ return _$ssr(_tmpl$53, _$escape(_$createComponent(MonthPickerView, {
2470
2460
  get owner() {
2471
2461
  return {
2472
2462
  ...props.owner,
@@ -2496,10 +2486,10 @@ const MobileMonthView = props => {
2496
2486
  return selectedEvents().length > 0;
2497
2487
  },
2498
2488
  get fallback() {
2499
- return _$ssr(_tmpl$61, _$escape(props.labels.noEvents));
2489
+ return _$ssr(_tmpl$54, _$escape(props.labels.noEvents));
2500
2490
  },
2501
2491
  get children() {
2502
- return _$ssr(_tmpl$59, _$escape(_$createComponent(For, {
2492
+ return _$ssr(_tmpl$52, _$escape(_$createComponent(For, {
2503
2493
  get each() {
2504
2494
  return selectedEvents();
2505
2495
  },
@@ -2516,7 +2506,7 @@ const MobileMonthView = props => {
2516
2506
  }
2517
2507
  })));
2518
2508
  };
2519
- const CalendarBody = props => _$ssr(_tmpl$62, _$escape(props.children));
2509
+ const CalendarBody = props => _$ssr(_tmpl$55, _$escape(props.children));
2520
2510
  const CalendarRoot = props => {
2521
2511
  const messages = useUiMessages();
2522
2512
  const calendarMessages = useCalendarMessages();
@@ -2566,7 +2556,181 @@ const CalendarRoot = props => {
2566
2556
  document.removeEventListener("visibilitychange", updateNow);
2567
2557
  });
2568
2558
  });
2569
- return _$ssr(_tmpl$63, `k2b-content-calendar ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("aria-busy", props.navigationPending ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(CalendarHeader, {
2559
+
2560
+ // The day and week views with `dayHours` scroll through their days; the header and the commands ask them first.
2561
+ const [timeView, setTimeView] = createSignal(null);
2562
+ const [monthCreate, setMonthCreate] = createSignal(null);
2563
+ const timeMode = () => Boolean(props.dayHours) && (view() === "day" || view() === "week");
2564
+ const parseKey = key => calendar.parseCalendarDate(key, dateConfig());
2565
+ /** The first shown day of a day or week view, or the selected day of the month view, for the other views. */
2566
+ const shownDay = () => {
2567
+ const first = timeView()?.visibleKeys().first;
2568
+ if (first) return parseKey(first);
2569
+ return view() === "month" ? focusDay() : null;
2570
+ };
2571
+ const go = (target, nextView) => {
2572
+ const href = props.getDateHref?.(target, nextView);
2573
+ if (href) followCalendarHref(owner, href);else openViewAt(props, target, nextView);
2574
+ };
2575
+ const step = direction => {
2576
+ if (timeView()?.step(direction)) return;
2577
+ go(adjacentCalendarDate(shownDay() ?? date(), view(), direction, dateConfig()), view());
2578
+ };
2579
+ const goToday = () => {
2580
+ if (timeView()?.today()) return;
2581
+ go(calendar.today(dateConfig()), view());
2582
+ };
2583
+ const goView = nextView => {
2584
+ const day = shownDay();
2585
+ if (day) {
2586
+ go(day, nextView);
2587
+ return;
2588
+ }
2589
+ const href = props.getViewHref?.(nextView);
2590
+ if (href) followCalendarHref(owner, href);else props.onViewChange?.(nextView);
2591
+ };
2592
+ const goToKey = key => {
2593
+ if (timeView()?.goTo(key)) return;
2594
+ go(parseKey(key), view());
2595
+ };
2596
+ const openGoTo = () => void openCalendarGoTo({
2597
+ messages: calendarMessages(),
2598
+ today: calendar.formatDateKey(new Date(), dateConfig()),
2599
+ describe: key => parseKey(key).toLocaleDateString(dateConfig().locale ?? "en", {
2600
+ weekday: "long",
2601
+ day: "numeric",
2602
+ month: "long",
2603
+ year: "numeric",
2604
+ timeZone: dateConfig().timeZone
2605
+ }),
2606
+ onGo: goToKey
2607
+ });
2608
+ const ownCommands = createMemo(() => {
2609
+ const text = calendarMessages();
2610
+ const available = ["day", "week", "month", "year"].filter(option => !props.views || props.views.includes(option));
2611
+ const viewLabels = {
2612
+ day: mergedLabels().day,
2613
+ week: mergedLabels().week,
2614
+ month: mergedLabels().month,
2615
+ year: mergedLabels().year
2616
+ };
2617
+ return [{
2618
+ id: "calendar.today",
2619
+ label: text.calendarCommandToday,
2620
+ description: text.calendarCommandTodayDescription,
2621
+ shortcut: "h",
2622
+ icon: "ti ti-calendar-event",
2623
+ run: goToday
2624
+ }, {
2625
+ id: "calendar.next",
2626
+ label: text.calendarCommandNext,
2627
+ description: text.calendarCommandNextDescription,
2628
+ shortcut: "j",
2629
+ icon: "ti ti-chevron-right",
2630
+ run: () => step(1)
2631
+ }, {
2632
+ id: "calendar.previous",
2633
+ label: text.calendarCommandPrevious,
2634
+ description: text.calendarCommandPreviousDescription,
2635
+ shortcut: "k",
2636
+ icon: "ti ti-chevron-left",
2637
+ run: () => step(-1)
2638
+ }, ...available.map((option, index) => ({
2639
+ id: `calendar.view.${option}`,
2640
+ label: text.calendarCommandView({
2641
+ view: viewLabels[option]
2642
+ }),
2643
+ description: text.calendarCommandViewDescription({
2644
+ view: viewLabels[option]
2645
+ }),
2646
+ shortcut: String(index + 1),
2647
+ icon: "ti ti-layout-columns",
2648
+ run: () => goView(option)
2649
+ })), {
2650
+ id: "calendar.goto",
2651
+ label: text.calendarCommandGoTo,
2652
+ description: text.calendarCommandGoToDescription,
2653
+ shortcut: "g",
2654
+ icon: "ti ti-calendar-search",
2655
+ run: openGoTo
2656
+ }];
2657
+ });
2658
+ const allCommands = createMemo(() => [...ownCommands(), ...(props.commands ?? [])]);
2659
+ /** While the month's quiet quick create waits for typing, a single key is the first letter of a title. */
2660
+ const typing = () => view() === "month" && (monthCreate()?.typing() ?? false);
2661
+ createEffect(() => {
2662
+ const commands = typing() ? allCommands().map(command => command.shortcut && singleKey(command.shortcut) ? {
2663
+ ...command,
2664
+ shortcut: undefined
2665
+ } : command) : allCommands();
2666
+ untrack(() => props.onCommandsChange?.(commands));
2667
+ });
2668
+ // The arrow keys page like J and K while the keyboard is in the calendar or nowhere, unless something there uses
2669
+ // them, such as the grid of the week or the month.
2670
+ let root;
2671
+ onMount(() => {
2672
+ const onKeyDown = event => {
2673
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
2674
+ if (event.defaultPrevented || event.isComposing || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
2675
+ if (!props.onCommandsChange || custom() || document.querySelector('dialog[open], [role="dialog"][aria-modal="true"]')) return;
2676
+ const target = event.target;
2677
+ const inCalendar = target instanceof Element && Boolean(root?.contains(target));
2678
+ if (!inCalendar && target !== document.body && target !== document.documentElement) return;
2679
+ if (target instanceof Element && target.closest("input, textarea, select, [contenteditable]:not([contenteditable=false]), [role=textbox], [popover], [role=dialog]")) return;
2680
+ event.preventDefault();
2681
+ step(event.key === "ArrowRight" ? 1 : -1);
2682
+ };
2683
+ window.addEventListener("keydown", onKeyDown);
2684
+ onCleanup(() => window.removeEventListener("keydown", onKeyDown));
2685
+ });
2686
+ const headerNav = {
2687
+ timeView,
2688
+ commands: () => props.onCommandsChange ? allCommands() : [],
2689
+ // The arrow keys page like J and K, so the list names them beside those keys.
2690
+ openShortcuts: () => void openCalendarShortcuts(allCommands(), calendarMessages(), custom() ? {} : {
2691
+ "calendar.next": "arrowright",
2692
+ "calendar.previous": "arrowleft"
2693
+ })
2694
+ };
2695
+ const controller = {
2696
+ quickCreate: create => {
2697
+ const active = timeView();
2698
+ if (active) active.controller.quickCreate(create);else monthCreate()?.quickCreate(create);
2699
+ },
2700
+ createTarget: () => {
2701
+ const active = timeView()?.controller.createTarget() ?? monthCreate()?.createTarget();
2702
+ if (active) return active;
2703
+ const start = calendar.today(dateConfig());
2704
+ return {
2705
+ start,
2706
+ end: calendar.addDays(start, 1, dateConfig()),
2707
+ allDay: true
2708
+ };
2709
+ },
2710
+ dragIn: (event, item, onDrop) => timeView()?.controller.dragIn(event, item, onDrop)
2711
+ };
2712
+ onMount(() => props.controller?.(controller));
2713
+ const timeProps = timeViewName => ({
2714
+ owner,
2715
+ view: timeViewName,
2716
+ get date() {
2717
+ return date();
2718
+ },
2719
+ get now() {
2720
+ return now();
2721
+ },
2722
+ get events() {
2723
+ return props.events;
2724
+ },
2725
+ get labels() {
2726
+ return mergedLabels();
2727
+ },
2728
+ get hours() {
2729
+ return props.dayHours ?? [0, 24];
2730
+ },
2731
+ register: setTimeView
2732
+ });
2733
+ return _$ssr(_tmpl$56, `k2b-content-calendar ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("aria-busy", props.navigationPending ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(CalendarHeader, {
2570
2734
  get date() {
2571
2735
  return date();
2572
2736
  },
@@ -2578,8 +2742,9 @@ const CalendarRoot = props => {
2578
2742
  },
2579
2743
  owner: owner,
2580
2744
  get focusDay() {
2581
- return _$memo(() => view() === "month")() ? focusDay() : null;
2582
- }
2745
+ return _$memo(() => view() === "month")() ? focusDay() : _$memo(() => !!timeView())() ? shownDay() : null;
2746
+ },
2747
+ nav: headerNav
2583
2748
  })), _$escape(_$createComponent(Show, {
2584
2749
  get when() {
2585
2750
  return !custom();
@@ -2613,7 +2778,8 @@ const CalendarRoot = props => {
2613
2778
  get labels() {
2614
2779
  return mergedLabels();
2615
2780
  },
2616
- onFocusDay: setFocusDay
2781
+ onFocusDay: setFocusDay,
2782
+ register: setMonthCreate
2617
2783
  });
2618
2784
  }
2619
2785
  });
@@ -2671,22 +2837,42 @@ const CalendarRoot = props => {
2671
2837
  });
2672
2838
  },
2673
2839
  get children() {
2674
- return _$createComponent(TimeGridView, {
2675
- owner: owner,
2676
- get date() {
2677
- return date();
2678
- },
2679
- get now() {
2680
- return now();
2840
+ return _$createComponent(Show, {
2841
+ get when() {
2842
+ return timeMode();
2681
2843
  },
2682
- get events() {
2683
- return normalizedEvents();
2684
- },
2685
- get labels() {
2686
- return mergedLabels();
2844
+ get fallback() {
2845
+ return _$createComponent(TimeGridView, {
2846
+ owner: owner,
2847
+ get date() {
2848
+ return date();
2849
+ },
2850
+ get now() {
2851
+ return now();
2852
+ },
2853
+ get events() {
2854
+ return normalizedEvents();
2855
+ },
2856
+ get labels() {
2857
+ return mergedLabels();
2858
+ },
2859
+ get days() {
2860
+ return days();
2861
+ }
2862
+ });
2687
2863
  },
2688
- get days() {
2689
- return days();
2864
+ get children() {
2865
+ return _$createComponent(Show, {
2866
+ get when() {
2867
+ return view() === "day";
2868
+ },
2869
+ get fallback() {
2870
+ return _$createComponent(CalendarWeekView, _$mergeProps(() => timeProps("week")));
2871
+ },
2872
+ get children() {
2873
+ return _$createComponent(CalendarDayView, _$mergeProps(() => timeProps("day")));
2874
+ }
2875
+ });
2690
2876
  }
2691
2877
  });
2692
2878
  }
@@ -2699,6 +2885,9 @@ const CalendarRoot = props => {
2699
2885
  })));
2700
2886
  };
2701
2887
 
2888
+ /** A shortcut without Ctrl, Meta, or Mod, which typing would set off. */
2889
+ const singleKey = shortcut => !/(^|\+)(ctrl|meta|mod)\+/i.test(shortcut);
2890
+
2702
2891
  /** JSX infers the values of `customViews`; inference from the last signature, as in `createComponent`, sees plain props. */
2703
2892
 
2704
2893
  function Calendar(props) {