@k2b/ui 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/content/Calendar.js +1086 -1049
- 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 +1571 -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 +199 -171
- package/dist/browser/content/DataTable.js.map +1 -1
- package/dist/browser/content/calendar-day-scroll.js +98 -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 +1649 -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 +123 -97
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/PageTitle.js +4 -1
- package/dist/browser/layout/PageTitle.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +164 -86
- package/dist/browser/layout/app-workspace-controller.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 +524 -335
- 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 +1069 -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 +69 -51
- package/dist/ssr/content/DataTable.js.map +1 -1
- package/dist/ssr/content/calendar-day-scroll.js +98 -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 +1306 -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 +38 -29
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/PageTitle.js +4 -1
- package/dist/ssr/layout/PageTitle.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +164 -86
- package/dist/ssr/layout/app-workspace-controller.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 +91 -0
- 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 +5 -0
- package/dist/types/content/calendar-day-scroll.d.ts +42 -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 +25 -3
- package/dist/types/layout/PageTitle.d.ts +2 -1
- package/dist/types/layout/app-workspace-controller.d.ts +9 -1
- package/dist/types/surfaces/StatCell.d.ts +5 -0
- package/package.json +1 -1
|
@@ -1,77 +1,70 @@
|
|
|
1
|
+
import { ssrStyle as _$ssrStyle } from "solid-js/web";
|
|
1
2
|
import { ssrStyleProperty as _$ssrStyleProperty } from "solid-js/web";
|
|
2
3
|
import { memo as _$memo } from "solid-js/web";
|
|
3
|
-
import {
|
|
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 k2b-detail-trail\"", "><div class=\"k2b-calendar-time-grid__days\" style=\"", "\"><div></div>", "</div>", "<div class=\"k2b-calendar-time-grid__scroll\"><div class=\"k2b-calendar-time-grid__grid\" style=\"", "\"><div class=\"k2b-calendar-time-grid__gutter\" style=\"", "\">", "</div>", "</div></div></div>"],
|
|
48
|
+
_tmpl$37 = ["<span class=\"k2b-calendar-time-grid__day-label\"", ">", "</span>"],
|
|
49
|
+
_tmpl$38 = ["<span class=\"k2b-calendar-time-grid__badge\">", "", "</span>"],
|
|
50
|
+
_tmpl$39 = ["<div class=\"k2b-calendar-time-grid__all-day-events\">", "", "</div>"],
|
|
51
|
+
_tmpl$40 = ["<div class=\"k2b-calendar-time-grid__hour\"", ">", ":00</div>"],
|
|
52
|
+
_tmpl$41 = ["<div class=\"k2b-calendar-time-grid__now\" style=\"", "\"></div>"],
|
|
53
|
+
_tmpl$42 = ["<div class=\"k2b-calendar-time-grid__column\" style=\"", "\">", "", "", "", "", "</div>"],
|
|
54
|
+
_tmpl$43 = ["<div class=\"k2b-calendar-preview__title\">", "</div>"],
|
|
55
|
+
_tmpl$44 = ["<div class=\"k2b-calendar-preview k2b-calendar-preview--timed\"", " style=\"", "\"><div class=\"k2b-calendar-preview__content\">", "<div class=\"k2b-calendar-preview__label\">", " - ", "</div></div></div>"],
|
|
56
|
+
_tmpl$45 = ["<button type=\"button\"", " draggable=\"false\" class=\"k2b-calendar-time-grid__resize\"><span class=\"k2b-calendar-time-grid__resize-icon\" aria-hidden=\"true\"></span></button>"],
|
|
57
|
+
_tmpl$46 = ["<div class=\"k2b-calendar-time-grid__event-position\" style=\"", "\"><div class=\"k2b-calendar-time-grid__event-frame\">", "", "</div></div>"],
|
|
58
|
+
_tmpl$47 = ["<button type=\"button\" class=\"k2b-calendar-time-grid__overflow\" style=\"", "\"", "><span class=\"k2b-calendar-time-grid__overflow-count\">+", "</span></button>"],
|
|
59
|
+
_tmpl$48 = ["<div class=\"k2b-calendar-time-grid__overflow-menu\" style=\"", "\"><div class=\"k2b-calendar-time-grid__overflow-title\">", " - ", "</div>", "</div>"],
|
|
60
|
+
_tmpl$49 = ["<div class=\"k2b-calendar-year\">", "</div>"],
|
|
61
|
+
_tmpl$50 = ["<div class=\"k2b-calendar-year__month\"><div class=\"k2b-calendar-year__title\">", "</div><div class=\"k2b-calendar-year__grid\">", "</div></div>"],
|
|
62
|
+
_tmpl$51 = ["<span class=\"k2b-calendar-year__indicator\"", " style=\"", "\"></span>"],
|
|
63
|
+
_tmpl$52 = ["<div class=\"k2b-calendar-mobile-month__events\">", "</div>"],
|
|
64
|
+
_tmpl$53 = ["<div class=\"k2b-calendar-mobile-month\">", "<div class=\"k2b-calendar-mobile-month__agenda\"><div class=\"k2b-calendar-mobile-month__title\">", "</div>", "</div></div>"],
|
|
65
|
+
_tmpl$54 = ["<div class=\"k2b-calendar-mobile-month__empty\">", "</div>"],
|
|
66
|
+
_tmpl$55 = ["<div class=\"k2b-calendar-body\">", "</div>"],
|
|
67
|
+
_tmpl$56 = ["<section class=\"", "\"", ">", "", "</section>"];
|
|
75
68
|
import { Link } from "@k2b/ssr/nav";
|
|
76
69
|
import { dates as calendar } from "@k2b/stdlib";
|
|
77
70
|
import { createEffect, createMemo, createSignal, For, mergeProps, on, onCleanup, onMount, Show, untrack } from "solid-js";
|
|
@@ -80,31 +73,29 @@ import { GestureMenu } from "../actions/GestureMenu";
|
|
|
80
73
|
import SegmentedControl from "../actions/SegmentedControl";
|
|
81
74
|
import { useDateConfigLocale } from "../intl/locale";
|
|
82
75
|
import { useUiMessages } from "../intl/messages";
|
|
76
|
+
import { CalendarDayView } from "./CalendarDayView";
|
|
77
|
+
import { CalendarWeekView } from "./CalendarWeekView";
|
|
78
|
+
import { openCalendarGoTo, openCalendarShortcuts } from "./calendar-dialogs";
|
|
83
79
|
import { layoutCalendarIntervals } from "./calendar-event-layout";
|
|
84
80
|
import { useCalendarMessages } from "./calendar-messages";
|
|
85
81
|
import { fitMonthWeek, layoutMonthWeek, monthLaneCapacity } from "./calendar-month-layout";
|
|
86
82
|
import { calendarDayIndexAtPoint, calendarMinuteAtPoint, startCalendarPointerSession } from "./calendar-pointer";
|
|
83
|
+
import { EventChip, eventHref, followCalendarHref, formatTime, ownerDateConfig, parseDate, placeCalendarPopover, textWidth, validDate } from "./calendar-shared";
|
|
84
|
+
import { compactGermanDate } from "./calendar-time-view";
|
|
87
85
|
|
|
88
|
-
/**
|
|
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
|
/**
|
|
@@ -1262,6 +1231,25 @@ const MonthView = props => {
|
|
|
1262
1231
|
})) return;
|
|
1263
1232
|
if (props.owner.onSlotActivate) props.owner.onSlotActivate(rangeOf(range));
|
|
1264
1233
|
};
|
|
1234
|
+
onMount(() => props.register?.({
|
|
1235
|
+
quickCreate: create => {
|
|
1236
|
+
const range = selection() ?? {
|
|
1237
|
+
first: rovingKey(),
|
|
1238
|
+
last: rovingKey()
|
|
1239
|
+
};
|
|
1240
|
+
select(range.first, range.last);
|
|
1241
|
+
if (!openCreate(range, {
|
|
1242
|
+
active: true,
|
|
1243
|
+
create
|
|
1244
|
+
})) props.owner.onSlotActivate?.(rangeOf(range));
|
|
1245
|
+
},
|
|
1246
|
+
createTarget: () => rangeOf(selection() ?? {
|
|
1247
|
+
first: rovingKey(),
|
|
1248
|
+
last: rovingKey()
|
|
1249
|
+
}),
|
|
1250
|
+
typing: () => popover()?.kind === "create" && !createActive()
|
|
1251
|
+
}));
|
|
1252
|
+
onCleanup(() => props.register?.(null));
|
|
1265
1253
|
const openDayList = key => {
|
|
1266
1254
|
const anchor = cells.get(key);
|
|
1267
1255
|
if (!anchor) return;
|
|
@@ -1582,18 +1570,18 @@ const MonthView = props => {
|
|
|
1582
1570
|
if (linkedItem() === item.key) setLinkedItem("");
|
|
1583
1571
|
}
|
|
1584
1572
|
});
|
|
1585
|
-
const grid = () => _$ssr(_tmpl$
|
|
1573
|
+
const grid = () => _$ssr(_tmpl$20, _$ssrAttribute("aria-label", _$escape(formatMonth(props.date, dateConfig()), true), false), _$ssrStyleProperty("grid-template-rows:", `auto repeat(${_$escape(weeks().length, true)}, minmax(5rem, 1fr))`) + _$ssrStyleProperty(";--k2b-calendar-lane:", "1.25rem") + _$ssrStyleProperty(";--k2b-calendar-lane-gap:", "0.125rem"), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
|
|
1586
1574
|
get when() {
|
|
1587
1575
|
return props.owner.withWeekNumbers;
|
|
1588
1576
|
},
|
|
1589
1577
|
get children() {
|
|
1590
|
-
return _$ssr(_tmpl$
|
|
1578
|
+
return _$ssr(_tmpl$19, _$escape(calendarMessages().weekShort));
|
|
1591
1579
|
}
|
|
1592
1580
|
})), _$escape(_$createComponent(For, {
|
|
1593
1581
|
get each() {
|
|
1594
1582
|
return weekdays();
|
|
1595
1583
|
},
|
|
1596
|
-
children: (day, index) => _$ssr(_tmpl$
|
|
1584
|
+
children: (day, index) => _$ssr(_tmpl$21, _$ssrAttribute("data-weekend", index() > 4 ? "true" : _$escape(undefined, true), false), _$escape(day))
|
|
1597
1585
|
})), _$escape(_$createComponent(For, {
|
|
1598
1586
|
get each() {
|
|
1599
1587
|
return weeks();
|
|
@@ -1605,12 +1593,12 @@ const MonthView = props => {
|
|
|
1605
1593
|
}, capacities()[weekIndex()] ?? MONTH_DEFAULT_LANES));
|
|
1606
1594
|
const weekHref = () => viewHref(week[0].key, "week");
|
|
1607
1595
|
const weekNumber = () => zonedWeekNumber(week[0].day, dateConfig());
|
|
1608
|
-
return _$ssr(_tmpl$
|
|
1596
|
+
return _$ssr(_tmpl$23, _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
|
|
1609
1597
|
get when() {
|
|
1610
1598
|
return props.owner.withWeekNumbers;
|
|
1611
1599
|
},
|
|
1612
1600
|
get children() {
|
|
1613
|
-
return _$ssr(_tmpl$
|
|
1601
|
+
return _$ssr(_tmpl$22, _$escape(_$createComponent(Show, {
|
|
1614
1602
|
get when() {
|
|
1615
1603
|
return weekHref();
|
|
1616
1604
|
},
|
|
@@ -1623,7 +1611,7 @@ const MonthView = props => {
|
|
|
1623
1611
|
return weekNumber();
|
|
1624
1612
|
},
|
|
1625
1613
|
get children() {
|
|
1626
|
-
return _$ssr(_tmpl$
|
|
1614
|
+
return _$ssr(_tmpl$24, _$ssrAttribute("title", _$escape(calendarMessages().calendarOpenWeekNumber({
|
|
1627
1615
|
week: weekNumber()
|
|
1628
1616
|
}), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarOpenWeekNumber({
|
|
1629
1617
|
week: weekNumber()
|
|
@@ -1671,13 +1659,13 @@ const MonthView = props => {
|
|
|
1671
1659
|
shown: [],
|
|
1672
1660
|
hidden: 0
|
|
1673
1661
|
};
|
|
1674
|
-
return _$ssr(_tmpl$
|
|
1662
|
+
return _$ssr(_tmpl$26, _$ssrAttribute("tabindex", rovingKey() === key ? 0 : -1, false) + _$ssrAttribute("aria-label", _$escape(label, true), false) + _$ssrAttribute("aria-selected", within(selection(), key) ? "true" : "false", false) + _$ssrAttribute("aria-current", key === todayKey() ? "date" : _$escape(undefined, true), false) + _$ssrAttribute("data-calendar-day-key", _$escape(key, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-weekend", column() > 4 ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-past", key < todayKey() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-selected", _$escape(selectionPart(key), true), false) + _$ssrAttribute("data-drop-preview", within(dropRange(), key) ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-today", key === todayKey() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-outside", !sameMonth ? "true" : _$escape(undefined, true), false), _$escape(calendar.formatDayNumber(day, dateConfig())), _$escape(_$createComponent(Show, {
|
|
1675
1663
|
when: dayBadge,
|
|
1676
|
-
children: badge => _$ssr(_tmpl$
|
|
1664
|
+
children: badge => _$ssr(_tmpl$17, _$escape(_$createComponent(Show, {
|
|
1677
1665
|
get when() {
|
|
1678
1666
|
return badge().icon;
|
|
1679
1667
|
},
|
|
1680
|
-
children: icon => _$ssr(_tmpl$
|
|
1668
|
+
children: icon => _$ssr(_tmpl$2, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
|
|
1681
1669
|
})), _$escape(badge().label))
|
|
1682
1670
|
})), _$escape(_$createComponent(For, {
|
|
1683
1671
|
get each() {
|
|
@@ -1752,7 +1740,7 @@ const MonthView = props => {
|
|
|
1752
1740
|
get each() {
|
|
1753
1741
|
return cell().shown;
|
|
1754
1742
|
},
|
|
1755
|
-
children: (item, index) => _$ssr(_tmpl$
|
|
1743
|
+
children: (item, index) => _$ssr(_tmpl$27, _$ssrStyleProperty("--k2b-calendar-span:", "1") + _$ssrStyleProperty(";--k2b-calendar-row:", _$escape(String(cell().top + index()), true)), _$escape(_$createComponent(EventChip, {
|
|
1756
1744
|
get event() {
|
|
1757
1745
|
return item.event;
|
|
1758
1746
|
},
|
|
@@ -1778,7 +1766,7 @@ const MonthView = props => {
|
|
|
1778
1766
|
return cell().hidden > 0;
|
|
1779
1767
|
},
|
|
1780
1768
|
get children() {
|
|
1781
|
-
return _$ssr(_tmpl$
|
|
1769
|
+
return _$ssr(_tmpl$25, _$ssrStyleProperty("--k2b-calendar-row:", _$escape(String(cell().top + cell().shown.length), true)), _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarMoreEventsOn({
|
|
1782
1770
|
count: cell().hidden,
|
|
1783
1771
|
label
|
|
1784
1772
|
}), true), false), _$ssrAttribute("aria-expanded", (() => {
|
|
@@ -1798,19 +1786,19 @@ const MonthView = props => {
|
|
|
1798
1786
|
const href = viewHref(dayKey, "day");
|
|
1799
1787
|
// Read where it renders, so a refresh while the list is open updates it as it does the grid.
|
|
1800
1788
|
const entries = () => dayEntries(dayKey);
|
|
1801
|
-
return _$ssr(_tmpl$
|
|
1789
|
+
return _$ssr(_tmpl$30, _$escape(dayLabel(day)), _$escape(_$createComponent(Show, {
|
|
1802
1790
|
get when() {
|
|
1803
1791
|
return entries().length > 0;
|
|
1804
1792
|
},
|
|
1805
1793
|
get fallback() {
|
|
1806
|
-
return _$ssr(_tmpl$
|
|
1794
|
+
return _$ssr(_tmpl$31, _$escape(calendarMessages().calendarNothingPlanned));
|
|
1807
1795
|
},
|
|
1808
1796
|
get children() {
|
|
1809
|
-
return _$ssr(_tmpl$
|
|
1797
|
+
return _$ssr(_tmpl$28, _$escape(_$createComponent(For, {
|
|
1810
1798
|
get each() {
|
|
1811
1799
|
return entries();
|
|
1812
1800
|
},
|
|
1813
|
-
children: item => _$ssr(_tmpl$
|
|
1801
|
+
children: item => _$ssr(_tmpl$32, _$escape(_$createComponent(EventChip, {
|
|
1814
1802
|
get event() {
|
|
1815
1803
|
return item.event;
|
|
1816
1804
|
},
|
|
@@ -1847,7 +1835,7 @@ const MonthView = props => {
|
|
|
1847
1835
|
size: "sm",
|
|
1848
1836
|
onClick: () => openView(dayKey, "day"),
|
|
1849
1837
|
get children() {
|
|
1850
|
-
return [_$ssr(_tmpl$
|
|
1838
|
+
return [_$ssr(_tmpl$33), calendarMessages().calendarOpenDay];
|
|
1851
1839
|
}
|
|
1852
1840
|
});
|
|
1853
1841
|
}
|
|
@@ -1866,7 +1854,7 @@ const MonthView = props => {
|
|
|
1866
1854
|
"data-size": "sm"
|
|
1867
1855
|
},
|
|
1868
1856
|
get children() {
|
|
1869
|
-
return [_$ssr(_tmpl$
|
|
1857
|
+
return [_$ssr(_tmpl$33), calendarMessages().calendarOpenDay];
|
|
1870
1858
|
}
|
|
1871
1859
|
})
|
|
1872
1860
|
})), _$escape(_$createComponent(Show, {
|
|
@@ -1888,7 +1876,7 @@ const MonthView = props => {
|
|
|
1888
1876
|
});
|
|
1889
1877
|
},
|
|
1890
1878
|
get children() {
|
|
1891
|
-
return [_$ssr(_tmpl$
|
|
1879
|
+
return [_$ssr(_tmpl$29), calendarMessages().calendarNewEvent];
|
|
1892
1880
|
}
|
|
1893
1881
|
});
|
|
1894
1882
|
}
|
|
@@ -1917,7 +1905,7 @@ const MonthView = props => {
|
|
|
1917
1905
|
}
|
|
1918
1906
|
});
|
|
1919
1907
|
}
|
|
1920
|
-
}), _$ssr(_tmpl$
|
|
1908
|
+
}), _$ssr(_tmpl$34, _$ssrAttribute("aria-label", (() => {
|
|
1921
1909
|
const current = popover();
|
|
1922
1910
|
if (current?.kind === "day") return dayLabel(parseKey(current.dayKey));
|
|
1923
1911
|
return _$escape(calendarMessages().calendarQuickCreate, true);
|
|
@@ -2106,10 +2094,12 @@ const TimeGridView = props => {
|
|
|
2106
2094
|
}
|
|
2107
2095
|
return [...groups.values()];
|
|
2108
2096
|
};
|
|
2097
|
+
// 12 rem per lane. The 40 rem grid is wider than one or two lanes, so only
|
|
2098
|
+
// three or more make the day scroll, and one lane fits beside a tablet drawer.
|
|
2109
2099
|
const dayColumnMinWidth = layouts => {
|
|
2110
2100
|
if (!isDayView()) return undefined;
|
|
2111
2101
|
const lanes = Math.max(1, ...layouts.map(layout => layout.lanes));
|
|
2112
|
-
return `${
|
|
2102
|
+
return `${lanes * 12}rem`;
|
|
2113
2103
|
};
|
|
2114
2104
|
const laneStyle = layoutItem => {
|
|
2115
2105
|
if (isDayView()) {
|
|
@@ -2145,7 +2135,7 @@ const TimeGridView = props => {
|
|
|
2145
2135
|
});
|
|
2146
2136
|
});
|
|
2147
2137
|
});
|
|
2148
|
-
return _$ssr(_tmpl$
|
|
2138
|
+
return _$ssr(_tmpl$36, _$ssrAttribute("data-view", isDayView() ? "day" : "week", false), _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`), _$escape(_$createComponent(For, {
|
|
2149
2139
|
get each() {
|
|
2150
2140
|
return props.days;
|
|
2151
2141
|
},
|
|
@@ -2163,13 +2153,13 @@ const TimeGridView = props => {
|
|
|
2163
2153
|
class: "k2b-calendar-time-grid__day"
|
|
2164
2154
|
},
|
|
2165
2155
|
get children() {
|
|
2166
|
-
return [_$ssr(_tmpl$
|
|
2156
|
+
return [_$ssr(_tmpl$37, _$ssrAttribute("data-today", today() ? "true" : _$escape(undefined, true), false), _$escape(formatDay(day, dateConfig()))), _$createComponent(Show, {
|
|
2167
2157
|
when: dayBadge,
|
|
2168
|
-
children: badge => _$ssr(_tmpl$
|
|
2158
|
+
children: badge => _$ssr(_tmpl$38, _$escape(_$createComponent(Show, {
|
|
2169
2159
|
get when() {
|
|
2170
2160
|
return badge().icon;
|
|
2171
2161
|
},
|
|
2172
|
-
children: icon => _$ssr(_tmpl$
|
|
2162
|
+
children: icon => _$ssr(_tmpl$2, `k2b-calendar-time-grid__badge-icon ti ti-${_$escape(icon(), true)}`)
|
|
2173
2163
|
})), _$escape(badge().label))
|
|
2174
2164
|
})];
|
|
2175
2165
|
}
|
|
@@ -2180,7 +2170,7 @@ const TimeGridView = props => {
|
|
|
2180
2170
|
return !props.owner.hideAllDay;
|
|
2181
2171
|
},
|
|
2182
2172
|
get children() {
|
|
2183
|
-
return _$ssr(_tmpl$
|
|
2173
|
+
return _$ssr(_tmpl$35, _$ssrStyleProperty("grid-template-columns:", `4rem repeat(${_$escape(props.days.length, true)}, minmax(0, 1fr))`) + _$ssrStyleProperty(";max-height:", `${_$escape(props.owner.allDayMaxHeightRem ?? 7, true)}rem`), _$escape(props.labels.allDay), _$escape(_$createComponent(For, {
|
|
2184
2174
|
get each() {
|
|
2185
2175
|
return props.days;
|
|
2186
2176
|
},
|
|
@@ -2204,9 +2194,9 @@ const TimeGridView = props => {
|
|
|
2204
2194
|
end: calendar.addDays(start, 1, dateConfig()),
|
|
2205
2195
|
allDay: true
|
|
2206
2196
|
};
|
|
2207
|
-
}, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$
|
|
2197
|
+
}, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$39, _$escape(_$createComponent(For, {
|
|
2208
2198
|
each: previewAllDay,
|
|
2209
|
-
children: event => _$ssr(_tmpl$
|
|
2199
|
+
children: event => _$ssr(_tmpl$14, _$escape(event.title))
|
|
2210
2200
|
})), _$escape(_$createComponent(For, {
|
|
2211
2201
|
get each() {
|
|
2212
2202
|
return allDay();
|
|
@@ -2235,7 +2225,7 @@ const TimeGridView = props => {
|
|
|
2235
2225
|
get each() {
|
|
2236
2226
|
return hours();
|
|
2237
2227
|
},
|
|
2238
|
-
children: hour => _$ssr(_tmpl$
|
|
2228
|
+
children: hour => _$ssr(_tmpl$40, _$ssrAttribute("data-outside-business", hour < businessStartHour() || hour > businessEndHour() ? "true" : _$escape(undefined, true), false), _$escape(`${hour}`.padStart(2, "0")))
|
|
2239
2229
|
})), _$escape(_$createComponent(For, {
|
|
2240
2230
|
get each() {
|
|
2241
2231
|
return props.days;
|
|
@@ -2243,12 +2233,12 @@ const TimeGridView = props => {
|
|
|
2243
2233
|
children: day => {
|
|
2244
2234
|
const dayKey = calendar.formatDateKey(day, dateConfig());
|
|
2245
2235
|
const layouts = createMemo(() => timedEventLayouts(eventsByDay().get(dayKey)?.timed ?? []));
|
|
2246
|
-
return _$ssr(_tmpl$
|
|
2236
|
+
return _$ssr(_tmpl$42, _$ssrStyleProperty("min-width:", _$escape(dayColumnMinWidth(layouts()), true)) + _$ssrStyleProperty(";grid-template-rows:", `repeat(${_$escape(hours().length, true)}, minmax(4rem, 1fr))`), _$escape(_$createComponent(Show, {
|
|
2247
2237
|
get when() {
|
|
2248
2238
|
return currentTimeLine(day) !== null;
|
|
2249
2239
|
},
|
|
2250
2240
|
get children() {
|
|
2251
|
-
return _$ssr(_tmpl$
|
|
2241
|
+
return _$ssr(_tmpl$41, _$ssrStyleProperty("top:", `${_$escape(currentTimeLine(day) ?? 0, true)}%`));
|
|
2252
2242
|
}
|
|
2253
2243
|
})), _$escape(_$createComponent(For, {
|
|
2254
2244
|
get each() {
|
|
@@ -2277,12 +2267,12 @@ const TimeGridView = props => {
|
|
|
2277
2267
|
children: event => {
|
|
2278
2268
|
const layout = eventLayout(event);
|
|
2279
2269
|
const short = event.endDate.getTime() - event.startDate.getTime() < 60 * 60_000;
|
|
2280
|
-
return _$ssr(_tmpl$
|
|
2270
|
+
return _$ssr(_tmpl$44, _$ssrAttribute("data-short", short ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$escape(_$createComponent(Show, {
|
|
2281
2271
|
get when() {
|
|
2282
2272
|
return event.title;
|
|
2283
2273
|
},
|
|
2284
2274
|
get children() {
|
|
2285
|
-
return _$ssr(_tmpl$
|
|
2275
|
+
return _$ssr(_tmpl$43, _$escape(event.title));
|
|
2286
2276
|
}
|
|
2287
2277
|
})), _$escape(formatTime(event.startDate, dateConfig())), _$escape(formatTime(event.endDate, dateConfig())));
|
|
2288
2278
|
}
|
|
@@ -2328,7 +2318,7 @@ const TimeGridView = props => {
|
|
|
2328
2318
|
onCancel: clearInteraction
|
|
2329
2319
|
});
|
|
2330
2320
|
};
|
|
2331
|
-
return _$ssr(_tmpl$
|
|
2321
|
+
return _$ssr(_tmpl$46, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`) + _$ssrStyleProperty(";left:", _$escape(position.left, true)) + _$ssrStyleProperty(";width:", _$escape(position.width, true)) + _$ssrStyleProperty(";z-index:", _$escape(String(20 + layoutItem.lane), true)), _$escape(_$createComponent(EventChip, {
|
|
2332
2322
|
event: event,
|
|
2333
2323
|
get owner() {
|
|
2334
2324
|
return props.owner;
|
|
@@ -2348,7 +2338,7 @@ const TimeGridView = props => {
|
|
|
2348
2338
|
return props.owner.onEventResize;
|
|
2349
2339
|
},
|
|
2350
2340
|
get children() {
|
|
2351
|
-
return _$ssr(_tmpl$
|
|
2341
|
+
return _$ssr(_tmpl$45, _$ssrAttribute("aria-label", _$escape(calendarMessages().resizeEvent, true), false));
|
|
2352
2342
|
}
|
|
2353
2343
|
})));
|
|
2354
2344
|
}
|
|
@@ -2360,14 +2350,14 @@ const TimeGridView = props => {
|
|
|
2360
2350
|
const layout = timeRangeLayout(overflow.groupStartDate, overflow.groupEndDate);
|
|
2361
2351
|
const key = `${dayKey}-${overflow.groupId}`;
|
|
2362
2352
|
const hiddenTitle = () => overflow.hiddenEvents.map(event => `${formatTime(event.startDate, dateConfig())} ${event.title}`).join("\n");
|
|
2363
|
-
return [_$ssr(_tmpl$
|
|
2353
|
+
return [_$ssr(_tmpl$47, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$ssrAttribute("title", _$escape(hiddenTitle(), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().hiddenOverlappingEvents({
|
|
2364
2354
|
count: overflow.hiddenEvents.length
|
|
2365
2355
|
}), true), false), _$escape(overflow.hiddenEvents.length)), _$createComponent(Show, {
|
|
2366
2356
|
get when() {
|
|
2367
2357
|
return expandedOverflow() === key;
|
|
2368
2358
|
},
|
|
2369
2359
|
get children() {
|
|
2370
|
-
return _$ssr(_tmpl$
|
|
2360
|
+
return _$ssr(_tmpl$48, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`), _$escape(formatTime(overflow.groupStartDate, dateConfig())), _$escape(formatTime(overflow.groupEndDate, dateConfig())), _$escape(_$createComponent(For, {
|
|
2371
2361
|
get each() {
|
|
2372
2362
|
return overflow.hiddenEvents;
|
|
2373
2363
|
},
|
|
@@ -2426,11 +2416,11 @@ const YearView = props => {
|
|
|
2426
2416
|
};
|
|
2427
2417
|
});
|
|
2428
2418
|
});
|
|
2429
|
-
return _$ssr(_tmpl$
|
|
2419
|
+
return _$ssr(_tmpl$49, _$escape(_$createComponent(For, {
|
|
2430
2420
|
get each() {
|
|
2431
2421
|
return months();
|
|
2432
2422
|
},
|
|
2433
|
-
children: month => _$ssr(_tmpl$
|
|
2423
|
+
children: month => _$ssr(_tmpl$50, _$escape(month.label), _$escape(_$createComponent(For, {
|
|
2434
2424
|
get each() {
|
|
2435
2425
|
return month.days;
|
|
2436
2426
|
},
|
|
@@ -2453,7 +2443,7 @@ const YearView = props => {
|
|
|
2453
2443
|
get when() {
|
|
2454
2444
|
return day.events[0];
|
|
2455
2445
|
},
|
|
2456
|
-
children: event => _$ssr(_tmpl$
|
|
2446
|
+
children: event => _$ssr(_tmpl$51, _$ssrAttribute("data-color", event().colorHex ? _$escape(undefined, true) : _$escape(event().color ?? "blue", true), false) + _$ssrAttribute("data-today", day.isToday ? "true" : _$escape(undefined, true), false), _$ssrStyle(event().colorHex ? {
|
|
2457
2447
|
"background-color": day.isToday ? "white" : event().colorHex
|
|
2458
2448
|
} : undefined))
|
|
2459
2449
|
})];
|
|
@@ -2466,7 +2456,7 @@ const MobileMonthView = props => {
|
|
|
2466
2456
|
const dateConfig = createMemo(() => ownerDateConfig(props.owner));
|
|
2467
2457
|
const selectedDateKey = createMemo(() => calendar.formatDateKey(props.selectedDate, dateConfig()));
|
|
2468
2458
|
const selectedEvents = createMemo(() => props.events.filter(event => event.dayKey === selectedDateKey()));
|
|
2469
|
-
return _$ssr(_tmpl$
|
|
2459
|
+
return _$ssr(_tmpl$53, _$escape(_$createComponent(MonthPickerView, {
|
|
2470
2460
|
get owner() {
|
|
2471
2461
|
return {
|
|
2472
2462
|
...props.owner,
|
|
@@ -2496,10 +2486,10 @@ const MobileMonthView = props => {
|
|
|
2496
2486
|
return selectedEvents().length > 0;
|
|
2497
2487
|
},
|
|
2498
2488
|
get fallback() {
|
|
2499
|
-
return _$ssr(_tmpl$
|
|
2489
|
+
return _$ssr(_tmpl$54, _$escape(props.labels.noEvents));
|
|
2500
2490
|
},
|
|
2501
2491
|
get children() {
|
|
2502
|
-
return _$ssr(_tmpl$
|
|
2492
|
+
return _$ssr(_tmpl$52, _$escape(_$createComponent(For, {
|
|
2503
2493
|
get each() {
|
|
2504
2494
|
return selectedEvents();
|
|
2505
2495
|
},
|
|
@@ -2516,7 +2506,7 @@ const MobileMonthView = props => {
|
|
|
2516
2506
|
}
|
|
2517
2507
|
})));
|
|
2518
2508
|
};
|
|
2519
|
-
const CalendarBody = props => _$ssr(_tmpl$
|
|
2509
|
+
const CalendarBody = props => _$ssr(_tmpl$55, _$escape(props.children));
|
|
2520
2510
|
const CalendarRoot = props => {
|
|
2521
2511
|
const messages = useUiMessages();
|
|
2522
2512
|
const calendarMessages = useCalendarMessages();
|
|
@@ -2566,7 +2556,181 @@ const CalendarRoot = props => {
|
|
|
2566
2556
|
document.removeEventListener("visibilitychange", updateNow);
|
|
2567
2557
|
});
|
|
2568
2558
|
});
|
|
2569
|
-
|
|
2559
|
+
|
|
2560
|
+
// The day and week views with `dayHours` scroll through their days; the header and the commands ask them first.
|
|
2561
|
+
const [timeView, setTimeView] = createSignal(null);
|
|
2562
|
+
const [monthCreate, setMonthCreate] = createSignal(null);
|
|
2563
|
+
const timeMode = () => Boolean(props.dayHours) && (view() === "day" || view() === "week");
|
|
2564
|
+
const parseKey = key => calendar.parseCalendarDate(key, dateConfig());
|
|
2565
|
+
/** The first shown day of a day or week view, or the selected day of the month view, for the other views. */
|
|
2566
|
+
const shownDay = () => {
|
|
2567
|
+
const first = timeView()?.visibleKeys().first;
|
|
2568
|
+
if (first) return parseKey(first);
|
|
2569
|
+
return view() === "month" ? focusDay() : null;
|
|
2570
|
+
};
|
|
2571
|
+
const go = (target, nextView) => {
|
|
2572
|
+
const href = props.getDateHref?.(target, nextView);
|
|
2573
|
+
if (href) followCalendarHref(owner, href);else openViewAt(props, target, nextView);
|
|
2574
|
+
};
|
|
2575
|
+
const step = direction => {
|
|
2576
|
+
if (timeView()?.step(direction)) return;
|
|
2577
|
+
go(adjacentCalendarDate(shownDay() ?? date(), view(), direction, dateConfig()), view());
|
|
2578
|
+
};
|
|
2579
|
+
const goToday = () => {
|
|
2580
|
+
if (timeView()?.today()) return;
|
|
2581
|
+
go(calendar.today(dateConfig()), view());
|
|
2582
|
+
};
|
|
2583
|
+
const goView = nextView => {
|
|
2584
|
+
const day = shownDay();
|
|
2585
|
+
if (day) {
|
|
2586
|
+
go(day, nextView);
|
|
2587
|
+
return;
|
|
2588
|
+
}
|
|
2589
|
+
const href = props.getViewHref?.(nextView);
|
|
2590
|
+
if (href) followCalendarHref(owner, href);else props.onViewChange?.(nextView);
|
|
2591
|
+
};
|
|
2592
|
+
const goToKey = key => {
|
|
2593
|
+
if (timeView()?.goTo(key)) return;
|
|
2594
|
+
go(parseKey(key), view());
|
|
2595
|
+
};
|
|
2596
|
+
const openGoTo = () => void openCalendarGoTo({
|
|
2597
|
+
messages: calendarMessages(),
|
|
2598
|
+
today: calendar.formatDateKey(new Date(), dateConfig()),
|
|
2599
|
+
describe: key => parseKey(key).toLocaleDateString(dateConfig().locale ?? "en", {
|
|
2600
|
+
weekday: "long",
|
|
2601
|
+
day: "numeric",
|
|
2602
|
+
month: "long",
|
|
2603
|
+
year: "numeric",
|
|
2604
|
+
timeZone: dateConfig().timeZone
|
|
2605
|
+
}),
|
|
2606
|
+
onGo: goToKey
|
|
2607
|
+
});
|
|
2608
|
+
const ownCommands = createMemo(() => {
|
|
2609
|
+
const text = calendarMessages();
|
|
2610
|
+
const available = ["day", "week", "month", "year"].filter(option => !props.views || props.views.includes(option));
|
|
2611
|
+
const viewLabels = {
|
|
2612
|
+
day: mergedLabels().day,
|
|
2613
|
+
week: mergedLabels().week,
|
|
2614
|
+
month: mergedLabels().month,
|
|
2615
|
+
year: mergedLabels().year
|
|
2616
|
+
};
|
|
2617
|
+
return [{
|
|
2618
|
+
id: "calendar.today",
|
|
2619
|
+
label: text.calendarCommandToday,
|
|
2620
|
+
description: text.calendarCommandTodayDescription,
|
|
2621
|
+
shortcut: "h",
|
|
2622
|
+
icon: "ti ti-calendar-event",
|
|
2623
|
+
run: goToday
|
|
2624
|
+
}, {
|
|
2625
|
+
id: "calendar.next",
|
|
2626
|
+
label: text.calendarCommandNext,
|
|
2627
|
+
description: text.calendarCommandNextDescription,
|
|
2628
|
+
shortcut: "j",
|
|
2629
|
+
icon: "ti ti-chevron-right",
|
|
2630
|
+
run: () => step(1)
|
|
2631
|
+
}, {
|
|
2632
|
+
id: "calendar.previous",
|
|
2633
|
+
label: text.calendarCommandPrevious,
|
|
2634
|
+
description: text.calendarCommandPreviousDescription,
|
|
2635
|
+
shortcut: "k",
|
|
2636
|
+
icon: "ti ti-chevron-left",
|
|
2637
|
+
run: () => step(-1)
|
|
2638
|
+
}, ...available.map((option, index) => ({
|
|
2639
|
+
id: `calendar.view.${option}`,
|
|
2640
|
+
label: text.calendarCommandView({
|
|
2641
|
+
view: viewLabels[option]
|
|
2642
|
+
}),
|
|
2643
|
+
description: text.calendarCommandViewDescription({
|
|
2644
|
+
view: viewLabels[option]
|
|
2645
|
+
}),
|
|
2646
|
+
shortcut: String(index + 1),
|
|
2647
|
+
icon: "ti ti-layout-columns",
|
|
2648
|
+
run: () => goView(option)
|
|
2649
|
+
})), {
|
|
2650
|
+
id: "calendar.goto",
|
|
2651
|
+
label: text.calendarCommandGoTo,
|
|
2652
|
+
description: text.calendarCommandGoToDescription,
|
|
2653
|
+
shortcut: "g",
|
|
2654
|
+
icon: "ti ti-calendar-search",
|
|
2655
|
+
run: openGoTo
|
|
2656
|
+
}];
|
|
2657
|
+
});
|
|
2658
|
+
const allCommands = createMemo(() => [...ownCommands(), ...(props.commands ?? [])]);
|
|
2659
|
+
/** While the month's quiet quick create waits for typing, a single key is the first letter of a title. */
|
|
2660
|
+
const typing = () => view() === "month" && (monthCreate()?.typing() ?? false);
|
|
2661
|
+
createEffect(() => {
|
|
2662
|
+
const commands = typing() ? allCommands().map(command => command.shortcut && singleKey(command.shortcut) ? {
|
|
2663
|
+
...command,
|
|
2664
|
+
shortcut: undefined
|
|
2665
|
+
} : command) : allCommands();
|
|
2666
|
+
untrack(() => props.onCommandsChange?.(commands));
|
|
2667
|
+
});
|
|
2668
|
+
// The arrow keys page like J and K while the keyboard is in the calendar or nowhere, unless something there uses
|
|
2669
|
+
// them, such as the grid of the week or the month.
|
|
2670
|
+
let root;
|
|
2671
|
+
onMount(() => {
|
|
2672
|
+
const onKeyDown = event => {
|
|
2673
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
2674
|
+
if (event.defaultPrevented || event.isComposing || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
2675
|
+
if (!props.onCommandsChange || custom() || document.querySelector('dialog[open], [role="dialog"][aria-modal="true"]')) return;
|
|
2676
|
+
const target = event.target;
|
|
2677
|
+
const inCalendar = target instanceof Element && Boolean(root?.contains(target));
|
|
2678
|
+
if (!inCalendar && target !== document.body && target !== document.documentElement) return;
|
|
2679
|
+
if (target instanceof Element && target.closest("input, textarea, select, [contenteditable]:not([contenteditable=false]), [role=textbox], [popover], [role=dialog]")) return;
|
|
2680
|
+
event.preventDefault();
|
|
2681
|
+
step(event.key === "ArrowRight" ? 1 : -1);
|
|
2682
|
+
};
|
|
2683
|
+
window.addEventListener("keydown", onKeyDown);
|
|
2684
|
+
onCleanup(() => window.removeEventListener("keydown", onKeyDown));
|
|
2685
|
+
});
|
|
2686
|
+
const headerNav = {
|
|
2687
|
+
timeView,
|
|
2688
|
+
commands: () => props.onCommandsChange ? allCommands() : [],
|
|
2689
|
+
// The arrow keys page like J and K, so the list names them beside those keys.
|
|
2690
|
+
openShortcuts: () => void openCalendarShortcuts(allCommands(), calendarMessages(), custom() ? {} : {
|
|
2691
|
+
"calendar.next": "arrowright",
|
|
2692
|
+
"calendar.previous": "arrowleft"
|
|
2693
|
+
})
|
|
2694
|
+
};
|
|
2695
|
+
const controller = {
|
|
2696
|
+
quickCreate: create => {
|
|
2697
|
+
const active = timeView();
|
|
2698
|
+
if (active) active.controller.quickCreate(create);else monthCreate()?.quickCreate(create);
|
|
2699
|
+
},
|
|
2700
|
+
createTarget: () => {
|
|
2701
|
+
const active = timeView()?.controller.createTarget() ?? monthCreate()?.createTarget();
|
|
2702
|
+
if (active) return active;
|
|
2703
|
+
const start = calendar.today(dateConfig());
|
|
2704
|
+
return {
|
|
2705
|
+
start,
|
|
2706
|
+
end: calendar.addDays(start, 1, dateConfig()),
|
|
2707
|
+
allDay: true
|
|
2708
|
+
};
|
|
2709
|
+
},
|
|
2710
|
+
dragIn: (event, item, onDrop) => timeView()?.controller.dragIn(event, item, onDrop)
|
|
2711
|
+
};
|
|
2712
|
+
onMount(() => props.controller?.(controller));
|
|
2713
|
+
const timeProps = timeViewName => ({
|
|
2714
|
+
owner,
|
|
2715
|
+
view: timeViewName,
|
|
2716
|
+
get date() {
|
|
2717
|
+
return date();
|
|
2718
|
+
},
|
|
2719
|
+
get now() {
|
|
2720
|
+
return now();
|
|
2721
|
+
},
|
|
2722
|
+
get events() {
|
|
2723
|
+
return props.events;
|
|
2724
|
+
},
|
|
2725
|
+
get labels() {
|
|
2726
|
+
return mergedLabels();
|
|
2727
|
+
},
|
|
2728
|
+
get hours() {
|
|
2729
|
+
return props.dayHours ?? [0, 24];
|
|
2730
|
+
},
|
|
2731
|
+
register: setTimeView
|
|
2732
|
+
});
|
|
2733
|
+
return _$ssr(_tmpl$56, `k2b-content-calendar ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("aria-busy", props.navigationPending ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(CalendarHeader, {
|
|
2570
2734
|
get date() {
|
|
2571
2735
|
return date();
|
|
2572
2736
|
},
|
|
@@ -2578,8 +2742,9 @@ const CalendarRoot = props => {
|
|
|
2578
2742
|
},
|
|
2579
2743
|
owner: owner,
|
|
2580
2744
|
get focusDay() {
|
|
2581
|
-
return _$memo(() => view() === "month")() ? focusDay() : null;
|
|
2582
|
-
}
|
|
2745
|
+
return _$memo(() => view() === "month")() ? focusDay() : _$memo(() => !!timeView())() ? shownDay() : null;
|
|
2746
|
+
},
|
|
2747
|
+
nav: headerNav
|
|
2583
2748
|
})), _$escape(_$createComponent(Show, {
|
|
2584
2749
|
get when() {
|
|
2585
2750
|
return !custom();
|
|
@@ -2613,7 +2778,8 @@ const CalendarRoot = props => {
|
|
|
2613
2778
|
get labels() {
|
|
2614
2779
|
return mergedLabels();
|
|
2615
2780
|
},
|
|
2616
|
-
onFocusDay: setFocusDay
|
|
2781
|
+
onFocusDay: setFocusDay,
|
|
2782
|
+
register: setMonthCreate
|
|
2617
2783
|
});
|
|
2618
2784
|
}
|
|
2619
2785
|
});
|
|
@@ -2671,22 +2837,42 @@ const CalendarRoot = props => {
|
|
|
2671
2837
|
});
|
|
2672
2838
|
},
|
|
2673
2839
|
get children() {
|
|
2674
|
-
return _$createComponent(
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
return date();
|
|
2678
|
-
},
|
|
2679
|
-
get now() {
|
|
2680
|
-
return now();
|
|
2840
|
+
return _$createComponent(Show, {
|
|
2841
|
+
get when() {
|
|
2842
|
+
return timeMode();
|
|
2681
2843
|
},
|
|
2682
|
-
get
|
|
2683
|
-
return
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2844
|
+
get fallback() {
|
|
2845
|
+
return _$createComponent(TimeGridView, {
|
|
2846
|
+
owner: owner,
|
|
2847
|
+
get date() {
|
|
2848
|
+
return date();
|
|
2849
|
+
},
|
|
2850
|
+
get now() {
|
|
2851
|
+
return now();
|
|
2852
|
+
},
|
|
2853
|
+
get events() {
|
|
2854
|
+
return normalizedEvents();
|
|
2855
|
+
},
|
|
2856
|
+
get labels() {
|
|
2857
|
+
return mergedLabels();
|
|
2858
|
+
},
|
|
2859
|
+
get days() {
|
|
2860
|
+
return days();
|
|
2861
|
+
}
|
|
2862
|
+
});
|
|
2687
2863
|
},
|
|
2688
|
-
get
|
|
2689
|
-
return
|
|
2864
|
+
get children() {
|
|
2865
|
+
return _$createComponent(Show, {
|
|
2866
|
+
get when() {
|
|
2867
|
+
return view() === "day";
|
|
2868
|
+
},
|
|
2869
|
+
get fallback() {
|
|
2870
|
+
return _$createComponent(CalendarWeekView, _$mergeProps(() => timeProps("week")));
|
|
2871
|
+
},
|
|
2872
|
+
get children() {
|
|
2873
|
+
return _$createComponent(CalendarDayView, _$mergeProps(() => timeProps("day")));
|
|
2874
|
+
}
|
|
2875
|
+
});
|
|
2690
2876
|
}
|
|
2691
2877
|
});
|
|
2692
2878
|
}
|
|
@@ -2699,6 +2885,9 @@ const CalendarRoot = props => {
|
|
|
2699
2885
|
})));
|
|
2700
2886
|
};
|
|
2701
2887
|
|
|
2888
|
+
/** A shortcut without Ctrl, Meta, or Mod, which typing would set off. */
|
|
2889
|
+
const singleKey = shortcut => !/(^|\+)(ctrl|meta|mod)\+/i.test(shortcut);
|
|
2890
|
+
|
|
2702
2891
|
/** JSX infers the values of `customViews`; inference from the last signature, as in `createComponent`, sees plain props. */
|
|
2703
2892
|
|
|
2704
2893
|
function Calendar(props) {
|