@k2b/ui 0.22.0 → 0.24.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 (117) hide show
  1. package/dist/browser/content/Calendar.js +1122 -1065
  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 +1593 -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 +235 -197
  12. package/dist/browser/content/DataTable.js.map +1 -1
  13. package/dist/browser/content/calendar-day-scroll.js +111 -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 +1654 -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 +125 -97
  33. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  34. package/dist/browser/layout/Navigation.js +18 -3
  35. package/dist/browser/layout/Navigation.js.map +1 -1
  36. package/dist/browser/layout/PageTitle.js +18 -1
  37. package/dist/browser/layout/PageTitle.js.map +1 -1
  38. package/dist/browser/layout/SidebarSwitcher.js +505 -0
  39. package/dist/browser/layout/SidebarSwitcher.js.map +1 -0
  40. package/dist/browser/layout/app-workspace-controller.js +174 -86
  41. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  42. package/dist/browser/layout/index.js +1 -0
  43. package/dist/browser/layout/index.js.map +1 -1
  44. package/dist/browser/layout/navigation-model.js +1 -0
  45. package/dist/browser/layout/navigation-model.js.map +1 -1
  46. package/dist/browser/surfaces/StatCell.js +18 -6
  47. package/dist/browser/surfaces/StatCell.js.map +1 -1
  48. package/dist/ssr/content/Calendar.js +553 -341
  49. package/dist/ssr/content/Calendar.js.map +1 -1
  50. package/dist/ssr/content/CalendarDayView.js +800 -0
  51. package/dist/ssr/content/CalendarDayView.js.map +1 -0
  52. package/dist/ssr/content/CalendarWeekView.js +1090 -0
  53. package/dist/ssr/content/CalendarWeekView.js.map +1 -0
  54. package/dist/ssr/content/ChartExplorer.js +93 -34
  55. package/dist/ssr/content/ChartExplorer.js.map +1 -1
  56. package/dist/ssr/content/ChartFilterControls.js +49 -7
  57. package/dist/ssr/content/ChartFilterControls.js.map +1 -1
  58. package/dist/ssr/content/DataTable.js +88 -66
  59. package/dist/ssr/content/DataTable.js.map +1 -1
  60. package/dist/ssr/content/calendar-day-scroll.js +111 -0
  61. package/dist/ssr/content/calendar-day-scroll.js.map +1 -0
  62. package/dist/ssr/content/calendar-days.js +408 -0
  63. package/dist/ssr/content/calendar-days.js.map +1 -0
  64. package/dist/ssr/content/calendar-dialogs.js +159 -0
  65. package/dist/ssr/content/calendar-dialogs.js.map +1 -0
  66. package/dist/ssr/content/calendar-messages.js +210 -2
  67. package/dist/ssr/content/calendar-messages.js.map +1 -1
  68. package/dist/ssr/content/calendar-pointer.js +15 -3
  69. package/dist/ssr/content/calendar-pointer.js.map +1 -1
  70. package/dist/ssr/content/calendar-shared.js +261 -0
  71. package/dist/ssr/content/calendar-shared.js.map +1 -0
  72. package/dist/ssr/content/calendar-time-view.js +1311 -0
  73. package/dist/ssr/content/calendar-time-view.js.map +1 -0
  74. package/dist/ssr/content/chart-messages.js +10 -0
  75. package/dist/ssr/content/chart-messages.js.map +1 -1
  76. package/dist/ssr/content/index.js.map +1 -1
  77. package/dist/ssr/inputs/Combobox.js.map +1 -1
  78. package/dist/ssr/layout/AppWorkspace.js +40 -29
  79. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  80. package/dist/ssr/layout/Navigation.js +12 -2
  81. package/dist/ssr/layout/Navigation.js.map +1 -1
  82. package/dist/ssr/layout/PageTitle.js +18 -1
  83. package/dist/ssr/layout/PageTitle.js.map +1 -1
  84. package/dist/ssr/layout/SidebarSwitcher.js +271 -0
  85. package/dist/ssr/layout/SidebarSwitcher.js.map +1 -0
  86. package/dist/ssr/layout/app-workspace-controller.js +174 -86
  87. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  88. package/dist/ssr/layout/index.js +1 -0
  89. package/dist/ssr/layout/index.js.map +1 -1
  90. package/dist/ssr/layout/navigation-model.js +1 -0
  91. package/dist/ssr/layout/navigation-model.js.map +1 -1
  92. package/dist/ssr/surfaces/StatCell.js +2 -2
  93. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  94. package/dist/styles.css +1 -1
  95. package/dist/types/content/Calendar.d.ts +95 -1
  96. package/dist/types/content/CalendarDayView.d.ts +7 -0
  97. package/dist/types/content/CalendarWeekView.d.ts +7 -0
  98. package/dist/types/content/ChartExplorer.d.ts +36 -1
  99. package/dist/types/content/ChartFilterControls.d.ts +6 -1
  100. package/dist/types/content/DataTable.d.ts +14 -0
  101. package/dist/types/content/calendar-day-scroll.d.ts +47 -0
  102. package/dist/types/content/calendar-days.d.ts +192 -0
  103. package/dist/types/content/calendar-dialogs.d.ts +22 -0
  104. package/dist/types/content/calendar-messages.d.ts +99 -0
  105. package/dist/types/content/calendar-pointer.d.ts +9 -0
  106. package/dist/types/content/calendar-shared.d.ts +69 -0
  107. package/dist/types/content/calendar-time-view.d.ts +252 -0
  108. package/dist/types/content/chart-messages.d.ts +5 -0
  109. package/dist/types/content/index.d.ts +2 -2
  110. package/dist/types/layout/AppWorkspace.d.ts +27 -3
  111. package/dist/types/layout/PageTitle.d.ts +2 -1
  112. package/dist/types/layout/SidebarSwitcher.d.ts +65 -0
  113. package/dist/types/layout/app-workspace-controller.d.ts +9 -1
  114. package/dist/types/layout/index.d.ts +1 -0
  115. package/dist/types/layout/navigation-model.d.ts +4 -0
  116. package/dist/types/surfaces/StatCell.d.ts +5 -0
  117. package/package.json +3 -3
@@ -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\"", "><div class=\"k2b-calendar-time-grid__days\" style=\"", "\"><div class=\"k2b-calendar-time-grid__corner\"></div>", "</div>", "<div class=\"k2b-calendar-time-grid__scroll k2b-detail-trail\"><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
  /**
@@ -1222,6 +1191,8 @@ const MonthView = props => {
1222
1191
  const focusCell = key => cells.get(key)?.focus({
1223
1192
  preventScroll: true
1224
1193
  });
1194
+ /** Whether the focus is in the popover, or fell to the page as it hid: only then does a close return it. */
1195
+ const focusInPopover = () => popoverElement?.contains(document.activeElement) || document.activeElement === document.body;
1225
1196
  const closePopover = (restoreFocus = true) => {
1226
1197
  if (!popover()) return;
1227
1198
  setPopover(null);
@@ -1262,6 +1233,25 @@ const MonthView = props => {
1262
1233
  })) return;
1263
1234
  if (props.owner.onSlotActivate) props.owner.onSlotActivate(rangeOf(range));
1264
1235
  };
1236
+ onMount(() => props.register?.({
1237
+ quickCreate: create => {
1238
+ const range = selection() ?? {
1239
+ first: rovingKey(),
1240
+ last: rovingKey()
1241
+ };
1242
+ select(range.first, range.last);
1243
+ if (!openCreate(range, {
1244
+ active: true,
1245
+ create
1246
+ })) props.owner.onSlotActivate?.(rangeOf(range));
1247
+ },
1248
+ createTarget: () => rangeOf(selection() ?? {
1249
+ first: rovingKey(),
1250
+ last: rovingKey()
1251
+ }),
1252
+ typing: () => popover()?.kind === "create" && !createActive()
1253
+ }));
1254
+ onCleanup(() => props.register?.(null));
1265
1255
  const openDayList = key => {
1266
1256
  const anchor = cells.get(key);
1267
1257
  if (!anchor) return;
@@ -1582,18 +1572,18 @@ const MonthView = props => {
1582
1572
  if (linkedItem() === item.key) setLinkedItem("");
1583
1573
  }
1584
1574
  });
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, {
1575
+ 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
1576
  get when() {
1587
1577
  return props.owner.withWeekNumbers;
1588
1578
  },
1589
1579
  get children() {
1590
- return _$ssr(_tmpl$26, _$escape(calendarMessages().weekShort));
1580
+ return _$ssr(_tmpl$19, _$escape(calendarMessages().weekShort));
1591
1581
  }
1592
1582
  })), _$escape(_$createComponent(For, {
1593
1583
  get each() {
1594
1584
  return weekdays();
1595
1585
  },
1596
- children: (day, index) => _$ssr(_tmpl$28, _$ssrAttribute("data-weekend", index() > 4 ? "true" : _$escape(undefined, true), false), _$escape(day))
1586
+ children: (day, index) => _$ssr(_tmpl$21, _$ssrAttribute("data-weekend", index() > 4 ? "true" : _$escape(undefined, true), false), _$escape(day))
1597
1587
  })), _$escape(_$createComponent(For, {
1598
1588
  get each() {
1599
1589
  return weeks();
@@ -1605,12 +1595,12 @@ const MonthView = props => {
1605
1595
  }, capacities()[weekIndex()] ?? MONTH_DEFAULT_LANES));
1606
1596
  const weekHref = () => viewHref(week[0].key, "week");
1607
1597
  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, {
1598
+ return _$ssr(_tmpl$23, _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
1609
1599
  get when() {
1610
1600
  return props.owner.withWeekNumbers;
1611
1601
  },
1612
1602
  get children() {
1613
- return _$ssr(_tmpl$29, _$escape(_$createComponent(Show, {
1603
+ return _$ssr(_tmpl$22, _$escape(_$createComponent(Show, {
1614
1604
  get when() {
1615
1605
  return weekHref();
1616
1606
  },
@@ -1623,7 +1613,7 @@ const MonthView = props => {
1623
1613
  return weekNumber();
1624
1614
  },
1625
1615
  get children() {
1626
- return _$ssr(_tmpl$31, _$ssrAttribute("title", _$escape(calendarMessages().calendarOpenWeekNumber({
1616
+ return _$ssr(_tmpl$24, _$ssrAttribute("title", _$escape(calendarMessages().calendarOpenWeekNumber({
1627
1617
  week: weekNumber()
1628
1618
  }), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarOpenWeekNumber({
1629
1619
  week: weekNumber()
@@ -1671,13 +1661,13 @@ const MonthView = props => {
1671
1661
  shown: [],
1672
1662
  hidden: 0
1673
1663
  };
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, {
1664
+ 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
1665
  when: dayBadge,
1676
- children: badge => _$ssr(_tmpl$24, _$escape(_$createComponent(Show, {
1666
+ children: badge => _$ssr(_tmpl$17, _$escape(_$createComponent(Show, {
1677
1667
  get when() {
1678
1668
  return badge().icon;
1679
1669
  },
1680
- children: icon => _$ssr(_tmpl$10, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
1670
+ children: icon => _$ssr(_tmpl$2, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
1681
1671
  })), _$escape(badge().label))
1682
1672
  })), _$escape(_$createComponent(For, {
1683
1673
  get each() {
@@ -1752,7 +1742,7 @@ const MonthView = props => {
1752
1742
  get each() {
1753
1743
  return cell().shown;
1754
1744
  },
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, {
1745
+ 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
1746
  get event() {
1757
1747
  return item.event;
1758
1748
  },
@@ -1778,7 +1768,7 @@ const MonthView = props => {
1778
1768
  return cell().hidden > 0;
1779
1769
  },
1780
1770
  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({
1771
+ return _$ssr(_tmpl$25, _$ssrStyleProperty("--k2b-calendar-row:", _$escape(String(cell().top + cell().shown.length), true)), _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarMoreEventsOn({
1782
1772
  count: cell().hidden,
1783
1773
  label
1784
1774
  }), true), false), _$ssrAttribute("aria-expanded", (() => {
@@ -1798,19 +1788,19 @@ const MonthView = props => {
1798
1788
  const href = viewHref(dayKey, "day");
1799
1789
  // Read where it renders, so a refresh while the list is open updates it as it does the grid.
1800
1790
  const entries = () => dayEntries(dayKey);
1801
- return _$ssr(_tmpl$37, _$escape(dayLabel(day)), _$escape(_$createComponent(Show, {
1791
+ return _$ssr(_tmpl$30, _$escape(dayLabel(day)), _$escape(_$createComponent(Show, {
1802
1792
  get when() {
1803
1793
  return entries().length > 0;
1804
1794
  },
1805
1795
  get fallback() {
1806
- return _$ssr(_tmpl$38, _$escape(calendarMessages().calendarNothingPlanned));
1796
+ return _$ssr(_tmpl$31, _$escape(calendarMessages().calendarNothingPlanned));
1807
1797
  },
1808
1798
  get children() {
1809
- return _$ssr(_tmpl$35, _$escape(_$createComponent(For, {
1799
+ return _$ssr(_tmpl$28, _$escape(_$createComponent(For, {
1810
1800
  get each() {
1811
1801
  return entries();
1812
1802
  },
1813
- children: item => _$ssr(_tmpl$39, _$escape(_$createComponent(EventChip, {
1803
+ children: item => _$ssr(_tmpl$32, _$escape(_$createComponent(EventChip, {
1814
1804
  get event() {
1815
1805
  return item.event;
1816
1806
  },
@@ -1847,7 +1837,7 @@ const MonthView = props => {
1847
1837
  size: "sm",
1848
1838
  onClick: () => openView(dayKey, "day"),
1849
1839
  get children() {
1850
- return [_$ssr(_tmpl$40), calendarMessages().calendarOpenDay];
1840
+ return [_$ssr(_tmpl$33), calendarMessages().calendarOpenDay];
1851
1841
  }
1852
1842
  });
1853
1843
  }
@@ -1866,7 +1856,7 @@ const MonthView = props => {
1866
1856
  "data-size": "sm"
1867
1857
  },
1868
1858
  get children() {
1869
- return [_$ssr(_tmpl$40), calendarMessages().calendarOpenDay];
1859
+ return [_$ssr(_tmpl$33), calendarMessages().calendarOpenDay];
1870
1860
  }
1871
1861
  })
1872
1862
  })), _$escape(_$createComponent(Show, {
@@ -1888,7 +1878,7 @@ const MonthView = props => {
1888
1878
  });
1889
1879
  },
1890
1880
  get children() {
1891
- return [_$ssr(_tmpl$36), calendarMessages().calendarNewEvent];
1881
+ return [_$ssr(_tmpl$29), calendarMessages().calendarNewEvent];
1892
1882
  }
1893
1883
  });
1894
1884
  }
@@ -1917,7 +1907,7 @@ const MonthView = props => {
1917
1907
  }
1918
1908
  });
1919
1909
  }
1920
- }), _$ssr(_tmpl$41, _$ssrAttribute("aria-label", (() => {
1910
+ }), _$ssr(_tmpl$34, _$ssrAttribute("aria-label", (() => {
1921
1911
  const current = popover();
1922
1912
  if (current?.kind === "day") return dayLabel(parseKey(current.dayKey));
1923
1913
  return _$escape(calendarMessages().calendarQuickCreate, true);
@@ -1929,7 +1919,7 @@ const MonthView = props => {
1929
1919
  children: value => value.kind === "create" ? props.owner.renderQuickCreate?.(rangeOf(value.range), {
1930
1920
  create: value.create,
1931
1921
  close: () => {
1932
- if (popover() === value) closePopover();
1922
+ if (popover() === value) closePopover(focusInPopover());
1933
1923
  }
1934
1924
  }) : dayList(value.dayKey)
1935
1925
  })))];
@@ -1950,6 +1940,8 @@ const TimeGridView = props => {
1950
1940
  let scrollContainer;
1951
1941
  let timeGrid;
1952
1942
  let timeGutter;
1943
+ let daysRow;
1944
+ let allDayRow;
1953
1945
  let defaultHourMarker;
1954
1946
  let cancelInteraction;
1955
1947
  let suppressSlotClickUntil = 0;
@@ -1980,7 +1972,10 @@ const TimeGridView = props => {
1980
1972
  if (!timeGrid || !timeGutter) return null;
1981
1973
  const gridRect = timeGrid.getBoundingClientRect();
1982
1974
  const gutterRect = timeGutter.getBoundingClientRect();
1983
- const dayIndex = calendarDayIndexAtPoint(clientX, gutterRect.right, gridRect.right - gutterRect.right, props.days.length);
1975
+ // The gutter stays in view while the days scroll sideways under it, so the days start one gutter after the grid.
1976
+ if (clientX < gutterRect.right) return null;
1977
+ const daysLeft = gridRect.left + gutterRect.width;
1978
+ const dayIndex = calendarDayIndexAtPoint(clientX, daysLeft, gridRect.right - daysLeft, props.days.length);
1984
1979
  if (dayIndex === null) return null;
1985
1980
  const minute = Math.min(gridEndHour() * 60 + 45, calendarMinuteAtPoint(clientY, gridRect.top, gridRect.height, gridStartHour(), gridEndHour()));
1986
1981
  return zonedMinuteSlot(props.days[dayIndex], minute, dateConfig());
@@ -2106,10 +2101,28 @@ const TimeGridView = props => {
2106
2101
  }
2107
2102
  return [...groups.values()];
2108
2103
  };
2109
- const dayColumnMinWidth = layouts => {
2110
- if (!isDayView()) return undefined;
2111
- const lanes = Math.max(1, ...layouts.map(layout => layout.lanes));
2112
- return `${Math.max(32, lanes * 12)}rem`;
2104
+ // A week shares 36 rem between its days; a single day takes 12 rem per overlapping lane. The 40 rem grid is wider
2105
+ // than one or two lanes, so only three or more make the day scroll, and one lane fits beside a tablet drawer.
2106
+ const columnTemplate = createMemo(() => {
2107
+ let dayMin = "var(--k2b-calendar-day-min)";
2108
+ if (isDayView()) {
2109
+ const day = props.days[0];
2110
+ const layouts = timedEventLayouts(eventsByDay().get(calendar.formatDateKey(day, dateConfig()))?.timed ?? []);
2111
+ dayMin = `${Math.max(1, ...layouts.map(layout => layout.lanes)) * 12}rem`;
2112
+ }
2113
+ return `4rem repeat(${props.days.length}, minmax(${dayMin}, 1fr))`;
2114
+ });
2115
+ // The hours scroll sideways themselves; the day and all-day rows follow, also when focus scrolls one of them.
2116
+ // A row's scroll event from our own write arrives a frame late; echoing it back would undo a smooth scroll or fling.
2117
+ const followed = new WeakMap();
2118
+ const followColumns = source => {
2119
+ if (followed.get(source) === source.scrollLeft) return;
2120
+ followed.delete(source);
2121
+ for (const row of [scrollContainer, daysRow, allDayRow]) {
2122
+ if (!row || row === source || row.scrollLeft === source.scrollLeft) continue;
2123
+ row.scrollLeft = source.scrollLeft;
2124
+ followed.set(row, row.scrollLeft);
2125
+ }
2113
2126
  };
2114
2127
  const laneStyle = layoutItem => {
2115
2128
  if (isDayView()) {
@@ -2145,7 +2158,7 @@ const TimeGridView = props => {
2145
2158
  });
2146
2159
  });
2147
2160
  });
2148
- return _$ssr(_tmpl$43, _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`), _$escape(_$createComponent(For, {
2161
+ return _$ssr(_tmpl$36, _$ssrAttribute("data-view", isDayView() ? "day" : "week", false), _$ssrStyleProperty("grid-template-columns:", _$escape(columnTemplate(), true)), _$escape(_$createComponent(For, {
2149
2162
  get each() {
2150
2163
  return props.days;
2151
2164
  },
@@ -2163,13 +2176,13 @@ const TimeGridView = props => {
2163
2176
  class: "k2b-calendar-time-grid__day"
2164
2177
  },
2165
2178
  get children() {
2166
- return [_$ssr(_tmpl$44, _$ssrAttribute("data-today", today() ? "true" : _$escape(undefined, true), false), _$escape(formatDay(day, dateConfig()))), _$createComponent(Show, {
2179
+ return [_$ssr(_tmpl$37, _$ssrAttribute("data-today", today() ? "true" : _$escape(undefined, true), false), _$escape(formatDay(day, dateConfig()))), _$createComponent(Show, {
2167
2180
  when: dayBadge,
2168
- children: badge => _$ssr(_tmpl$45, _$escape(_$createComponent(Show, {
2181
+ children: badge => _$ssr(_tmpl$38, _$escape(_$createComponent(Show, {
2169
2182
  get when() {
2170
2183
  return badge().icon;
2171
2184
  },
2172
- children: icon => _$ssr(_tmpl$10, `k2b-calendar-time-grid__badge-icon ti ti-${_$escape(icon(), true)}`)
2185
+ children: icon => _$ssr(_tmpl$2, `k2b-calendar-time-grid__badge-icon ti ti-${_$escape(icon(), true)}`)
2173
2186
  })), _$escape(badge().label))
2174
2187
  })];
2175
2188
  }
@@ -2180,7 +2193,7 @@ const TimeGridView = props => {
2180
2193
  return !props.owner.hideAllDay;
2181
2194
  },
2182
2195
  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, {
2196
+ return _$ssr(_tmpl$35, _$ssrStyleProperty("grid-template-columns:", _$escape(columnTemplate(), true)) + _$ssrStyleProperty(";max-height:", `${_$escape(props.owner.allDayMaxHeightRem ?? 7, true)}rem`), _$escape(props.labels.allDay), _$escape(_$createComponent(For, {
2184
2197
  get each() {
2185
2198
  return props.days;
2186
2199
  },
@@ -2204,9 +2217,9 @@ const TimeGridView = props => {
2204
2217
  end: calendar.addDays(start, 1, dateConfig()),
2205
2218
  allDay: true
2206
2219
  };
2207
- }, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$46, _$escape(_$createComponent(For, {
2220
+ }, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$39, _$escape(_$createComponent(For, {
2208
2221
  each: previewAllDay,
2209
- children: event => _$ssr(_tmpl$21, _$escape(event.title))
2222
+ children: event => _$ssr(_tmpl$14, _$escape(event.title))
2210
2223
  })), _$escape(_$createComponent(For, {
2211
2224
  get each() {
2212
2225
  return allDay();
@@ -2231,11 +2244,11 @@ const TimeGridView = props => {
2231
2244
  }
2232
2245
  })));
2233
2246
  }
2234
- })), _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`), _$ssrStyleProperty("grid-template-rows:", `repeat(${_$escape(hours().length, true)}, minmax(4rem, 1fr))`), _$escape(_$createComponent(For, {
2247
+ })), _$ssrStyleProperty("grid-template-columns:", _$escape(columnTemplate(), true)), _$ssrStyleProperty("grid-template-rows:", `repeat(${_$escape(hours().length, true)}, minmax(4rem, 1fr))`), _$escape(_$createComponent(For, {
2235
2248
  get each() {
2236
2249
  return hours();
2237
2250
  },
2238
- children: hour => _$ssr(_tmpl$47, _$ssrAttribute("data-outside-business", hour < businessStartHour() || hour > businessEndHour() ? "true" : _$escape(undefined, true), false), _$escape(`${hour}`.padStart(2, "0")))
2251
+ children: hour => _$ssr(_tmpl$40, _$ssrAttribute("data-outside-business", hour < businessStartHour() || hour > businessEndHour() ? "true" : _$escape(undefined, true), false), _$escape(`${hour}`.padStart(2, "0")))
2239
2252
  })), _$escape(_$createComponent(For, {
2240
2253
  get each() {
2241
2254
  return props.days;
@@ -2243,12 +2256,12 @@ const TimeGridView = props => {
2243
2256
  children: day => {
2244
2257
  const dayKey = calendar.formatDateKey(day, dateConfig());
2245
2258
  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, {
2259
+ return _$ssr(_tmpl$42, _$ssrStyleProperty("grid-template-rows:", `repeat(${_$escape(hours().length, true)}, minmax(4rem, 1fr))`), _$escape(_$createComponent(Show, {
2247
2260
  get when() {
2248
2261
  return currentTimeLine(day) !== null;
2249
2262
  },
2250
2263
  get children() {
2251
- return _$ssr(_tmpl$48, _$ssrStyleProperty("top:", `${_$escape(currentTimeLine(day) ?? 0, true)}%`));
2264
+ return _$ssr(_tmpl$41, _$ssrStyleProperty("top:", `${_$escape(currentTimeLine(day) ?? 0, true)}%`));
2252
2265
  }
2253
2266
  })), _$escape(_$createComponent(For, {
2254
2267
  get each() {
@@ -2277,12 +2290,12 @@ const TimeGridView = props => {
2277
2290
  children: event => {
2278
2291
  const layout = eventLayout(event);
2279
2292
  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, {
2293
+ 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
2294
  get when() {
2282
2295
  return event.title;
2283
2296
  },
2284
2297
  get children() {
2285
- return _$ssr(_tmpl$50, _$escape(event.title));
2298
+ return _$ssr(_tmpl$43, _$escape(event.title));
2286
2299
  }
2287
2300
  })), _$escape(formatTime(event.startDate, dateConfig())), _$escape(formatTime(event.endDate, dateConfig())));
2288
2301
  }
@@ -2328,7 +2341,7 @@ const TimeGridView = props => {
2328
2341
  onCancel: clearInteraction
2329
2342
  });
2330
2343
  };
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, {
2344
+ 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
2345
  event: event,
2333
2346
  get owner() {
2334
2347
  return props.owner;
@@ -2348,7 +2361,7 @@ const TimeGridView = props => {
2348
2361
  return props.owner.onEventResize;
2349
2362
  },
2350
2363
  get children() {
2351
- return _$ssr(_tmpl$52, _$ssrAttribute("aria-label", _$escape(calendarMessages().resizeEvent, true), false));
2364
+ return _$ssr(_tmpl$45, _$ssrAttribute("aria-label", _$escape(calendarMessages().resizeEvent, true), false));
2352
2365
  }
2353
2366
  })));
2354
2367
  }
@@ -2360,14 +2373,14 @@ const TimeGridView = props => {
2360
2373
  const layout = timeRangeLayout(overflow.groupStartDate, overflow.groupEndDate);
2361
2374
  const key = `${dayKey}-${overflow.groupId}`;
2362
2375
  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({
2376
+ 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
2377
  count: overflow.hiddenEvents.length
2365
2378
  }), true), false), _$escape(overflow.hiddenEvents.length)), _$createComponent(Show, {
2366
2379
  get when() {
2367
2380
  return expandedOverflow() === key;
2368
2381
  },
2369
2382
  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, {
2383
+ return _$ssr(_tmpl$48, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`), _$escape(formatTime(overflow.groupStartDate, dateConfig())), _$escape(formatTime(overflow.groupEndDate, dateConfig())), _$escape(_$createComponent(For, {
2371
2384
  get each() {
2372
2385
  return overflow.hiddenEvents;
2373
2386
  },
@@ -2426,11 +2439,11 @@ const YearView = props => {
2426
2439
  };
2427
2440
  });
2428
2441
  });
2429
- return _$ssr(_tmpl$56, _$escape(_$createComponent(For, {
2442
+ return _$ssr(_tmpl$49, _$escape(_$createComponent(For, {
2430
2443
  get each() {
2431
2444
  return months();
2432
2445
  },
2433
- children: month => _$ssr(_tmpl$57, _$escape(month.label), _$escape(_$createComponent(For, {
2446
+ children: month => _$ssr(_tmpl$50, _$escape(month.label), _$escape(_$createComponent(For, {
2434
2447
  get each() {
2435
2448
  return month.days;
2436
2449
  },
@@ -2453,7 +2466,7 @@ const YearView = props => {
2453
2466
  get when() {
2454
2467
  return day.events[0];
2455
2468
  },
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 ? {
2469
+ 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
2470
  "background-color": day.isToday ? "white" : event().colorHex
2458
2471
  } : undefined))
2459
2472
  })];
@@ -2466,7 +2479,7 @@ const MobileMonthView = props => {
2466
2479
  const dateConfig = createMemo(() => ownerDateConfig(props.owner));
2467
2480
  const selectedDateKey = createMemo(() => calendar.formatDateKey(props.selectedDate, dateConfig()));
2468
2481
  const selectedEvents = createMemo(() => props.events.filter(event => event.dayKey === selectedDateKey()));
2469
- return _$ssr(_tmpl$60, _$escape(_$createComponent(MonthPickerView, {
2482
+ return _$ssr(_tmpl$53, _$escape(_$createComponent(MonthPickerView, {
2470
2483
  get owner() {
2471
2484
  return {
2472
2485
  ...props.owner,
@@ -2496,10 +2509,10 @@ const MobileMonthView = props => {
2496
2509
  return selectedEvents().length > 0;
2497
2510
  },
2498
2511
  get fallback() {
2499
- return _$ssr(_tmpl$61, _$escape(props.labels.noEvents));
2512
+ return _$ssr(_tmpl$54, _$escape(props.labels.noEvents));
2500
2513
  },
2501
2514
  get children() {
2502
- return _$ssr(_tmpl$59, _$escape(_$createComponent(For, {
2515
+ return _$ssr(_tmpl$52, _$escape(_$createComponent(For, {
2503
2516
  get each() {
2504
2517
  return selectedEvents();
2505
2518
  },
@@ -2516,7 +2529,7 @@ const MobileMonthView = props => {
2516
2529
  }
2517
2530
  })));
2518
2531
  };
2519
- const CalendarBody = props => _$ssr(_tmpl$62, _$escape(props.children));
2532
+ const CalendarBody = props => _$ssr(_tmpl$55, _$escape(props.children));
2520
2533
  const CalendarRoot = props => {
2521
2534
  const messages = useUiMessages();
2522
2535
  const calendarMessages = useCalendarMessages();
@@ -2566,7 +2579,181 @@ const CalendarRoot = props => {
2566
2579
  document.removeEventListener("visibilitychange", updateNow);
2567
2580
  });
2568
2581
  });
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, {
2582
+
2583
+ // The day and week views with `dayHours` scroll through their days; the header and the commands ask them first.
2584
+ const [timeView, setTimeView] = createSignal(null);
2585
+ const [monthCreate, setMonthCreate] = createSignal(null);
2586
+ const timeMode = () => Boolean(props.dayHours) && (view() === "day" || view() === "week");
2587
+ const parseKey = key => calendar.parseCalendarDate(key, dateConfig());
2588
+ /** The first shown day of a day or week view, or the selected day of the month view, for the other views. */
2589
+ const shownDay = () => {
2590
+ const first = timeView()?.visibleKeys().first;
2591
+ if (first) return parseKey(first);
2592
+ return view() === "month" ? focusDay() : null;
2593
+ };
2594
+ const go = (target, nextView) => {
2595
+ const href = props.getDateHref?.(target, nextView);
2596
+ if (href) followCalendarHref(owner, href);else openViewAt(props, target, nextView);
2597
+ };
2598
+ const step = direction => {
2599
+ if (timeView()?.step(direction)) return;
2600
+ go(adjacentCalendarDate(shownDay() ?? date(), view(), direction, dateConfig()), view());
2601
+ };
2602
+ const goToday = () => {
2603
+ if (timeView()?.today()) return;
2604
+ go(calendar.today(dateConfig()), view());
2605
+ };
2606
+ const goView = nextView => {
2607
+ const day = shownDay();
2608
+ if (day) {
2609
+ go(day, nextView);
2610
+ return;
2611
+ }
2612
+ const href = props.getViewHref?.(nextView);
2613
+ if (href) followCalendarHref(owner, href);else props.onViewChange?.(nextView);
2614
+ };
2615
+ const goToKey = key => {
2616
+ if (timeView()?.goTo(key)) return;
2617
+ go(parseKey(key), view());
2618
+ };
2619
+ const openGoTo = () => void openCalendarGoTo({
2620
+ messages: calendarMessages(),
2621
+ today: calendar.formatDateKey(new Date(), dateConfig()),
2622
+ describe: key => parseKey(key).toLocaleDateString(dateConfig().locale ?? "en", {
2623
+ weekday: "long",
2624
+ day: "numeric",
2625
+ month: "long",
2626
+ year: "numeric",
2627
+ timeZone: dateConfig().timeZone
2628
+ }),
2629
+ onGo: goToKey
2630
+ });
2631
+ const ownCommands = createMemo(() => {
2632
+ const text = calendarMessages();
2633
+ const available = ["day", "week", "month", "year"].filter(option => !props.views || props.views.includes(option));
2634
+ const viewLabels = {
2635
+ day: mergedLabels().day,
2636
+ week: mergedLabels().week,
2637
+ month: mergedLabels().month,
2638
+ year: mergedLabels().year
2639
+ };
2640
+ return [{
2641
+ id: "calendar.today",
2642
+ label: text.calendarCommandToday,
2643
+ description: text.calendarCommandTodayDescription,
2644
+ shortcut: "h",
2645
+ icon: "ti ti-calendar-event",
2646
+ run: goToday
2647
+ }, {
2648
+ id: "calendar.next",
2649
+ label: text.calendarCommandNext,
2650
+ description: text.calendarCommandNextDescription,
2651
+ shortcut: "j",
2652
+ icon: "ti ti-chevron-right",
2653
+ run: () => step(1)
2654
+ }, {
2655
+ id: "calendar.previous",
2656
+ label: text.calendarCommandPrevious,
2657
+ description: text.calendarCommandPreviousDescription,
2658
+ shortcut: "k",
2659
+ icon: "ti ti-chevron-left",
2660
+ run: () => step(-1)
2661
+ }, ...available.map((option, index) => ({
2662
+ id: `calendar.view.${option}`,
2663
+ label: text.calendarCommandView({
2664
+ view: viewLabels[option]
2665
+ }),
2666
+ description: text.calendarCommandViewDescription({
2667
+ view: viewLabels[option]
2668
+ }),
2669
+ shortcut: String(index + 1),
2670
+ icon: "ti ti-layout-columns",
2671
+ run: () => goView(option)
2672
+ })), {
2673
+ id: "calendar.goto",
2674
+ label: text.calendarCommandGoTo,
2675
+ description: text.calendarCommandGoToDescription,
2676
+ shortcut: "g",
2677
+ icon: "ti ti-calendar-search",
2678
+ run: openGoTo
2679
+ }];
2680
+ });
2681
+ const allCommands = createMemo(() => [...ownCommands(), ...(props.commands ?? [])]);
2682
+ /** While the month's quiet quick create waits for typing, a single key is the first letter of a title. */
2683
+ const typing = () => view() === "month" && (monthCreate()?.typing() ?? false);
2684
+ createEffect(() => {
2685
+ const commands = typing() ? allCommands().map(command => command.shortcut && singleKey(command.shortcut) ? {
2686
+ ...command,
2687
+ shortcut: undefined
2688
+ } : command) : allCommands();
2689
+ untrack(() => props.onCommandsChange?.(commands));
2690
+ });
2691
+ // The arrow keys page like J and K while the keyboard is in the calendar or nowhere, unless something there uses
2692
+ // them, such as the grid of the week or the month.
2693
+ let root;
2694
+ onMount(() => {
2695
+ const onKeyDown = event => {
2696
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
2697
+ if (event.defaultPrevented || event.isComposing || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
2698
+ if (!props.onCommandsChange || custom() || document.querySelector('dialog[open], [role="dialog"][aria-modal="true"]')) return;
2699
+ const target = event.target;
2700
+ const inCalendar = target instanceof Element && Boolean(root?.contains(target));
2701
+ if (!inCalendar && target !== document.body && target !== document.documentElement) return;
2702
+ if (target instanceof Element && target.closest("input, textarea, select, [contenteditable]:not([contenteditable=false]), [role=textbox], [popover], [role=dialog]")) return;
2703
+ event.preventDefault();
2704
+ step(event.key === "ArrowRight" ? 1 : -1);
2705
+ };
2706
+ window.addEventListener("keydown", onKeyDown);
2707
+ onCleanup(() => window.removeEventListener("keydown", onKeyDown));
2708
+ });
2709
+ const headerNav = {
2710
+ timeView,
2711
+ commands: () => props.onCommandsChange ? allCommands() : [],
2712
+ // The arrow keys page like J and K, so the list names them beside those keys.
2713
+ openShortcuts: () => void openCalendarShortcuts(allCommands(), calendarMessages(), custom() ? {} : {
2714
+ "calendar.next": "arrowright",
2715
+ "calendar.previous": "arrowleft"
2716
+ })
2717
+ };
2718
+ const controller = {
2719
+ quickCreate: create => {
2720
+ const active = timeView();
2721
+ if (active) active.controller.quickCreate(create);else monthCreate()?.quickCreate(create);
2722
+ },
2723
+ createTarget: () => {
2724
+ const active = timeView()?.controller.createTarget() ?? monthCreate()?.createTarget();
2725
+ if (active) return active;
2726
+ const start = calendar.today(dateConfig());
2727
+ return {
2728
+ start,
2729
+ end: calendar.addDays(start, 1, dateConfig()),
2730
+ allDay: true
2731
+ };
2732
+ },
2733
+ dragIn: (event, item, onDrop) => timeView()?.controller.dragIn(event, item, onDrop)
2734
+ };
2735
+ onMount(() => props.controller?.(controller));
2736
+ const timeProps = timeViewName => ({
2737
+ owner,
2738
+ view: timeViewName,
2739
+ get date() {
2740
+ return date();
2741
+ },
2742
+ get now() {
2743
+ return now();
2744
+ },
2745
+ get events() {
2746
+ return props.events;
2747
+ },
2748
+ get labels() {
2749
+ return mergedLabels();
2750
+ },
2751
+ get hours() {
2752
+ return props.dayHours ?? [0, 24];
2753
+ },
2754
+ register: setTimeView
2755
+ });
2756
+ 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
2757
  get date() {
2571
2758
  return date();
2572
2759
  },
@@ -2578,8 +2765,9 @@ const CalendarRoot = props => {
2578
2765
  },
2579
2766
  owner: owner,
2580
2767
  get focusDay() {
2581
- return _$memo(() => view() === "month")() ? focusDay() : null;
2582
- }
2768
+ return _$memo(() => view() === "month")() ? focusDay() : _$memo(() => !!timeView())() ? shownDay() : null;
2769
+ },
2770
+ nav: headerNav
2583
2771
  })), _$escape(_$createComponent(Show, {
2584
2772
  get when() {
2585
2773
  return !custom();
@@ -2613,7 +2801,8 @@ const CalendarRoot = props => {
2613
2801
  get labels() {
2614
2802
  return mergedLabels();
2615
2803
  },
2616
- onFocusDay: setFocusDay
2804
+ onFocusDay: setFocusDay,
2805
+ register: setMonthCreate
2617
2806
  });
2618
2807
  }
2619
2808
  });
@@ -2671,22 +2860,42 @@ const CalendarRoot = props => {
2671
2860
  });
2672
2861
  },
2673
2862
  get children() {
2674
- return _$createComponent(TimeGridView, {
2675
- owner: owner,
2676
- get date() {
2677
- return date();
2678
- },
2679
- get now() {
2680
- return now();
2681
- },
2682
- get events() {
2683
- return normalizedEvents();
2863
+ return _$createComponent(Show, {
2864
+ get when() {
2865
+ return timeMode();
2684
2866
  },
2685
- get labels() {
2686
- return mergedLabels();
2867
+ get fallback() {
2868
+ return _$createComponent(TimeGridView, {
2869
+ owner: owner,
2870
+ get date() {
2871
+ return date();
2872
+ },
2873
+ get now() {
2874
+ return now();
2875
+ },
2876
+ get events() {
2877
+ return normalizedEvents();
2878
+ },
2879
+ get labels() {
2880
+ return mergedLabels();
2881
+ },
2882
+ get days() {
2883
+ return days();
2884
+ }
2885
+ });
2687
2886
  },
2688
- get days() {
2689
- return days();
2887
+ get children() {
2888
+ return _$createComponent(Show, {
2889
+ get when() {
2890
+ return view() === "day";
2891
+ },
2892
+ get fallback() {
2893
+ return _$createComponent(CalendarWeekView, _$mergeProps(() => timeProps("week")));
2894
+ },
2895
+ get children() {
2896
+ return _$createComponent(CalendarDayView, _$mergeProps(() => timeProps("day")));
2897
+ }
2898
+ });
2690
2899
  }
2691
2900
  });
2692
2901
  }
@@ -2699,6 +2908,9 @@ const CalendarRoot = props => {
2699
2908
  })));
2700
2909
  };
2701
2910
 
2911
+ /** A shortcut without Ctrl, Meta, or Mod, which typing would set off. */
2912
+ const singleKey = shortcut => !/(^|\+)(ctrl|meta|mod)\+/i.test(shortcut);
2913
+
2702
2914
  /** JSX infers the values of `customViews`; inference from the last signature, as in `createComponent`, sees plain props. */
2703
2915
 
2704
2916
  function Calendar(props) {