@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.
- package/dist/browser/content/Calendar.js +1122 -1065
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/CalendarDayView.js +1187 -0
- package/dist/browser/content/CalendarDayView.js.map +1 -0
- package/dist/browser/content/CalendarWeekView.js +1593 -0
- package/dist/browser/content/CalendarWeekView.js.map +1 -0
- package/dist/browser/content/ChartExplorer.js +174 -82
- package/dist/browser/content/ChartExplorer.js.map +1 -1
- package/dist/browser/content/ChartFilterControls.js +90 -33
- package/dist/browser/content/ChartFilterControls.js.map +1 -1
- package/dist/browser/content/DataTable.js +235 -197
- package/dist/browser/content/DataTable.js.map +1 -1
- package/dist/browser/content/calendar-day-scroll.js +111 -0
- package/dist/browser/content/calendar-day-scroll.js.map +1 -0
- package/dist/browser/content/calendar-days.js +408 -0
- package/dist/browser/content/calendar-days.js.map +1 -0
- package/dist/browser/content/calendar-dialogs.js +236 -0
- package/dist/browser/content/calendar-dialogs.js.map +1 -0
- package/dist/browser/content/calendar-messages.js +210 -2
- package/dist/browser/content/calendar-messages.js.map +1 -1
- package/dist/browser/content/calendar-pointer.js +15 -3
- package/dist/browser/content/calendar-pointer.js.map +1 -1
- package/dist/browser/content/calendar-shared.js +328 -0
- package/dist/browser/content/calendar-shared.js.map +1 -0
- package/dist/browser/content/calendar-time-view.js +1654 -0
- package/dist/browser/content/calendar-time-view.js.map +1 -0
- package/dist/browser/content/chart-messages.js +10 -0
- package/dist/browser/content/chart-messages.js.map +1 -1
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/inputs/Combobox.js +0 -1
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +125 -97
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/Navigation.js +18 -3
- package/dist/browser/layout/Navigation.js.map +1 -1
- package/dist/browser/layout/PageTitle.js +18 -1
- package/dist/browser/layout/PageTitle.js.map +1 -1
- package/dist/browser/layout/SidebarSwitcher.js +505 -0
- package/dist/browser/layout/SidebarSwitcher.js.map +1 -0
- package/dist/browser/layout/app-workspace-controller.js +174 -86
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/index.js +1 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/navigation-model.js +1 -0
- package/dist/browser/layout/navigation-model.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +18 -6
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/content/Calendar.js +553 -341
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/CalendarDayView.js +800 -0
- package/dist/ssr/content/CalendarDayView.js.map +1 -0
- package/dist/ssr/content/CalendarWeekView.js +1090 -0
- package/dist/ssr/content/CalendarWeekView.js.map +1 -0
- package/dist/ssr/content/ChartExplorer.js +93 -34
- package/dist/ssr/content/ChartExplorer.js.map +1 -1
- package/dist/ssr/content/ChartFilterControls.js +49 -7
- package/dist/ssr/content/ChartFilterControls.js.map +1 -1
- package/dist/ssr/content/DataTable.js +88 -66
- package/dist/ssr/content/DataTable.js.map +1 -1
- package/dist/ssr/content/calendar-day-scroll.js +111 -0
- package/dist/ssr/content/calendar-day-scroll.js.map +1 -0
- package/dist/ssr/content/calendar-days.js +408 -0
- package/dist/ssr/content/calendar-days.js.map +1 -0
- package/dist/ssr/content/calendar-dialogs.js +159 -0
- package/dist/ssr/content/calendar-dialogs.js.map +1 -0
- package/dist/ssr/content/calendar-messages.js +210 -2
- package/dist/ssr/content/calendar-messages.js.map +1 -1
- package/dist/ssr/content/calendar-pointer.js +15 -3
- package/dist/ssr/content/calendar-pointer.js.map +1 -1
- package/dist/ssr/content/calendar-shared.js +261 -0
- package/dist/ssr/content/calendar-shared.js.map +1 -0
- package/dist/ssr/content/calendar-time-view.js +1311 -0
- package/dist/ssr/content/calendar-time-view.js.map +1 -0
- package/dist/ssr/content/chart-messages.js +10 -0
- package/dist/ssr/content/chart-messages.js.map +1 -1
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +40 -29
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/Navigation.js +12 -2
- package/dist/ssr/layout/Navigation.js.map +1 -1
- package/dist/ssr/layout/PageTitle.js +18 -1
- package/dist/ssr/layout/PageTitle.js.map +1 -1
- package/dist/ssr/layout/SidebarSwitcher.js +271 -0
- package/dist/ssr/layout/SidebarSwitcher.js.map +1 -0
- package/dist/ssr/layout/app-workspace-controller.js +174 -86
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/index.js +1 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/navigation-model.js +1 -0
- package/dist/ssr/layout/navigation-model.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +2 -2
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/content/Calendar.d.ts +95 -1
- package/dist/types/content/CalendarDayView.d.ts +7 -0
- package/dist/types/content/CalendarWeekView.d.ts +7 -0
- package/dist/types/content/ChartExplorer.d.ts +36 -1
- package/dist/types/content/ChartFilterControls.d.ts +6 -1
- package/dist/types/content/DataTable.d.ts +14 -0
- package/dist/types/content/calendar-day-scroll.d.ts +47 -0
- package/dist/types/content/calendar-days.d.ts +192 -0
- package/dist/types/content/calendar-dialogs.d.ts +22 -0
- package/dist/types/content/calendar-messages.d.ts +99 -0
- package/dist/types/content/calendar-pointer.d.ts +9 -0
- package/dist/types/content/calendar-shared.d.ts +69 -0
- package/dist/types/content/calendar-time-view.d.ts +252 -0
- package/dist/types/content/chart-messages.d.ts +5 -0
- package/dist/types/content/index.d.ts +2 -2
- package/dist/types/layout/AppWorkspace.d.ts +27 -3
- package/dist/types/layout/PageTitle.d.ts +2 -1
- package/dist/types/layout/SidebarSwitcher.d.ts +65 -0
- package/dist/types/layout/app-workspace-controller.d.ts +9 -1
- package/dist/types/layout/index.d.ts +1 -0
- package/dist/types/layout/navigation-model.d.ts +4 -0
- package/dist/types/surfaces/StatCell.d.ts +5 -0
- 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 {
|
|
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 {
|
|
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$ = ["<
|
|
11
|
-
_tmpl$2 = "<
|
|
12
|
-
_tmpl$3 = ["<
|
|
13
|
-
_tmpl$4 =
|
|
14
|
-
_tmpl$5 =
|
|
15
|
-
_tmpl$6 = ["<span class=\"k2b-
|
|
16
|
-
_tmpl$7 = ["<
|
|
17
|
-
_tmpl$8 = ["<
|
|
18
|
-
_tmpl$9 =
|
|
19
|
-
_tmpl$0 = ["<
|
|
20
|
-
_tmpl$1 = ["<
|
|
21
|
-
_tmpl$10 = ["<
|
|
22
|
-
_tmpl$11 = ["<
|
|
23
|
-
_tmpl$12 = ["<
|
|
24
|
-
_tmpl$13 = ["<div class=\"k2b-calendar-
|
|
25
|
-
_tmpl$14 = "<
|
|
26
|
-
_tmpl$15 = ["<
|
|
27
|
-
_tmpl$16 = ["<span class=\"k2b-calendar-
|
|
28
|
-
_tmpl$17 = ["<
|
|
29
|
-
_tmpl$18 = ["<
|
|
30
|
-
_tmpl$19 = ["<div class=\"k2b-calendar-
|
|
31
|
-
_tmpl$20 = ["<div class=\"k2b-calendar-
|
|
32
|
-
_tmpl$21 = ["<div class=\"k2b-calendar-
|
|
33
|
-
_tmpl$22 = ["<div class=\"k2b-calendar-
|
|
34
|
-
_tmpl$23 = ["<
|
|
35
|
-
_tmpl$24 = ["<
|
|
36
|
-
_tmpl$25 = ["<
|
|
37
|
-
_tmpl$26 = ["<div class=\"k2b-calendar-
|
|
38
|
-
_tmpl$27 = ["<div class=\"k2b-calendar-
|
|
39
|
-
_tmpl$28 = ["<
|
|
40
|
-
_tmpl$29 =
|
|
41
|
-
_tmpl$30 = ["<div class=\"k2b-calendar-
|
|
42
|
-
_tmpl$31 = ["<
|
|
43
|
-
_tmpl$32 = ["<
|
|
44
|
-
_tmpl$33 =
|
|
45
|
-
_tmpl$34 = ["<div class=\"k2b-calendar-
|
|
46
|
-
_tmpl$35 = ["<
|
|
47
|
-
_tmpl$36 = "<
|
|
48
|
-
_tmpl$37 = ["<
|
|
49
|
-
_tmpl$38 = ["<
|
|
50
|
-
_tmpl$39 = ["<
|
|
51
|
-
_tmpl$40 = "<
|
|
52
|
-
_tmpl$41 = ["<div class=\"k2b-calendar-
|
|
53
|
-
_tmpl$42 = ["<div class=\"k2b-calendar-time-
|
|
54
|
-
_tmpl$43 = ["<div class=\"k2b-calendar-
|
|
55
|
-
_tmpl$44 = ["<
|
|
56
|
-
_tmpl$45 = ["<
|
|
57
|
-
_tmpl$46 = ["<div class=\"k2b-calendar-time-
|
|
58
|
-
_tmpl$47 = ["<
|
|
59
|
-
_tmpl$48 = ["<div class=\"k2b-calendar-time-
|
|
60
|
-
_tmpl$49 = ["<div class=\"k2b-calendar-
|
|
61
|
-
_tmpl$50 = ["<div class=\"k2b-calendar-
|
|
62
|
-
_tmpl$51 = ["<
|
|
63
|
-
_tmpl$52 = ["<
|
|
64
|
-
_tmpl$53 = ["<div class=\"k2b-calendar-
|
|
65
|
-
_tmpl$54 = ["<
|
|
66
|
-
_tmpl$55 = ["<div class=\"k2b-calendar-
|
|
67
|
-
_tmpl$56 = ["<
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
|
509
|
-
const
|
|
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
|
|
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
|
-
|
|
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
|
|
530
|
+
title,
|
|
587
531
|
class: "k2b-calendar-header__nav-button"
|
|
588
532
|
},
|
|
589
533
|
get children() {
|
|
590
|
-
return _$ssr(_tmpl$
|
|
534
|
+
return _$ssr(_tmpl$2, `ti ${_$escape(icon, true)}`);
|
|
591
535
|
}
|
|
592
|
-
}) : props.owner.onDateChange ? _$ssr(_tmpl$
|
|
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
|
|
544
|
+
title,
|
|
600
545
|
class: "k2b-calendar-header__nav-button"
|
|
601
546
|
},
|
|
602
547
|
get children() {
|
|
603
|
-
return _$ssr(_tmpl$
|
|
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
|
|
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
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
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
|
-
|
|
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
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
1796
|
+
return _$ssr(_tmpl$31, _$escape(calendarMessages().calendarNothingPlanned));
|
|
1807
1797
|
},
|
|
1808
1798
|
get children() {
|
|
1809
|
-
return _$ssr(_tmpl$
|
|
1799
|
+
return _$ssr(_tmpl$28, _$escape(_$createComponent(For, {
|
|
1810
1800
|
get each() {
|
|
1811
1801
|
return entries();
|
|
1812
1802
|
},
|
|
1813
|
-
children: item => _$ssr(_tmpl$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
-
|
|
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
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
2220
|
+
}, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$39, _$escape(_$createComponent(For, {
|
|
2208
2221
|
each: previewAllDay,
|
|
2209
|
-
children: event => _$ssr(_tmpl$
|
|
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:",
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
2442
|
+
return _$ssr(_tmpl$49, _$escape(_$createComponent(For, {
|
|
2430
2443
|
get each() {
|
|
2431
2444
|
return months();
|
|
2432
2445
|
},
|
|
2433
|
-
children: month => _$ssr(_tmpl$
|
|
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$
|
|
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$
|
|
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$
|
|
2512
|
+
return _$ssr(_tmpl$54, _$escape(props.labels.noEvents));
|
|
2500
2513
|
},
|
|
2501
2514
|
get children() {
|
|
2502
|
-
return _$ssr(_tmpl$
|
|
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$
|
|
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
|
-
|
|
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(
|
|
2675
|
-
|
|
2676
|
-
|
|
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
|
|
2686
|
-
return
|
|
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
|
|
2689
|
-
return
|
|
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) {
|