@k2b/ui 0.24.0 → 0.26.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/README.md +2 -2
- package/dist/browser/actions/Dropdown.js +67 -52
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/GestureMenu.js +5 -5
- package/dist/browser/actions/GestureMenu.js.map +1 -1
- package/dist/browser/actions/SpotlightSearch.js +13 -6
- package/dist/browser/actions/SpotlightSearch.js.map +1 -1
- package/dist/browser/actions/Toolbar.js +75 -1
- package/dist/browser/actions/Toolbar.js.map +1 -1
- package/dist/browser/content/Calendar.js +1539 -911
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/CalendarDayView.js +5 -4
- package/dist/browser/content/CalendarDayView.js.map +1 -1
- package/dist/browser/content/CalendarWeekView.js +5 -4
- package/dist/browser/content/CalendarWeekView.js.map +1 -1
- package/dist/browser/content/Kbd.js +51 -0
- package/dist/browser/content/Kbd.js.map +1 -0
- package/dist/browser/content/LabelChip.js +38 -0
- package/dist/browser/content/LabelChip.js.map +1 -0
- package/dist/browser/content/MarkdownView.js +2 -1
- package/dist/browser/content/MarkdownView.js.map +1 -1
- package/dist/browser/content/Steps.js +34 -0
- package/dist/browser/content/Steps.js.map +1 -0
- package/dist/browser/content/Timeline.js +3 -3
- package/dist/browser/content/Timeline.js.map +1 -1
- package/dist/browser/content/VirtualFeed.js +33 -1
- package/dist/browser/content/VirtualFeed.js.map +1 -1
- package/dist/browser/content/calendar-dialogs.js +32 -60
- package/dist/browser/content/calendar-dialogs.js.map +1 -1
- package/dist/browser/content/calendar-month-scroll.js +80 -0
- package/dist/browser/content/calendar-month-scroll.js.map +1 -0
- package/dist/browser/content/calendar-time-view.js +0 -1
- package/dist/browser/content/calendar-time-view.js.map +1 -1
- package/dist/browser/content/index.js +4 -1
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/markdown-info-blocks.js +33 -5
- package/dist/browser/content/markdown-info-blocks.js.map +1 -1
- package/dist/browser/feedback/prompts.js +17 -3
- package/dist/browser/feedback/prompts.js.map +1 -1
- package/dist/browser/index.js +1 -0
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/inputs/Combobox.js +22 -3
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/inputs/QrScanner.js +2 -1
- package/dist/browser/inputs/QrScanner.js.map +1 -1
- package/dist/browser/intl/index.js +1 -0
- package/dist/browser/intl/index.js.map +1 -1
- package/dist/browser/intl/shortcut-messages.js +77 -0
- package/dist/browser/intl/shortcut-messages.js.map +1 -0
- package/dist/browser/intl/shortcut.js +123 -0
- package/dist/browser/intl/shortcut.js.map +1 -0
- package/dist/browser/layout/AppWorkspace.js +355 -338
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/TableOfContents.js +115 -0
- package/dist/browser/layout/TableOfContents.js.map +1 -0
- package/dist/browser/layout/app-workspace-controller.js +7 -50
- 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/scroll-fade.js +14 -9
- package/dist/browser/layout/scroll-fade.js.map +1 -1
- package/dist/browser/layout/sidebar-scroll-memory.js +38 -0
- package/dist/browser/layout/sidebar-scroll-memory.js.map +1 -0
- package/dist/browser/layout/table-of-contents-messages.js +19 -0
- package/dist/browser/layout/table-of-contents-messages.js.map +1 -0
- package/dist/browser/motion.js +7 -0
- package/dist/browser/motion.js.map +1 -0
- package/dist/browser/surfaces/LinkCard.js +40 -24
- package/dist/browser/surfaces/LinkCard.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +11 -5
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/GestureMenu.js +5 -5
- package/dist/ssr/actions/GestureMenu.js.map +1 -1
- package/dist/ssr/actions/SpotlightSearch.js +9 -3
- package/dist/ssr/actions/SpotlightSearch.js.map +1 -1
- package/dist/ssr/actions/Toolbar.js +67 -1
- package/dist/ssr/actions/Toolbar.js.map +1 -1
- package/dist/ssr/content/Calendar.js +864 -312
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/CalendarDayView.js +5 -4
- package/dist/ssr/content/CalendarDayView.js.map +1 -1
- package/dist/ssr/content/CalendarWeekView.js +5 -4
- package/dist/ssr/content/CalendarWeekView.js.map +1 -1
- package/dist/ssr/content/Kbd.js +38 -0
- package/dist/ssr/content/Kbd.js.map +1 -0
- package/dist/ssr/content/LabelChip.js +21 -0
- package/dist/ssr/content/LabelChip.js.map +1 -0
- package/dist/ssr/content/MarkdownView.js +2 -1
- package/dist/ssr/content/MarkdownView.js.map +1 -1
- package/dist/ssr/content/Steps.js +14 -0
- package/dist/ssr/content/Steps.js.map +1 -0
- package/dist/ssr/content/Timeline.js +3 -3
- package/dist/ssr/content/Timeline.js.map +1 -1
- package/dist/ssr/content/VirtualFeed.js +33 -1
- package/dist/ssr/content/VirtualFeed.js.map +1 -1
- package/dist/ssr/content/calendar-dialogs.js +12 -32
- package/dist/ssr/content/calendar-dialogs.js.map +1 -1
- package/dist/ssr/content/calendar-month-scroll.js +80 -0
- package/dist/ssr/content/calendar-month-scroll.js.map +1 -0
- package/dist/ssr/content/calendar-time-view.js +0 -1
- package/dist/ssr/content/calendar-time-view.js.map +1 -1
- package/dist/ssr/content/index.js +4 -1
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/markdown-info-blocks.js +33 -5
- package/dist/ssr/content/markdown-info-blocks.js.map +1 -1
- package/dist/ssr/feedback/prompts.js +17 -3
- package/dist/ssr/feedback/prompts.js.map +1 -1
- package/dist/ssr/index.js +1 -0
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/inputs/Combobox.js +18 -3
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/inputs/QrScanner.js +2 -1
- package/dist/ssr/inputs/QrScanner.js.map +1 -1
- package/dist/ssr/intl/index.js +1 -0
- package/dist/ssr/intl/index.js.map +1 -1
- package/dist/ssr/intl/shortcut-messages.js +77 -0
- package/dist/ssr/intl/shortcut-messages.js.map +1 -0
- package/dist/ssr/intl/shortcut.js +123 -0
- package/dist/ssr/intl/shortcut.js.map +1 -0
- package/dist/ssr/layout/AppWorkspace.js +77 -72
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/TableOfContents.js +79 -0
- package/dist/ssr/layout/TableOfContents.js.map +1 -0
- package/dist/ssr/layout/app-workspace-controller.js +7 -50
- 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/scroll-fade.js +14 -9
- package/dist/ssr/layout/scroll-fade.js.map +1 -1
- package/dist/ssr/layout/sidebar-scroll-memory.js +38 -0
- package/dist/ssr/layout/sidebar-scroll-memory.js.map +1 -0
- package/dist/ssr/layout/table-of-contents-messages.js +19 -0
- package/dist/ssr/layout/table-of-contents-messages.js.map +1 -0
- package/dist/ssr/motion.js +7 -0
- package/dist/ssr/motion.js.map +1 -0
- package/dist/ssr/surfaces/LinkCard.js +26 -10
- package/dist/ssr/surfaces/LinkCard.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Dropdown.d.ts +12 -0
- package/dist/types/actions/SpotlightSearch.d.ts +2 -0
- package/dist/types/content/Calendar.d.ts +16 -6
- package/dist/types/content/Kbd.d.ts +16 -0
- package/dist/types/content/LabelChip.d.ts +12 -0
- package/dist/types/content/MarkdownView.d.ts +2 -1
- package/dist/types/content/Steps.d.ts +12 -0
- package/dist/types/content/VirtualFeed.d.ts +8 -0
- package/dist/types/content/calendar-dialogs.d.ts +0 -2
- package/dist/types/content/calendar-month-scroll.d.ts +25 -0
- package/dist/types/content/calendar-time-view.d.ts +0 -1
- package/dist/types/content/index.d.ts +7 -1
- package/dist/types/content/markdown-info-blocks.d.ts +21 -4
- package/dist/types/feedback/prompts.d.ts +8 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/inputs/Combobox.d.ts +1 -0
- package/dist/types/intl/index.d.ts +2 -0
- package/dist/types/intl/shortcut-messages.d.ts +35 -0
- package/dist/types/intl/shortcut.d.ts +29 -0
- package/dist/types/layout/AppWorkspace.d.ts +3 -1
- package/dist/types/layout/TableOfContents.d.ts +24 -0
- package/dist/types/layout/index.d.ts +2 -0
- package/dist/types/layout/scroll-fade.d.ts +2 -0
- package/dist/types/layout/sidebar-scroll-memory.d.ts +6 -0
- package/dist/types/layout/table-of-contents-messages.d.ts +4 -0
- package/dist/types/motion.d.ts +6 -0
- package/dist/types/surfaces/LinkCard.d.ts +3 -0
- package/package.json +3 -3
|
@@ -27,58 +27,63 @@ var _tmpl$ = ["<div role=\"radiogroup\"", " aria-orientation=\"horizontal\" clas
|
|
|
27
27
|
_tmpl$16 = ["<span class=\"k2b-calendar-month__day-number\"", ">", "</span>"],
|
|
28
28
|
_tmpl$17 = ["<span class=\"k2b-calendar-month__badge\">", "", "</span>"],
|
|
29
29
|
_tmpl$18 = ["<span class=\"k2b-calendar-dot\"", " style=\"", "\"></span>"],
|
|
30
|
-
_tmpl$19 = ["<div class=\"k2b-calendar-
|
|
31
|
-
_tmpl$20 = ["<div class=\"k2b-calendar-
|
|
32
|
-
_tmpl$21 = ["<
|
|
33
|
-
_tmpl$22 = ["<
|
|
34
|
-
_tmpl$23 = ["<div class=\"k2b-calendar-
|
|
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 = ["<
|
|
42
|
-
_tmpl$31 =
|
|
43
|
-
_tmpl$32 = ["<
|
|
44
|
-
_tmpl$33 = "<
|
|
45
|
-
_tmpl$34 = ["<
|
|
46
|
-
_tmpl$35 =
|
|
47
|
-
_tmpl$36 = ["<div class=\"k2b-calendar-
|
|
48
|
-
_tmpl$37 = ["<
|
|
49
|
-
_tmpl$38 = ["<
|
|
50
|
-
_tmpl$39 = ["<
|
|
51
|
-
_tmpl$40 = ["<
|
|
52
|
-
_tmpl$41 = ["<div class=\"k2b-calendar-time-
|
|
53
|
-
_tmpl$42 = ["<div class=\"k2b-calendar-time-
|
|
54
|
-
_tmpl$43 = ["<div class=\"k2b-calendar-
|
|
55
|
-
_tmpl$44 = ["<div class=\"k2b-calendar-
|
|
56
|
-
_tmpl$45 = ["<
|
|
57
|
-
_tmpl$46 = ["<div class=\"k2b-calendar-
|
|
58
|
-
_tmpl$47 = ["<button type=\"button\" class=\"k2b-calendar-time-
|
|
59
|
-
_tmpl$48 = ["<div class=\"k2b-calendar-time-
|
|
60
|
-
_tmpl$49 = ["<
|
|
61
|
-
_tmpl$50 = ["<div class=\"k2b-calendar-
|
|
62
|
-
_tmpl$51 = ["<
|
|
63
|
-
_tmpl$52 = ["<div class=\"k2b-calendar-
|
|
64
|
-
_tmpl$53 = ["<
|
|
65
|
-
_tmpl$54 = ["<div class=\"k2b-calendar-mobile-
|
|
66
|
-
_tmpl$55 = ["<div class=\"k2b-calendar-
|
|
67
|
-
_tmpl$56 = ["<
|
|
30
|
+
_tmpl$19 = ["<div class=\"k2b-calendar-month__week-number\" role=\"rowheader\">", "</div>"],
|
|
31
|
+
_tmpl$20 = ["<div class=\"k2b-calendar-month__week\" role=\"row\"", " style=\"", "\"", ">", "", "</div>"],
|
|
32
|
+
_tmpl$21 = ["<button type=\"button\" class=\"k2b-calendar-month__week-link\" tabindex=\"-1\"", ">", "</button>"],
|
|
33
|
+
_tmpl$22 = ["<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>"],
|
|
34
|
+
_tmpl$23 = ["<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>"],
|
|
35
|
+
_tmpl$24 = ["<div class=\"k2b-calendar-month__segment\" style=\"", "\">", "</div>"],
|
|
36
|
+
_tmpl$25 = ["<div class=\"k2b-calendar-month__weekday\" role=\"columnheader\">", "</div>"],
|
|
37
|
+
_tmpl$26 = ["<div class=\"k2b-calendar-month__weekdays\" role=\"row\"", ">", "", "</div>"],
|
|
38
|
+
_tmpl$27 = ["<div class=\"k2b-calendar-month__weekday\" role=\"columnheader\"", ">", "</div>"],
|
|
39
|
+
_tmpl$28 = ["<div class=\"k2b-calendar-month\" role=\"grid\"", " aria-multiselectable=\"true\" data-lanes=\"true\" style=\"", "\">", "", "</div>"],
|
|
40
|
+
_tmpl$29 = ["<div class=\"k2b-calendar-month-viewport\"><div class=\"k2b-calendar-month\" role=\"grid\"", " aria-multiselectable=\"true\" data-lanes=\"true\" data-continuous=\"true\"", " style=\"", "\">", "<div class=\"k2b-calendar-month__track\" role=\"rowgroup\" style=\"", "\">", "</div></div><div class=\"k2b-calendar-month__scroll-label\" aria-hidden=\"true\"", ">", "</div></div>"],
|
|
41
|
+
_tmpl$30 = ["<ul class=\"k2b-calendar-day-list__events\">", "</ul>"],
|
|
42
|
+
_tmpl$31 = "<i class=\"ti ti-plus\" aria-hidden=\"true\"></i>",
|
|
43
|
+
_tmpl$32 = ["<div class=\"k2b-calendar-day-list\"><div class=\"k2b-calendar-day-list__title\">", "</div>", "<div class=\"k2b-calendar-day-list__actions\">", "", "</div></div>"],
|
|
44
|
+
_tmpl$33 = ["<p class=\"k2b-calendar-day-list__empty\">", "</p>"],
|
|
45
|
+
_tmpl$34 = ["<li>", "</li>"],
|
|
46
|
+
_tmpl$35 = "<i class=\"ti ti-zoom-in\" aria-hidden=\"true\"></i>",
|
|
47
|
+
_tmpl$36 = ["<div class=\"k2b-calendar-popover\" popover=\"auto\" role=\"dialog\"", ">", "</div>"],
|
|
48
|
+
_tmpl$37 = ["<div class=\"k2b-calendar-time-grid__all-day\" style=\"", "\"><div class=\"k2b-calendar-time-grid__all-day-label\">", "</div>", "</div>"],
|
|
49
|
+
_tmpl$38 = ["<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>"],
|
|
50
|
+
_tmpl$39 = ["<span class=\"k2b-calendar-time-grid__day-label\"", ">", "</span>"],
|
|
51
|
+
_tmpl$40 = ["<span class=\"k2b-calendar-time-grid__badge\">", "", "</span>"],
|
|
52
|
+
_tmpl$41 = ["<div class=\"k2b-calendar-time-grid__all-day-events\">", "", "</div>"],
|
|
53
|
+
_tmpl$42 = ["<div class=\"k2b-calendar-time-grid__hour\"", ">", ":00</div>"],
|
|
54
|
+
_tmpl$43 = ["<div class=\"k2b-calendar-time-grid__now\" style=\"", "\"></div>"],
|
|
55
|
+
_tmpl$44 = ["<div class=\"k2b-calendar-time-grid__column\" style=\"", "\">", "", "", "", "", "</div>"],
|
|
56
|
+
_tmpl$45 = ["<div class=\"k2b-calendar-preview__title\">", "</div>"],
|
|
57
|
+
_tmpl$46 = ["<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>"],
|
|
58
|
+
_tmpl$47 = ["<button type=\"button\"", " draggable=\"false\" class=\"k2b-calendar-time-grid__resize\"><span class=\"k2b-calendar-time-grid__resize-icon\" aria-hidden=\"true\"></span></button>"],
|
|
59
|
+
_tmpl$48 = ["<div class=\"k2b-calendar-time-grid__event-position\" style=\"", "\"><div class=\"k2b-calendar-time-grid__event-frame\">", "", "</div></div>"],
|
|
60
|
+
_tmpl$49 = ["<button type=\"button\" class=\"k2b-calendar-time-grid__overflow\" style=\"", "\"", "><span class=\"k2b-calendar-time-grid__overflow-count\">+", "</span></button>"],
|
|
61
|
+
_tmpl$50 = ["<div class=\"k2b-calendar-time-grid__overflow-menu\" style=\"", "\"><div class=\"k2b-calendar-time-grid__overflow-title\">", " - ", "</div>", "</div>"],
|
|
62
|
+
_tmpl$51 = ["<div class=\"k2b-calendar-year\">", "</div>"],
|
|
63
|
+
_tmpl$52 = ["<div class=\"k2b-calendar-year__month\"><div class=\"k2b-calendar-year__title\">", "</div><div class=\"k2b-calendar-year__grid\">", "</div></div>"],
|
|
64
|
+
_tmpl$53 = ["<span class=\"k2b-calendar-year__indicator\"", " style=\"", "\"></span>"],
|
|
65
|
+
_tmpl$54 = ["<div class=\"k2b-calendar-mobile-month__events\">", "</div>"],
|
|
66
|
+
_tmpl$55 = ["<div class=\"k2b-calendar-mobile-month\">", "<div class=\"k2b-calendar-mobile-month__agenda\"><div class=\"k2b-calendar-mobile-month__title\">", "</div>", "</div></div>"],
|
|
67
|
+
_tmpl$56 = ["<div class=\"k2b-calendar-mobile-month__empty\">", "</div>"],
|
|
68
|
+
_tmpl$57 = ["<div class=\"k2b-calendar-body\">", "</div>"],
|
|
69
|
+
_tmpl$58 = ["<section class=\"", "\"", ">", "", "</section>"];
|
|
68
70
|
import { Link } from "@k2b/ssr/nav";
|
|
69
71
|
import { dates as calendar } from "@k2b/stdlib";
|
|
70
|
-
import { createEffect, createMemo, createSignal, For, mergeProps, on, onCleanup, onMount, Show, untrack } from "solid-js";
|
|
72
|
+
import { createComputed, createEffect, createMemo, createSignal, For, mergeProps, on, onCleanup, onMount, Show, untrack } from "solid-js";
|
|
71
73
|
import { Button } from "../actions/Button";
|
|
72
74
|
import { GestureMenu } from "../actions/GestureMenu";
|
|
73
75
|
import SegmentedControl from "../actions/SegmentedControl";
|
|
74
76
|
import { useDateConfigLocale } from "../intl/locale";
|
|
75
77
|
import { useUiMessages } from "../intl/messages";
|
|
78
|
+
import { prefersReducedMotion } from "../motion";
|
|
76
79
|
import { CalendarDayView } from "./CalendarDayView";
|
|
77
80
|
import { CalendarWeekView } from "./CalendarWeekView";
|
|
81
|
+
import { addDayKeys } from "./calendar-days";
|
|
78
82
|
import { openCalendarGoTo, openCalendarShortcuts } from "./calendar-dialogs";
|
|
79
83
|
import { layoutCalendarIntervals } from "./calendar-event-layout";
|
|
80
84
|
import { useCalendarMessages } from "./calendar-messages";
|
|
81
85
|
import { fitMonthWeek, layoutMonthWeek, monthLaneCapacity } from "./calendar-month-layout";
|
|
86
|
+
import { MONTH_ROW_BLOCK, MONTH_ROWS_IN_VIEW, monthFocusRow, monthOfWeek, monthRenderWindow, monthRevealTop, monthRowOf, monthTodayDirection, monthVisibleRows, monthWeekKeys } from "./calendar-month-scroll";
|
|
82
87
|
import { calendarDayIndexAtPoint, calendarMinuteAtPoint, startCalendarPointerSession } from "./calendar-pointer";
|
|
83
88
|
import { EventChip, eventHref, followCalendarHref, formatTime, ownerDateConfig, parseDate, placeCalendarPopover, textWidth, validDate } from "./calendar-shared";
|
|
84
89
|
import { compactGermanDate } from "./calendar-time-view";
|
|
@@ -413,11 +418,13 @@ const CalendarHeader = props => {
|
|
|
413
418
|
const calendarMessages = useCalendarMessages();
|
|
414
419
|
const dateConfig = () => ownerDateConfig(props.owner);
|
|
415
420
|
const timeView = () => props.nav.timeView();
|
|
421
|
+
const monthView = () => props.nav.monthView();
|
|
422
|
+
const scrollingView = () => timeView() ?? monthView();
|
|
416
423
|
const parseKey = key => calendar.parseCalendarDate(key, dateConfig());
|
|
417
424
|
/** The date the header pages from: the first day a day or week view shows, else the date. */
|
|
418
425
|
const base = () => {
|
|
419
426
|
const shown = timeView()?.visibleKeys().first;
|
|
420
|
-
return shown ? parseKey(shown) : props.date;
|
|
427
|
+
return shown ? parseKey(shown) : monthView()?.stepFrom() ?? props.date;
|
|
421
428
|
};
|
|
422
429
|
const previous = () => adjacentCalendarDate(base(), props.view, -1, dateConfig());
|
|
423
430
|
const next = () => adjacentCalendarDate(base(), props.view, 1, dateConfig());
|
|
@@ -451,7 +458,7 @@ const CalendarHeader = props => {
|
|
|
451
458
|
timeZone: dateConfig().timeZone
|
|
452
459
|
});
|
|
453
460
|
if (props.view === "week") return `${formatDay(calendar.startOfWeek(props.date, dateConfig()), dateConfig())} - ${formatDay(calendar.addDays(calendar.startOfWeek(props.date, dateConfig()), 6, dateConfig()), dateConfig())}`;
|
|
454
|
-
return formatMonth(props.date, dateConfig());
|
|
461
|
+
return formatMonth(monthView()?.focusMonth() ?? props.date, dateConfig());
|
|
455
462
|
};
|
|
456
463
|
/**
|
|
457
464
|
* The titles this view can show around the current date: the months of the year, the weeks of the month and across
|
|
@@ -515,37 +522,52 @@ const CalendarHeader = props => {
|
|
|
515
522
|
const href = props.owner.getViewHref?.(view);
|
|
516
523
|
if (href) window.location.href = href;
|
|
517
524
|
};
|
|
525
|
+
/**
|
|
526
|
+
* A previous or next button. Its element stays while its target changes, such as with each step through the months,
|
|
527
|
+
* so a repeated click or Enter lands on the same button and keeps its focus.
|
|
528
|
+
*/
|
|
518
529
|
const navButton = (date, icon, label, direction) => {
|
|
519
|
-
const href = props.owner.getDateHref?.(date, props.view);
|
|
520
|
-
const step = () =>
|
|
521
|
-
const title = props.nav.commands().length > 0 ? `${label} (${direction > 0 ? "J" : "K"})` : label;
|
|
522
|
-
|
|
530
|
+
const href = () => props.owner.getDateHref?.(date(), props.view);
|
|
531
|
+
const step = () => scrollingView()?.step(direction) ?? false;
|
|
532
|
+
const title = () => props.nav.commands().length > 0 ? `${label} (${direction > 0 ? "J" : "K"})` : label;
|
|
533
|
+
const link = target => _$createComponent(CalendarNavigationLink, {
|
|
523
534
|
get owner() {
|
|
524
535
|
return props.owner;
|
|
525
536
|
},
|
|
526
|
-
href
|
|
537
|
+
get href() {
|
|
538
|
+
return target();
|
|
539
|
+
},
|
|
527
540
|
intercept: step,
|
|
528
|
-
anchorProps
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
541
|
+
get anchorProps() {
|
|
542
|
+
return {
|
|
543
|
+
"aria-label": label,
|
|
544
|
+
title: title(),
|
|
545
|
+
class: "k2b-calendar-header__nav-button"
|
|
546
|
+
};
|
|
532
547
|
},
|
|
533
548
|
get children() {
|
|
534
549
|
return _$ssr(_tmpl$2, `ti ${_$escape(icon, true)}`);
|
|
535
550
|
}
|
|
536
|
-
})
|
|
537
|
-
|
|
538
|
-
|
|
551
|
+
});
|
|
552
|
+
return _$createComponent(Show, {
|
|
553
|
+
get when() {
|
|
554
|
+
return Boolean((props.owner.onNavigateHref || props.owner.onNavigate) && href());
|
|
539
555
|
},
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
556
|
+
get fallback() {
|
|
557
|
+
return _$createComponent(Show, {
|
|
558
|
+
get when() {
|
|
559
|
+
return props.owner.onDateChange;
|
|
560
|
+
},
|
|
561
|
+
get fallback() {
|
|
562
|
+
return link(() => href() ?? "#");
|
|
563
|
+
},
|
|
564
|
+
get children() {
|
|
565
|
+
return _$ssr(_tmpl$3, _$ssrAttribute("aria-label", _$escape(label, true), false) + _$ssrAttribute("title", _$escape(title(), true), false), `ti ${_$escape(icon, true)}`);
|
|
566
|
+
}
|
|
567
|
+
});
|
|
546
568
|
},
|
|
547
569
|
get children() {
|
|
548
|
-
return
|
|
570
|
+
return link(() => href() ?? "#");
|
|
549
571
|
}
|
|
550
572
|
});
|
|
551
573
|
};
|
|
@@ -553,7 +575,7 @@ const CalendarHeader = props => {
|
|
|
553
575
|
* In the day and week views that scroll through their days, Today points where today lies, or shows a calm dot while
|
|
554
576
|
* it is on screen; the icon keeps its place either way. The other views name their period in the title.
|
|
555
577
|
*/
|
|
556
|
-
const direction = () => timeMode() ? (
|
|
578
|
+
const direction = () => timeMode() || monthView() ? (scrollingView()?.todayDirection() ?? todayDirectionOf(String(props.view), props.date, dateConfig())) || "here" : undefined;
|
|
557
579
|
/** One arrow that the stylesheet turns toward today, or the dot while today shows. */
|
|
558
580
|
const todayIcon = () => _$createComponent(Show, {
|
|
559
581
|
get when() {
|
|
@@ -574,7 +596,7 @@ const CalendarHeader = props => {
|
|
|
574
596
|
const todayButton = () => {
|
|
575
597
|
const today = calendar.today(dateConfig());
|
|
576
598
|
const href = props.owner.getDateHref?.(today, props.view);
|
|
577
|
-
const intercept = () =>
|
|
599
|
+
const intercept = () => scrollingView()?.today() ?? false;
|
|
578
600
|
const title = () => props.nav.commands().length > 0 ? `${props.labels.today} (H)` : undefined;
|
|
579
601
|
const label = [todayIcon(), _$ssr(_tmpl$6, _$escape(props.labels.today))];
|
|
580
602
|
return (props.owner.onNavigateHref || props.owner.onNavigate) && href ? _$createComponent(CalendarNavigationLink, {
|
|
@@ -641,7 +663,7 @@ const CalendarHeader = props => {
|
|
|
641
663
|
value: "year",
|
|
642
664
|
label: props.labels.year
|
|
643
665
|
}].filter(option => !props.owner.views || props.owner.views.includes(option.value)), ...(props.owner.customViews ?? [])]);
|
|
644
|
-
return _$ssr(_tmpl$0, _$escape(navButton(previous
|
|
666
|
+
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, {
|
|
645
667
|
get each() {
|
|
646
668
|
return titleWidths();
|
|
647
669
|
},
|
|
@@ -950,7 +972,7 @@ const MonthPickerView = props => {
|
|
|
950
972
|
|
|
951
973
|
/** One entry of the month grid: its whole range, and the days it covers as `YYYY-MM-DD` keys. */
|
|
952
974
|
|
|
953
|
-
/** What the calendar's controller
|
|
975
|
+
/** What the calendar's controller and header ask of the month view; the rest serves the month that scrolls. */
|
|
954
976
|
|
|
955
977
|
/** Lane height and gap of the month entries, in rem; the stylesheet reads both from the grid's custom properties. */
|
|
956
978
|
const MONTH_LANE_REM = 1.25;
|
|
@@ -1010,9 +1032,13 @@ const PRINTABLE_KEY = /^.$/u;
|
|
|
1010
1032
|
const MonthView = props => {
|
|
1011
1033
|
const calendarMessages = useCalendarMessages();
|
|
1012
1034
|
const dateConfig = createMemo(() => ownerDateConfig(props.owner));
|
|
1035
|
+
const continuous = createMemo(() => Boolean(props.owner.range));
|
|
1036
|
+
const [mounted, setMounted] = createSignal(false);
|
|
1037
|
+
const hostMonthKey = () => calendar.formatDateKey(calendar.startOfMonth(props.date, dateConfig()), dateConfig());
|
|
1038
|
+
const [focusMonthKey, setFocusMonthKey] = createSignal(untrack(hostMonthKey));
|
|
1013
1039
|
// The shown month and its grid change only with the month, so a refresh of the same month keeps every cell and its
|
|
1014
1040
|
// focus.
|
|
1015
|
-
const month = createMemo(() => zonedYearMonth(props.date, dateConfig()), undefined, {
|
|
1041
|
+
const month = createMemo(() => zonedYearMonth(continuous() ? calendar.parseCalendarDate(focusMonthKey(), dateConfig()) : props.date, dateConfig()), undefined, {
|
|
1016
1042
|
equals: (previous, next) => previous.year === next.year && previous.month === next.month
|
|
1017
1043
|
});
|
|
1018
1044
|
const weeks = createMemo(() => calendar.getMonthGrid(month().year, month().month, dateConfig()).map(week => week.map(day => ({
|
|
@@ -1024,17 +1050,12 @@ const MonthView = props => {
|
|
|
1024
1050
|
const weekdays = createMemo(() => calendar.weekdays(dateConfig()));
|
|
1025
1051
|
const todayKey = createMemo(() => calendar.formatDateKey(props.now, dateConfig()));
|
|
1026
1052
|
const items = createMemo(() => monthItems(props.events));
|
|
1027
|
-
const weekLayouts = createMemo(() => weeks().map(week => layoutMonthWeek(week.map(entry => entry.key), items().map(item => ({
|
|
1028
|
-
item,
|
|
1029
|
-
firstKey: item.firstKey,
|
|
1030
|
-
lastKey: item.lastKey,
|
|
1031
|
-
bar: item.bar
|
|
1032
|
-
})))));
|
|
1033
1053
|
const [capacities, setCapacities] = createSignal([]);
|
|
1034
1054
|
const [cellWidth, setCellWidth] = createSignal(0);
|
|
1035
1055
|
const [barFont, setBarFont] = createSignal("");
|
|
1036
1056
|
const [anchorKey, setAnchorKey] = createSignal(null);
|
|
1037
1057
|
const [focusKey, setFocusKey] = createSignal(null);
|
|
1058
|
+
const [focusedCellKey, setFocusedCellKey] = createSignal(null);
|
|
1038
1059
|
const [popover, setPopover] = createSignal(null);
|
|
1039
1060
|
/** Whether the quick create holds the focus; until then the grid keeps it. */
|
|
1040
1061
|
const [createActive, setCreateActive] = createSignal(false);
|
|
@@ -1060,13 +1081,479 @@ const MonthView = props => {
|
|
|
1060
1081
|
end: calendar.addDays(parseKey(range.last), 1, dateConfig()),
|
|
1061
1082
|
allDay: true
|
|
1062
1083
|
});
|
|
1063
|
-
const
|
|
1084
|
+
const hostKey = () => calendar.formatDateKey(props.date, dateConfig());
|
|
1085
|
+
const loadedRange = createMemo(() => {
|
|
1086
|
+
const range = props.owner.range;
|
|
1087
|
+
const keyOf = value => calendar.formatDateKey(parseDate(value, dateConfig()), dateConfig());
|
|
1088
|
+
return range ? {
|
|
1089
|
+
first: keyOf(range.from),
|
|
1090
|
+
to: keyOf(range.to)
|
|
1091
|
+
} : {
|
|
1092
|
+
first: hostMonthKey(),
|
|
1093
|
+
to: hostMonthKey()
|
|
1094
|
+
};
|
|
1095
|
+
});
|
|
1096
|
+
const loadedWeeks = createMemo(() => monthWeekKeys(loadedRange().first, loadedRange().to, dateConfig().firstDayOfWeek ?? 1));
|
|
1097
|
+
const loaded = key => key >= loadedRange().first && key < loadedRange().to;
|
|
1098
|
+
// The first paint starts at the month's first week. Mount adds the earlier weeks and positions synchronously.
|
|
1099
|
+
const trackWeeks = createMemo(() => {
|
|
1100
|
+
const all = loadedWeeks();
|
|
1101
|
+
const anchor = monthRowOf(all, hostMonthKey());
|
|
1102
|
+
return mounted() || anchor === undefined ? all : all.slice(anchor);
|
|
1103
|
+
});
|
|
1104
|
+
const [scrollTop, setScrollTop] = createSignal(0);
|
|
1105
|
+
const [rowHeight, setRowHeight] = createSignal(80);
|
|
1106
|
+
const [viewHeight, setViewHeight] = createSignal(400);
|
|
1107
|
+
const [labelShown, setLabelShown] = createSignal(false);
|
|
1108
|
+
const [pulseKey, setPulseKey] = createSignal("");
|
|
1109
|
+
let scroller;
|
|
1110
|
+
let weekdayElement;
|
|
1111
|
+
let ready = false;
|
|
1112
|
+
let positioned = false;
|
|
1113
|
+
let silentTop = null;
|
|
1114
|
+
let frame = 0;
|
|
1115
|
+
let labelTimer = 0;
|
|
1116
|
+
let reportTimer = 0;
|
|
1117
|
+
let queueTimer = 0;
|
|
1118
|
+
let glideTimer = 0;
|
|
1119
|
+
let arrivalTimer = 0;
|
|
1120
|
+
let pulseTimer = 0;
|
|
1121
|
+
/** The month that quick repeated steps head for; the next step and the arrows' links go on from it. */
|
|
1122
|
+
const [queuedMonth, setQueuedMonth] = createSignal(null);
|
|
1123
|
+
let pendingTarget = null;
|
|
1124
|
+
let pendingOrigin = null;
|
|
1125
|
+
let glideTarget = null;
|
|
1126
|
+
let pulseOnArrival = false;
|
|
1127
|
+
let reported = "";
|
|
1128
|
+
let reportedFocus = "";
|
|
1129
|
+
let askedEarlier = "";
|
|
1130
|
+
let askedLater = "";
|
|
1131
|
+
let exhaustedEarlier = "";
|
|
1132
|
+
let exhaustedLater = "";
|
|
1133
|
+
const scrollFocusDay = createMemo(() => {
|
|
1134
|
+
const first = focusMonthKey();
|
|
1135
|
+
const range = selection();
|
|
1136
|
+
const selected = range && range.last >= first ? range.first > first ? range.first : first : null;
|
|
1137
|
+
if (selected?.slice(0, 7) === first.slice(0, 7)) return selected;
|
|
1138
|
+
if (hostKey().slice(0, 7) === first.slice(0, 7)) return hostKey();
|
|
1139
|
+
return todayKey().slice(0, 7) === first.slice(0, 7) ? todayKey() : first;
|
|
1140
|
+
});
|
|
1141
|
+
const visibleRange = createMemo(() => {
|
|
1142
|
+
const weeks = trackWeeks();
|
|
1143
|
+
const rows = monthVisibleRows(scrollTop(), viewHeight(), rowHeight(), weeks.length);
|
|
1144
|
+
const first = weeks[rows.first] ?? focusMonthKey();
|
|
1145
|
+
return {
|
|
1146
|
+
first,
|
|
1147
|
+
last: addDayKeys(weeks[Math.max(rows.first, rows.end - 1)] ?? first, 6)
|
|
1148
|
+
};
|
|
1149
|
+
});
|
|
1150
|
+
const renderWindow = createMemo(() => mounted() ? monthRenderWindow(scrollTop(), viewHeight(), rowHeight(), trackWeeks().length) : {
|
|
1151
|
+
first: 0,
|
|
1152
|
+
end: Math.min(trackWeeks().length, MONTH_ROW_BLOCK * 2)
|
|
1153
|
+
}, undefined, {
|
|
1154
|
+
equals: (left, right) => left.first === right.first && left.end === right.end
|
|
1155
|
+
});
|
|
1156
|
+
/** The window's weeks, and those of the focused day, the selection's moving end, and an open popover's day. */
|
|
1157
|
+
const renderedWeeks = createMemo(() => {
|
|
1158
|
+
const weeks = trackWeeks();
|
|
1159
|
+
const window = renderWindow();
|
|
1160
|
+
const keys = new Set(weeks.slice(window.first, window.end));
|
|
1161
|
+
for (const key of [focusKey(), focusedCellKey(), popover()?.anchor.dataset.calendarDayKey]) {
|
|
1162
|
+
const row = key ? monthRowOf(weeks, key) : undefined;
|
|
1163
|
+
if (row !== undefined) keys.add(weeks[row]);
|
|
1164
|
+
}
|
|
1165
|
+
return [...keys].sort();
|
|
1166
|
+
});
|
|
1167
|
+
// Rows keep their elements, but the list moves a kept row when the window passes it, and a browser drops the focus
|
|
1168
|
+
// from an element that moves. The focused element takes it back once the rows are in place.
|
|
1169
|
+
let refocus = null;
|
|
1170
|
+
createComputed(on(renderedWeeks, () => {
|
|
1171
|
+
const active = typeof document === "undefined" ? null : document.activeElement;
|
|
1172
|
+
refocus = active && scroller?.contains(active) ? active : null;
|
|
1173
|
+
}, {
|
|
1174
|
+
defer: true
|
|
1175
|
+
}));
|
|
1176
|
+
createEffect(on(renderedWeeks, () => {
|
|
1177
|
+
const element = refocus;
|
|
1178
|
+
refocus = null;
|
|
1179
|
+
if (element instanceof HTMLElement && element.isConnected && document.activeElement !== element) element.focus({
|
|
1180
|
+
preventScroll: true
|
|
1181
|
+
});
|
|
1182
|
+
}, {
|
|
1183
|
+
defer: true
|
|
1184
|
+
}));
|
|
1185
|
+
const placeOfToday = () => {
|
|
1186
|
+
const weeks = trackWeeks();
|
|
1187
|
+
const row = monthRowOf(weeks, todayKey());
|
|
1188
|
+
return row === undefined ? todayKey() < (weeks[0] ?? focusMonthKey()) ? "up" : "down" : monthTodayDirection(row, scrollTop(), viewHeight(), rowHeight());
|
|
1189
|
+
};
|
|
1190
|
+
const measureScroll = () => {
|
|
1191
|
+
if (!scroller) return;
|
|
1192
|
+
const row = scroller.querySelector(".k2b-calendar-month__week");
|
|
1193
|
+
const height = row?.getBoundingClientRect().height;
|
|
1194
|
+
if (height && height > 0) setRowHeight(height);
|
|
1195
|
+
setViewHeight(Math.max(0, scroller.clientHeight - (weekdayElement?.getBoundingClientRect().height ?? 0)));
|
|
1196
|
+
};
|
|
1197
|
+
const loadMore = edge => {
|
|
1198
|
+
if (!ready) return;
|
|
1199
|
+
const range = loadedRange();
|
|
1200
|
+
const asked = edge === "earlier" ? range.first : range.to;
|
|
1201
|
+
const loader = edge === "earlier" ? props.owner.onLoadEarlier : props.owner.onLoadLater;
|
|
1202
|
+
if (!loader || (edge === "earlier" ? askedEarlier === asked || exhaustedEarlier === asked : askedLater === asked || exhaustedLater === asked)) return;
|
|
1203
|
+
if (edge === "earlier") askedEarlier = asked;else askedLater = asked;
|
|
1204
|
+
const result = loader();
|
|
1205
|
+
if (result !== null && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") {
|
|
1206
|
+
const settled = () => {
|
|
1207
|
+
if (!ready || (edge === "earlier" ? loadedRange().first : loadedRange().to) !== asked) return;
|
|
1208
|
+
if (edge === "earlier") exhaustedEarlier = asked;else exhaustedLater = asked;
|
|
1209
|
+
const target = pendingOrigin === (edge === "earlier" ? -1 : 1) ? pendingTarget : null;
|
|
1210
|
+
if (target) {
|
|
1211
|
+
pendingTarget = null;
|
|
1212
|
+
pendingOrigin = null;
|
|
1213
|
+
setQueuedMonth(null);
|
|
1214
|
+
window.clearTimeout(queueTimer);
|
|
1215
|
+
}
|
|
1216
|
+
if (edge === "later" && glideTarget?.expires === Number.POSITIVE_INFINITY) {
|
|
1217
|
+
glideTarget = null;
|
|
1218
|
+
pulseOnArrival = false;
|
|
1219
|
+
setQueuedMonth(null);
|
|
1220
|
+
for (const timer of [queueTimer, glideTimer, arrivalTimer]) window.clearTimeout(timer);
|
|
1221
|
+
readScroll();
|
|
1222
|
+
}
|
|
1223
|
+
if (target) props.goToDate?.(parseKey(target));
|
|
1224
|
+
};
|
|
1225
|
+
void Promise.resolve(result).then(settled, settled);
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1228
|
+
/** Asks for more weeks near either end; weeks inserted above a running glide would move its way, so it waits. */
|
|
1229
|
+
const loadNearEdges = () => {
|
|
1230
|
+
if (!scroller) return;
|
|
1231
|
+
if (!glideTarget && scroller.scrollTop < MONTH_ROWS_IN_VIEW * rowHeight()) loadMore("earlier");
|
|
1232
|
+
if (scroller.scrollTop + viewHeight() > (trackWeeks().length - MONTH_ROWS_IN_VIEW * 2) * rowHeight()) loadMore("later");
|
|
1233
|
+
};
|
|
1234
|
+
const reportVisible = () => {
|
|
1235
|
+
if (!ready) return;
|
|
1236
|
+
const {
|
|
1237
|
+
first,
|
|
1238
|
+
last
|
|
1239
|
+
} = untrack(visibleRange);
|
|
1240
|
+
const focus = untrack(scrollFocusDay);
|
|
1241
|
+
const value = `${first}/${last}/${focus}`;
|
|
1242
|
+
if (reported === value) return;
|
|
1243
|
+
reported = value;
|
|
1244
|
+
window.clearTimeout(reportTimer);
|
|
1245
|
+
reportTimer = window.setTimeout(() => {
|
|
1246
|
+
reportedFocus = focus;
|
|
1247
|
+
props.owner.onVisibleDateChange?.(parseKey(first), parseKey(last), parseKey(focus));
|
|
1248
|
+
}, 250);
|
|
1249
|
+
};
|
|
1250
|
+
const keepLabel = () => {
|
|
1251
|
+
window.clearTimeout(labelTimer);
|
|
1252
|
+
labelTimer = window.setTimeout(() => setLabelShown(false), 650);
|
|
1253
|
+
};
|
|
1254
|
+
const readScroll = (showLabel = true) => {
|
|
1255
|
+
if (!scroller) return;
|
|
1256
|
+
const top = scroller.scrollTop;
|
|
1257
|
+
setScrollTop(top);
|
|
1258
|
+
const weeks = trackWeeks();
|
|
1259
|
+
const week = weeks[monthFocusRow(top, viewHeight(), rowHeight(), weeks.length)];
|
|
1260
|
+
if (week) {
|
|
1261
|
+
const next = monthOfWeek(week);
|
|
1262
|
+
if (next !== untrack(focusMonthKey)) {
|
|
1263
|
+
setFocusMonthKey(next);
|
|
1264
|
+
if (showLabel && ready) {
|
|
1265
|
+
setLabelShown(true);
|
|
1266
|
+
keepLabel();
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
reportVisible();
|
|
1271
|
+
};
|
|
1272
|
+
const pulseToday = () => {
|
|
1273
|
+
if (prefersReducedMotion()) return;
|
|
1274
|
+
setPulseKey(todayKey());
|
|
1275
|
+
window.clearTimeout(pulseTimer);
|
|
1276
|
+
pulseTimer = window.setTimeout(() => setPulseKey(""), 1000);
|
|
1277
|
+
};
|
|
1278
|
+
const finishGlide = () => {
|
|
1279
|
+
if (!scroller) return;
|
|
1280
|
+
const target = glideTarget;
|
|
1281
|
+
const row = target ? monthRowOf(trackWeeks(), target.week) : undefined;
|
|
1282
|
+
// A clamped glide may still be waiting for more weeks below; scrollend is not arrival then.
|
|
1283
|
+
if (target && row !== undefined && Math.abs(scroller.scrollTop - (row * rowHeight() + target.offset)) > 1) return;
|
|
1284
|
+
glideTarget = null;
|
|
1285
|
+
if (pendingOrigin !== -1 && pendingOrigin !== 1) {
|
|
1286
|
+
setQueuedMonth(null);
|
|
1287
|
+
window.clearTimeout(queueTimer);
|
|
1288
|
+
}
|
|
1289
|
+
window.clearTimeout(glideTimer);
|
|
1290
|
+
window.clearTimeout(arrivalTimer);
|
|
1291
|
+
readScroll();
|
|
1292
|
+
// A glide that lands near an end asks for the next weeks there, as the reader's own scrolling does.
|
|
1293
|
+
if (target) loadNearEdges();
|
|
1294
|
+
if (pulseOnArrival) {
|
|
1295
|
+
pulseOnArrival = false;
|
|
1296
|
+
pulseToday();
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
const cancelGlide = () => {
|
|
1300
|
+
if (!scroller) return;
|
|
1301
|
+
if (pendingOrigin === -1 || pendingOrigin === 1) {
|
|
1302
|
+
pendingTarget = null;
|
|
1303
|
+
pendingOrigin = null;
|
|
1304
|
+
setQueuedMonth(null);
|
|
1305
|
+
window.clearTimeout(queueTimer);
|
|
1306
|
+
}
|
|
1307
|
+
if (!glideTarget) return;
|
|
1308
|
+
// A reader's wheel or touch takes over from navigation, including any target waiting for more weeks.
|
|
1309
|
+
glideTarget = null;
|
|
1310
|
+
pulseOnArrival = false;
|
|
1311
|
+
setQueuedMonth(null);
|
|
1312
|
+
for (const timer of [queueTimer, glideTimer, arrivalTimer]) window.clearTimeout(timer);
|
|
1313
|
+
scroller.scrollTo({
|
|
1314
|
+
top: scroller.scrollTop,
|
|
1315
|
+
behavior: "instant"
|
|
1316
|
+
});
|
|
1317
|
+
};
|
|
1318
|
+
const issueGlide = (top, smooth) => {
|
|
1319
|
+
if (!scroller) return;
|
|
1320
|
+
const maximum = Math.max(0, scroller.scrollHeight - scroller.clientHeight);
|
|
1321
|
+
const target = Math.max(0, Math.min(top, maximum));
|
|
1322
|
+
if (smooth && !prefersReducedMotion() && Math.abs(target - scroller.scrollTop) > viewHeight() * 3) {
|
|
1323
|
+
scroller.scrollTop = target - Math.sign(target - scroller.scrollTop) * viewHeight();
|
|
1324
|
+
readScroll();
|
|
1325
|
+
}
|
|
1326
|
+
scroller.scrollTo({
|
|
1327
|
+
top: target,
|
|
1328
|
+
behavior: smooth && !prefersReducedMotion() ? "smooth" : "instant"
|
|
1329
|
+
});
|
|
1330
|
+
if (top > maximum + 1) loadMore("later");
|
|
1331
|
+
if (!smooth || prefersReducedMotion()) {
|
|
1332
|
+
readScroll();
|
|
1333
|
+
finishGlide();
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
const glide = (top, smooth = true) => {
|
|
1337
|
+
if (!scroller) return;
|
|
1338
|
+
const row = Math.max(0, Math.min(trackWeeks().length - 1, Math.floor(top / rowHeight())));
|
|
1339
|
+
const week = trackWeeks()[row];
|
|
1340
|
+
if (!week) return;
|
|
1341
|
+
// A target past the loaded weeks waits for them however long they take; the reader's own scrolling ends the wait.
|
|
1342
|
+
const waiting = top > scroller.scrollHeight - scroller.clientHeight + 1;
|
|
1343
|
+
glideTarget = {
|
|
1344
|
+
week,
|
|
1345
|
+
offset: top - row * rowHeight(),
|
|
1346
|
+
expires: waiting ? Number.POSITIVE_INFINITY : performance.now() + 1600
|
|
1347
|
+
};
|
|
1348
|
+
window.clearTimeout(glideTimer);
|
|
1349
|
+
window.clearTimeout(arrivalTimer);
|
|
1350
|
+
if (!waiting) glideTimer = window.setTimeout(() => {
|
|
1351
|
+
glideTarget = null;
|
|
1352
|
+
pulseOnArrival = false;
|
|
1353
|
+
}, 1600);
|
|
1354
|
+
arrivalTimer = window.setTimeout(finishGlide, 900);
|
|
1355
|
+
issueGlide(top, smooth);
|
|
1356
|
+
};
|
|
1357
|
+
const positionMonth = (key, smooth = true, reveal = false) => {
|
|
1358
|
+
if (!continuous() || !loaded(key) || !scroller) return false;
|
|
1359
|
+
const weeks = trackWeeks();
|
|
1360
|
+
const first = monthRowOf(weeks, `${key.slice(0, 7)}-01`);
|
|
1361
|
+
const row = monthRowOf(weeks, key);
|
|
1362
|
+
if (first === undefined || row === undefined) return false;
|
|
1363
|
+
const top = first * rowHeight();
|
|
1364
|
+
glide(reveal ? monthRevealTop(row, top, viewHeight(), rowHeight()) ?? top : top, smooth);
|
|
1365
|
+
return true;
|
|
1366
|
+
};
|
|
1367
|
+
const goToMonth = key => positionMonth(key, true, true);
|
|
1368
|
+
const stepMonth = direction => {
|
|
1369
|
+
if (!continuous() || !scroller) return false;
|
|
1370
|
+
const target = calendar.formatDateKey(calendar.addMonths(parseKey(queuedMonth() ?? focusMonthKey()), direction, dateConfig()), dateConfig());
|
|
1371
|
+
if (loaded(target)) {
|
|
1372
|
+
pendingTarget = null;
|
|
1373
|
+
pendingOrigin = null;
|
|
1374
|
+
if (!positionMonth(target)) return false;
|
|
1375
|
+
} else {
|
|
1376
|
+
// A month past the loaded weeks asks for them and waits; an end the host has reached goes through its navigation.
|
|
1377
|
+
const range = loadedRange();
|
|
1378
|
+
const later = direction === 1;
|
|
1379
|
+
const edge = later ? range.to : range.first;
|
|
1380
|
+
if (!(later ? props.owner.onLoadLater : props.owner.onLoadEarlier) || (later ? exhaustedLater : exhaustedEarlier) === edge) return false;
|
|
1381
|
+
pendingTarget = target;
|
|
1382
|
+
pendingOrigin = direction;
|
|
1383
|
+
loadMore(later ? "later" : "earlier");
|
|
1384
|
+
}
|
|
1385
|
+
// Instant positioning may finish during positionMonth; queue afterwards so rapid clicks still accumulate.
|
|
1386
|
+
setQueuedMonth(target);
|
|
1387
|
+
window.clearTimeout(queueTimer);
|
|
1388
|
+
// A glide that waits for more weeks keeps its month queued until it arrives or the reader scrolls.
|
|
1389
|
+
queueTimer = window.setTimeout(() => {
|
|
1390
|
+
if (pendingOrigin !== -1 && pendingOrigin !== 1 && glideTarget?.expires !== Number.POSITIVE_INFINITY) setQueuedMonth(null);
|
|
1391
|
+
}, 1200);
|
|
1392
|
+
return true;
|
|
1393
|
+
};
|
|
1394
|
+
const goToday = () => {
|
|
1395
|
+
if (!continuous() || !loaded(todayKey()) || !scroller) return false;
|
|
1396
|
+
pulseOnArrival = !prefersReducedMotion();
|
|
1397
|
+
if (positionMonth(todayKey(), true, true)) return true;
|
|
1398
|
+
pulseOnArrival = false;
|
|
1399
|
+
return false;
|
|
1400
|
+
};
|
|
1401
|
+
const revealDay = key => {
|
|
1402
|
+
const row = monthRowOf(trackWeeks(), key);
|
|
1403
|
+
if (row === undefined || !scroller) return;
|
|
1404
|
+
const top = monthRevealTop(row, scroller.scrollTop, viewHeight(), rowHeight());
|
|
1405
|
+
if (top !== undefined) glide(top);
|
|
1406
|
+
};
|
|
1407
|
+
const onScroll = () => {
|
|
1408
|
+
if (!ready || !scroller) return;
|
|
1409
|
+
// Initial positioning and range rebasing are not the reader asking for more weeks.
|
|
1410
|
+
if (silentTop !== null && Math.abs(scroller.scrollTop - silentTop) < 1) return;
|
|
1411
|
+
silentTop = null;
|
|
1412
|
+
if (untrack(labelShown)) keepLabel();
|
|
1413
|
+
if (!frame) frame = requestAnimationFrame(() => {
|
|
1414
|
+
frame = 0;
|
|
1415
|
+
readScroll();
|
|
1416
|
+
if (!scroller) return;
|
|
1417
|
+
loadNearEdges();
|
|
1418
|
+
});
|
|
1419
|
+
};
|
|
1420
|
+
// Capture the old track before render effects change its height, then restore the same week and pixel below.
|
|
1421
|
+
let previousWeeks = [];
|
|
1422
|
+
let savedAnchor = null;
|
|
1423
|
+
createComputed(on(loadedWeeks, weeks => {
|
|
1424
|
+
if (!untrack(mounted) || !scroller) return;
|
|
1425
|
+
const top = scroller.scrollTop;
|
|
1426
|
+
const row = Math.floor(top / untrack(rowHeight));
|
|
1427
|
+
const week = previousWeeks[row];
|
|
1428
|
+
savedAnchor = week ? {
|
|
1429
|
+
week,
|
|
1430
|
+
delta: top - row * untrack(rowHeight)
|
|
1431
|
+
} : null;
|
|
1432
|
+
const next = week ? monthRowOf(weeks, week) : undefined;
|
|
1433
|
+
// Move the render window before DOM updates, so even a larger rebase retains the visible rows' elements.
|
|
1434
|
+
if (next !== undefined && savedAnchor) setScrollTop(next * untrack(rowHeight) + savedAnchor.delta);
|
|
1435
|
+
}, {
|
|
1436
|
+
defer: true
|
|
1437
|
+
}));
|
|
1438
|
+
createEffect(on(loadedWeeks, () => {
|
|
1439
|
+
if (!untrack(mounted) || !scroller) return;
|
|
1440
|
+
measureScroll();
|
|
1441
|
+
previousWeeks = untrack(trackWeeks);
|
|
1442
|
+
const row = savedAnchor ? monthRowOf(previousWeeks, savedAnchor.week) : undefined;
|
|
1443
|
+
const top = row !== undefined && savedAnchor ? row * untrack(rowHeight) + savedAnchor.delta : scroller.scrollTop;
|
|
1444
|
+
// Weeks added below move nothing, and writing the same position would stop a glide on its way.
|
|
1445
|
+
const moved = Math.abs(scroller.scrollTop - top) >= 1;
|
|
1446
|
+
if (moved) scroller.scrollTop = top;
|
|
1447
|
+
if (pendingTarget && loaded(pendingTarget)) {
|
|
1448
|
+
const key = pendingTarget;
|
|
1449
|
+
pendingTarget = null;
|
|
1450
|
+
pendingOrigin = null;
|
|
1451
|
+
positioned = positionMonth(key, positioned) || positioned;
|
|
1452
|
+
if (pendingKey === key) {
|
|
1453
|
+
pendingKey = null;
|
|
1454
|
+
select(key);
|
|
1455
|
+
queueMicrotask(() => focusCell(key));
|
|
1456
|
+
}
|
|
1457
|
+
} else {
|
|
1458
|
+
if (pendingTarget && (pendingOrigin === -1 || pendingOrigin === 1)) loadMore(pendingOrigin === -1 ? "earlier" : "later");
|
|
1459
|
+
// A glide goes on after the weeks above moved it, and one that waited at the end goes on into the new weeks.
|
|
1460
|
+
if (glideTarget && performance.now() < glideTarget.expires && (moved || glideTarget.expires === Number.POSITIVE_INFINITY)) {
|
|
1461
|
+
const target = monthRowOf(previousWeeks, glideTarget.week);
|
|
1462
|
+
if (target !== undefined) issueGlide(target * untrack(rowHeight) + glideTarget.offset, true);
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
savedAnchor = null;
|
|
1466
|
+
silentTop = scroller.scrollTop;
|
|
1467
|
+
readScroll(false);
|
|
1468
|
+
}, {
|
|
1469
|
+
defer: true
|
|
1470
|
+
}));
|
|
1471
|
+
createEffect(on(hostKey, key => {
|
|
1472
|
+
if (!continuous() || !untrack(mounted) || !scroller) return;
|
|
1473
|
+
if (key === reportedFocus) {
|
|
1474
|
+
if (pendingOrigin === "host") {
|
|
1475
|
+
pendingTarget = null;
|
|
1476
|
+
pendingOrigin = null;
|
|
1477
|
+
}
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
pendingTarget = loaded(key) ? null : key;
|
|
1481
|
+
pendingOrigin = pendingTarget ? "host" : null;
|
|
1482
|
+
if (pendingTarget) return;
|
|
1483
|
+
const visible = untrack(visibleRange);
|
|
1484
|
+
if (key.slice(0, 7) !== untrack(focusMonthKey).slice(0, 7) || key < visible.first || key > visible.last) positionMonth(key);
|
|
1485
|
+
if (pendingKey === key) {
|
|
1486
|
+
pendingKey = null;
|
|
1487
|
+
select(key);
|
|
1488
|
+
queueMicrotask(() => focusCell(key));
|
|
1489
|
+
}
|
|
1490
|
+
}, {
|
|
1491
|
+
defer: true
|
|
1492
|
+
}));
|
|
1493
|
+
createEffect(on(scrollFocusDay, () => {
|
|
1494
|
+
if (continuous()) reportVisible();
|
|
1495
|
+
}, {
|
|
1496
|
+
defer: true
|
|
1497
|
+
}));
|
|
1498
|
+
// The scrolling starts once the grid is on the page, also when a host passes `range` only later.
|
|
1499
|
+
createEffect(on(continuous, active => {
|
|
1500
|
+
if (!active || !scroller) return;
|
|
1501
|
+
setMounted(true);
|
|
1502
|
+
measureScroll();
|
|
1503
|
+
previousWeeks = trackWeeks();
|
|
1504
|
+
const row = monthRowOf(previousWeeks, hostMonthKey());
|
|
1505
|
+
if (row !== undefined && loaded(hostKey())) scroller.scrollTop = row * rowHeight();
|
|
1506
|
+
// Too few weeks below the month, such as the days of another view while the month's own load, cannot put its
|
|
1507
|
+
// first week on top yet; the month goes there once its weeks arrive.
|
|
1508
|
+
positioned = row !== undefined && Math.abs(scroller.scrollTop - row * rowHeight()) < 1;
|
|
1509
|
+
if (!positioned) {
|
|
1510
|
+
pendingTarget = hostKey();
|
|
1511
|
+
pendingOrigin = "mount";
|
|
1512
|
+
}
|
|
1513
|
+
readScroll(false);
|
|
1514
|
+
silentTop = scroller.scrollTop;
|
|
1515
|
+
ready = true;
|
|
1516
|
+
reportVisible();
|
|
1517
|
+
scroller.addEventListener("scrollend", finishGlide);
|
|
1518
|
+
const resize = typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver(() => {
|
|
1519
|
+
if (!scroller) return;
|
|
1520
|
+
const height = untrack(rowHeight);
|
|
1521
|
+
const position = scroller.scrollTop / height;
|
|
1522
|
+
measureScroll();
|
|
1523
|
+
if (height !== untrack(rowHeight)) {
|
|
1524
|
+
scroller.scrollTop = position * untrack(rowHeight);
|
|
1525
|
+
if (glideTarget) {
|
|
1526
|
+
const target = monthRowOf(untrack(trackWeeks), glideTarget.week);
|
|
1527
|
+
if (target !== undefined) issueGlide(target * untrack(rowHeight) + glideTarget.offset, true);
|
|
1528
|
+
}
|
|
1529
|
+
silentTop = scroller.scrollTop;
|
|
1530
|
+
}
|
|
1531
|
+
readScroll(false);
|
|
1532
|
+
});
|
|
1533
|
+
resize?.observe(scroller);
|
|
1534
|
+
const element = scroller;
|
|
1535
|
+
onCleanup(() => {
|
|
1536
|
+
resize?.disconnect();
|
|
1537
|
+
element.removeEventListener("scrollend", finishGlide);
|
|
1538
|
+
for (const timer of [labelTimer, reportTimer, queueTimer, glideTimer, arrivalTimer, pulseTimer]) window.clearTimeout(timer);
|
|
1539
|
+
if (frame) cancelAnimationFrame(frame);
|
|
1540
|
+
frame = 0;
|
|
1541
|
+
ready = false;
|
|
1542
|
+
setMounted(false);
|
|
1543
|
+
});
|
|
1544
|
+
}));
|
|
1545
|
+
const visibleKeys = createMemo(() => continuous() ? renderedWeeks().flatMap(key => Array.from({
|
|
1546
|
+
length: 7
|
|
1547
|
+
}, (_, day) => addDayKeys(key, day))) : weeks().flatMap(week => week.map(entry => entry.key)));
|
|
1064
1548
|
const rovingKey = createMemo(() => {
|
|
1065
1549
|
const keys = visibleKeys();
|
|
1066
|
-
const focus = focusKey();
|
|
1550
|
+
const focus = focusKey() ?? (continuous() ? focusedCellKey() : null);
|
|
1067
1551
|
if (focus && keys.includes(focus)) return focus;
|
|
1068
|
-
if (keys.includes(todayKey())) return todayKey();
|
|
1069
|
-
|
|
1552
|
+
if (keys.includes(todayKey()) && (!continuous() || todayKey() >= visibleRange().first && todayKey() <= visibleRange().last)) return todayKey();
|
|
1553
|
+
const first = calendar.formatDateKey(zonedMonthDate(month().year, month().month, dateConfig()), dateConfig());
|
|
1554
|
+
if (!continuous() || keys.includes(first)) return first;
|
|
1555
|
+
const visible = visibleRange();
|
|
1556
|
+
return keys.find(key => key.slice(0, 7) === first.slice(0, 7) && key >= visible.first && key <= visible.last) ?? keys.find(key => key >= visible.first && key <= visible.last) ?? keys[0] ?? first;
|
|
1070
1557
|
});
|
|
1071
1558
|
const dropRange = createMemo(() => {
|
|
1072
1559
|
const preview = movePreview();
|
|
@@ -1091,8 +1578,7 @@ const MonthView = props => {
|
|
|
1091
1578
|
setAnchorKey(anchor);
|
|
1092
1579
|
setFocusKey(focus);
|
|
1093
1580
|
};
|
|
1094
|
-
//
|
|
1095
|
-
// goes with the view, so switching to another view reports that nothing is selected.
|
|
1581
|
+
// Selection survives scrolling; only paging starts a month without it. Switching views clears the host's selection.
|
|
1096
1582
|
createEffect(on(selection, range => props.owner.onSelectionChange?.(range ? rangeOf(range) : null), {
|
|
1097
1583
|
defer: true
|
|
1098
1584
|
}));
|
|
@@ -1101,6 +1587,7 @@ const MonthView = props => {
|
|
|
1101
1587
|
});
|
|
1102
1588
|
createEffect(on(selection, range => props.onFocusDay?.(range ? parseKey(range.first) : null)));
|
|
1103
1589
|
createEffect(on(month, () => {
|
|
1590
|
+
if (continuous()) return;
|
|
1104
1591
|
setPopover(null);
|
|
1105
1592
|
const key = pendingKey;
|
|
1106
1593
|
pendingKey = null;
|
|
@@ -1224,6 +1711,11 @@ const MonthView = props => {
|
|
|
1224
1711
|
popoverFocusable()?.focus();
|
|
1225
1712
|
return true;
|
|
1226
1713
|
};
|
|
1714
|
+
/**
|
|
1715
|
+
* The day to create on without a selection. The month that scrolls takes the day it stands for, today or the 1st of
|
|
1716
|
+
* the month in focus, never a day the keyboard last visited in another month.
|
|
1717
|
+
*/
|
|
1718
|
+
const unselectedKey = () => continuous() ? scrollFocusDay() : rovingKey();
|
|
1227
1719
|
/** Enter, a double-click, and N create on the selection, with the quick create or the host's own create action. */
|
|
1228
1720
|
const createOnSelection = () => {
|
|
1229
1721
|
const range = selection();
|
|
@@ -1236,8 +1728,8 @@ const MonthView = props => {
|
|
|
1236
1728
|
onMount(() => props.register?.({
|
|
1237
1729
|
quickCreate: create => {
|
|
1238
1730
|
const range = selection() ?? {
|
|
1239
|
-
first:
|
|
1240
|
-
last:
|
|
1731
|
+
first: unselectedKey(),
|
|
1732
|
+
last: unselectedKey()
|
|
1241
1733
|
};
|
|
1242
1734
|
select(range.first, range.last);
|
|
1243
1735
|
if (!openCreate(range, {
|
|
@@ -1246,10 +1738,18 @@ const MonthView = props => {
|
|
|
1246
1738
|
})) props.owner.onSlotActivate?.(rangeOf(range));
|
|
1247
1739
|
},
|
|
1248
1740
|
createTarget: () => rangeOf(selection() ?? {
|
|
1249
|
-
first:
|
|
1250
|
-
last:
|
|
1741
|
+
first: unselectedKey(),
|
|
1742
|
+
last: unselectedKey()
|
|
1251
1743
|
}),
|
|
1252
|
-
typing: () => popover()?.kind === "create" && !createActive()
|
|
1744
|
+
typing: () => popover()?.kind === "create" && !createActive(),
|
|
1745
|
+
continuous,
|
|
1746
|
+
focusMonth: () => parseKey(focusMonthKey()),
|
|
1747
|
+
stepFrom: () => parseKey(queuedMonth() ?? focusMonthKey()),
|
|
1748
|
+
focusDay: () => parseKey(scrollFocusDay()),
|
|
1749
|
+
step: stepMonth,
|
|
1750
|
+
goTo: goToMonth,
|
|
1751
|
+
today: goToday,
|
|
1752
|
+
todayDirection: placeOfToday
|
|
1253
1753
|
}));
|
|
1254
1754
|
onCleanup(() => props.register?.(null));
|
|
1255
1755
|
const openDayList = key => {
|
|
@@ -1284,12 +1784,15 @@ const MonthView = props => {
|
|
|
1284
1784
|
}
|
|
1285
1785
|
};
|
|
1286
1786
|
const moveFocus = (key, extend) => {
|
|
1287
|
-
if (!visibleKeys().includes(key)) {
|
|
1787
|
+
if (continuous() ? !loaded(key) : !visibleKeys().includes(key)) {
|
|
1288
1788
|
pageTo(key);
|
|
1289
1789
|
return;
|
|
1290
1790
|
}
|
|
1291
1791
|
if (extend) select(anchorKey() ?? focusKey() ?? key, key);else select(key);
|
|
1292
|
-
|
|
1792
|
+
if (continuous()) {
|
|
1793
|
+
revealDay(key);
|
|
1794
|
+
queueMicrotask(() => focusCell(key));
|
|
1795
|
+
} else focusCell(key);
|
|
1293
1796
|
followSelection();
|
|
1294
1797
|
};
|
|
1295
1798
|
const onCellKeyDown = (event, key) => {
|
|
@@ -1318,7 +1821,12 @@ const MonthView = props => {
|
|
|
1318
1821
|
}
|
|
1319
1822
|
if (event.key === "PageUp" || event.key === "PageDown") {
|
|
1320
1823
|
event.preventDefault();
|
|
1321
|
-
|
|
1824
|
+
const target = calendar.formatDateKey(addMonthsClamped(day, event.key === "PageUp" ? -1 : 1, dateConfig()), dateConfig());
|
|
1825
|
+
if (continuous() && loaded(target)) {
|
|
1826
|
+
moveFocus(target, event.shiftKey);
|
|
1827
|
+
// The month's first week goes on top, unless the day lies in a sixth week that would then stay out of view.
|
|
1828
|
+
goToMonth(target);
|
|
1829
|
+
} else pageTo(target);
|
|
1322
1830
|
return;
|
|
1323
1831
|
}
|
|
1324
1832
|
if (event.key === "Enter" || (event.key === "n" || event.key === "N") && !event.shiftKey) {
|
|
@@ -1388,6 +1896,9 @@ const MonthView = props => {
|
|
|
1388
1896
|
cancelInteraction?.();
|
|
1389
1897
|
cancelInteraction = startCalendarPointerSession({
|
|
1390
1898
|
event,
|
|
1899
|
+
scrollContainer: continuous() ? scroller : undefined,
|
|
1900
|
+
// A drag along the last row on screen selects its days; the view scrolls once the pointer came from inside.
|
|
1901
|
+
armAutoScroll: true,
|
|
1391
1902
|
resolve: (clientX, clientY) => dayKeyAtPoint(clientX, clientY),
|
|
1392
1903
|
onActivate: () => {
|
|
1393
1904
|
suppressClickUntil = performance.now() + 400;
|
|
@@ -1396,6 +1907,8 @@ const MonthView = props => {
|
|
|
1396
1907
|
},
|
|
1397
1908
|
onPreview: current => select(key, current),
|
|
1398
1909
|
onCommit: current => {
|
|
1910
|
+
// The click that ends a long drag, such as one that scrolled the view, must not select the pressed day again.
|
|
1911
|
+
suppressClickUntil = performance.now() + 400;
|
|
1399
1912
|
select(key, current);
|
|
1400
1913
|
focusCell(current);
|
|
1401
1914
|
const range = orderedSelection(key, current);
|
|
@@ -1415,8 +1928,8 @@ const MonthView = props => {
|
|
|
1415
1928
|
const menuItems = createMemo(() => {
|
|
1416
1929
|
if (!hasMenu()) return [];
|
|
1417
1930
|
const range = selection() ?? {
|
|
1418
|
-
first:
|
|
1419
|
-
last:
|
|
1931
|
+
first: unselectedKey(),
|
|
1932
|
+
last: unselectedKey()
|
|
1420
1933
|
};
|
|
1421
1934
|
const own = props.owner.selectionMenu?.(rangeOf(range), {
|
|
1422
1935
|
quickCreate: create => {
|
|
@@ -1466,6 +1979,8 @@ const MonthView = props => {
|
|
|
1466
1979
|
cancelInteraction?.();
|
|
1467
1980
|
cancelInteraction = startCalendarPointerSession({
|
|
1468
1981
|
event: pointerEvent,
|
|
1982
|
+
scrollContainer: continuous() ? scroller : undefined,
|
|
1983
|
+
armAutoScroll: true,
|
|
1469
1984
|
resolve: (clientX, clientY) => {
|
|
1470
1985
|
const key = dayKeyAtPoint(clientX, clientY);
|
|
1471
1986
|
if (!key) return null;
|
|
@@ -1485,6 +2000,9 @@ const MonthView = props => {
|
|
|
1485
2000
|
},
|
|
1486
2001
|
onPreview: setMovePreview,
|
|
1487
2002
|
onCommit: next => {
|
|
2003
|
+
// The click that ends a long move, such as one that scrolled the view, must not open the entry.
|
|
2004
|
+
markDragged();
|
|
2005
|
+
suppressClickUntil = performance.now() + 400;
|
|
1488
2006
|
clearMove();
|
|
1489
2007
|
if (eventTimeChanged(event, next)) props.owner.onEventDrop?.(event, next);
|
|
1490
2008
|
},
|
|
@@ -1572,235 +2090,264 @@ const MonthView = props => {
|
|
|
1572
2090
|
if (linkedItem() === item.key) setLinkedItem("");
|
|
1573
2091
|
}
|
|
1574
2092
|
});
|
|
1575
|
-
const
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
get children() {
|
|
1603
|
-
return _$ssr(_tmpl$22, _$escape(_$createComponent(Show, {
|
|
1604
|
-
get when() {
|
|
1605
|
-
return weekHref();
|
|
1606
|
-
},
|
|
1607
|
-
get fallback() {
|
|
1608
|
-
return _$createComponent(Show, {
|
|
1609
|
-
get when() {
|
|
1610
|
-
return canOpenView("week");
|
|
1611
|
-
},
|
|
1612
|
-
get fallback() {
|
|
1613
|
-
return weekNumber();
|
|
1614
|
-
},
|
|
1615
|
-
get children() {
|
|
1616
|
-
return _$ssr(_tmpl$24, _$ssrAttribute("title", _$escape(calendarMessages().calendarOpenWeekNumber({
|
|
1617
|
-
week: weekNumber()
|
|
1618
|
-
}), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarOpenWeekNumber({
|
|
1619
|
-
week: weekNumber()
|
|
1620
|
-
}), true), false), _$escape(weekNumber()));
|
|
1621
|
-
}
|
|
1622
|
-
});
|
|
1623
|
-
},
|
|
1624
|
-
children: href => _$createComponent(CalendarNavigationLink, {
|
|
1625
|
-
get owner() {
|
|
1626
|
-
return props.owner;
|
|
1627
|
-
},
|
|
1628
|
-
get href() {
|
|
1629
|
-
return href();
|
|
2093
|
+
const weekRow = (week, weekIndex) => {
|
|
2094
|
+
const layout = createMemo(() => layoutMonthWeek(week().map(entry => entry.key), items().map(item => ({
|
|
2095
|
+
item,
|
|
2096
|
+
firstKey: item.firstKey,
|
|
2097
|
+
lastKey: item.lastKey,
|
|
2098
|
+
bar: item.bar
|
|
2099
|
+
}))));
|
|
2100
|
+
// The continuous rows are all as high as the first, so they share its measured capacity.
|
|
2101
|
+
const capacity = () => capacities()[continuous() ? 0 : weekIndex()] ?? MONTH_DEFAULT_LANES;
|
|
2102
|
+
const fit = createMemo(() => fitMonthWeek(layout(), capacity()));
|
|
2103
|
+
const weekHref = () => viewHref(week()[0].key, "week");
|
|
2104
|
+
const weekNumber = () => zonedWeekNumber(week()[0].day, dateConfig());
|
|
2105
|
+
return _$ssr(_tmpl$20, _$ssrAttribute("data-week-key", continuous() ? _$escape(week()[0]?.key, true) : _$escape(undefined, true), false) + _$ssrAttribute("aria-rowindex", continuous() ? _$escape(weekIndex(), true) + 2 : _$escape(undefined, true), false), _$ssrStyle(continuous() ? {
|
|
2106
|
+
"--k2b-calendar-week-index": String(weekIndex())
|
|
2107
|
+
} : undefined), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
|
|
2108
|
+
get when() {
|
|
2109
|
+
return props.owner.withWeekNumbers;
|
|
2110
|
+
},
|
|
2111
|
+
get children() {
|
|
2112
|
+
return _$ssr(_tmpl$19, _$escape(_$createComponent(Show, {
|
|
2113
|
+
get when() {
|
|
2114
|
+
return weekHref();
|
|
2115
|
+
},
|
|
2116
|
+
get fallback() {
|
|
2117
|
+
return _$createComponent(Show, {
|
|
2118
|
+
get when() {
|
|
2119
|
+
return canOpenView("week");
|
|
1630
2120
|
},
|
|
1631
|
-
get
|
|
1632
|
-
return
|
|
1633
|
-
class: "k2b-calendar-month__week-link",
|
|
1634
|
-
tabIndex: -1,
|
|
1635
|
-
title: calendarMessages().calendarOpenWeekNumber({
|
|
1636
|
-
week: weekNumber()
|
|
1637
|
-
}),
|
|
1638
|
-
"aria-label": calendarMessages().calendarOpenWeekNumber({
|
|
1639
|
-
week: weekNumber()
|
|
1640
|
-
})
|
|
1641
|
-
};
|
|
2121
|
+
get fallback() {
|
|
2122
|
+
return weekNumber();
|
|
1642
2123
|
},
|
|
1643
2124
|
get children() {
|
|
1644
|
-
return
|
|
2125
|
+
return _$ssr(_tmpl$21, _$ssrAttribute("title", _$escape(calendarMessages().calendarOpenWeekNumber({
|
|
2126
|
+
week: weekNumber()
|
|
2127
|
+
}), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarOpenWeekNumber({
|
|
2128
|
+
week: weekNumber()
|
|
2129
|
+
}), true), false), _$escape(weekNumber()));
|
|
1645
2130
|
}
|
|
1646
|
-
})
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
children: ({
|
|
1652
|
-
day,
|
|
1653
|
-
key
|
|
1654
|
-
}, column) => {
|
|
1655
|
-
const dayBadge = props.owner.dayBadges?.[key];
|
|
1656
|
-
const sameMonth = calendar.isSameMonth(day, props.date, dateConfig());
|
|
1657
|
-
const label = dayLabel(day);
|
|
1658
|
-
const bars = createMemo(() => fit().bars.filter(bar => bar.startColumn === column()));
|
|
1659
|
-
const cell = () => fit().cells[column()] ?? {
|
|
1660
|
-
top: 0,
|
|
1661
|
-
shown: [],
|
|
1662
|
-
hidden: 0
|
|
1663
|
-
};
|
|
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, {
|
|
1665
|
-
when: dayBadge,
|
|
1666
|
-
children: badge => _$ssr(_tmpl$17, _$escape(_$createComponent(Show, {
|
|
1667
|
-
get when() {
|
|
1668
|
-
return badge().icon;
|
|
1669
|
-
},
|
|
1670
|
-
children: icon => _$ssr(_tmpl$2, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
|
|
1671
|
-
})), _$escape(badge().label))
|
|
1672
|
-
})), _$escape(_$createComponent(For, {
|
|
1673
|
-
get each() {
|
|
1674
|
-
return bars();
|
|
2131
|
+
});
|
|
2132
|
+
},
|
|
2133
|
+
children: href => _$createComponent(CalendarNavigationLink, {
|
|
2134
|
+
get owner() {
|
|
2135
|
+
return props.owner;
|
|
1675
2136
|
},
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
2137
|
+
get href() {
|
|
2138
|
+
return href();
|
|
2139
|
+
},
|
|
2140
|
+
get anchorProps() {
|
|
2141
|
+
return {
|
|
2142
|
+
class: "k2b-calendar-month__week-link",
|
|
2143
|
+
tabIndex: -1,
|
|
2144
|
+
title: calendarMessages().calendarOpenWeekNumber({
|
|
2145
|
+
week: weekNumber()
|
|
2146
|
+
}),
|
|
2147
|
+
"aria-label": calendarMessages().calendarOpenWeekNumber({
|
|
2148
|
+
week: weekNumber()
|
|
2149
|
+
})
|
|
1687
2150
|
};
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
return {
|
|
1692
|
-
"--k2b-calendar-span": String(span),
|
|
1693
|
-
"--k2b-calendar-row": String(bar.lane)
|
|
1694
|
-
};
|
|
1695
|
-
},
|
|
1696
|
-
"data-bar": "true",
|
|
1697
|
-
get ["data-linked"]() {
|
|
1698
|
-
return linkedItem() === bar.item.key && bar.item.firstKey !== bar.item.lastKey ? "true" : undefined;
|
|
1699
|
-
},
|
|
1700
|
-
get ["data-continues-before"]() {
|
|
1701
|
-
return bar.continuesBefore ? "true" : undefined;
|
|
1702
|
-
},
|
|
1703
|
-
get ["data-continues-after"]() {
|
|
1704
|
-
return bar.continuesAfter ? "true" : undefined;
|
|
1705
|
-
}
|
|
1706
|
-
}, () => linkProps(bar.item)), _$escape(_$createComponent(EventChip, {
|
|
1707
|
-
get event() {
|
|
1708
|
-
return bar.item.event;
|
|
1709
|
-
},
|
|
1710
|
-
get owner() {
|
|
1711
|
-
return props.owner;
|
|
1712
|
-
},
|
|
1713
|
-
get href() {
|
|
1714
|
-
return eventHref(props.owner, bar.item.event);
|
|
1715
|
-
},
|
|
1716
|
-
get label() {
|
|
1717
|
-
return itemLabel(bar.item);
|
|
1718
|
-
},
|
|
1719
|
-
compact: true,
|
|
1720
|
-
bar: true,
|
|
1721
|
-
get continuesBefore() {
|
|
1722
|
-
return bar.continuesBefore;
|
|
1723
|
-
},
|
|
1724
|
-
get continuesAfter() {
|
|
1725
|
-
return bar.continuesAfter;
|
|
1726
|
-
},
|
|
1727
|
-
get hintStart() {
|
|
1728
|
-
return startHint();
|
|
1729
|
-
},
|
|
1730
|
-
get hintEnd() {
|
|
1731
|
-
return endHint();
|
|
1732
|
-
},
|
|
1733
|
-
get moving() {
|
|
1734
|
-
return movingEventId() === bar.item.event.id;
|
|
1735
|
-
},
|
|
1736
|
-
get onMovePointerDown() {
|
|
1737
|
-
return props.owner.onEventDrop ? (pointerEvent, markDragged) => startMove(pointerEvent, bar.item, markDragged) : undefined;
|
|
1738
|
-
}
|
|
1739
|
-
})), false);
|
|
2151
|
+
},
|
|
2152
|
+
get children() {
|
|
2153
|
+
return weekNumber();
|
|
1740
2154
|
}
|
|
1741
|
-
})
|
|
1742
|
-
|
|
1743
|
-
|
|
2155
|
+
})
|
|
2156
|
+
})));
|
|
2157
|
+
}
|
|
2158
|
+
})), _$escape(_$createComponent(For, {
|
|
2159
|
+
get each() {
|
|
2160
|
+
return week();
|
|
2161
|
+
},
|
|
2162
|
+
children: ({
|
|
2163
|
+
day,
|
|
2164
|
+
key
|
|
2165
|
+
}, column) => {
|
|
2166
|
+
const dayBadge = props.owner.dayBadges?.[key];
|
|
2167
|
+
const sameMonth = () => calendar.isSameMonth(day, continuous() ? parseKey(focusMonthKey()) : props.date, dateConfig());
|
|
2168
|
+
const label = dayLabel(day);
|
|
2169
|
+
const bars = createMemo(() => fit().bars.filter(bar => bar.startColumn === column()));
|
|
2170
|
+
const cell = () => fit().cells[column()] ?? {
|
|
2171
|
+
top: 0,
|
|
2172
|
+
shown: [],
|
|
2173
|
+
hidden: 0
|
|
2174
|
+
};
|
|
2175
|
+
return _$ssr(_tmpl$23, _$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-month-first", continuous() && key.endsWith("-01") ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-month-top", continuous() && Number(key.slice(8)) <= 7 ? "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-pulse", continuous() && pulseKey() === 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), continuous() && key.endsWith("-01") ? _$escape(shortDayLabel(key).replace(/\.$/, "")) : _$escape(calendar.formatDayNumber(day, dateConfig())), _$escape(_$createComponent(Show, {
|
|
2176
|
+
when: dayBadge,
|
|
2177
|
+
children: badge => _$ssr(_tmpl$17, _$escape(_$createComponent(Show, {
|
|
2178
|
+
get when() {
|
|
2179
|
+
return badge().icon;
|
|
1744
2180
|
},
|
|
1745
|
-
children:
|
|
2181
|
+
children: icon => _$ssr(_tmpl$2, `k2b-calendar-month__badge-icon ti ti-${_$escape(icon(), true)}`)
|
|
2182
|
+
})), _$escape(badge().label))
|
|
2183
|
+
})), _$escape(_$createComponent(For, {
|
|
2184
|
+
get each() {
|
|
2185
|
+
return bars();
|
|
2186
|
+
},
|
|
2187
|
+
children: bar => {
|
|
2188
|
+
const span = bar.endColumn - bar.startColumn + 1;
|
|
2189
|
+
const startHint = () => {
|
|
2190
|
+
if (!bar.continuesBefore) return undefined;
|
|
2191
|
+
const hint = calendarMessages().calendarContinuesFrom(hintDate(bar.item.firstKey));
|
|
2192
|
+
return hintFits(bar.item.event.title, hint, span) ? hint : undefined;
|
|
2193
|
+
};
|
|
2194
|
+
const endHint = () => {
|
|
2195
|
+
if (!bar.continuesAfter) return undefined;
|
|
2196
|
+
const hint = calendarMessages().calendarContinuesUntil(hintDate(bar.item.lastKey));
|
|
2197
|
+
return hintFits(`${bar.item.event.title}${startHint() ?? ""}`, hint, span) ? hint : undefined;
|
|
2198
|
+
};
|
|
2199
|
+
return _$ssrElement("div", _$mergeProps({
|
|
2200
|
+
"class": "k2b-calendar-month__segment",
|
|
2201
|
+
get style() {
|
|
2202
|
+
return {
|
|
2203
|
+
"--k2b-calendar-span": String(span),
|
|
2204
|
+
"--k2b-calendar-row": String(bar.lane)
|
|
2205
|
+
};
|
|
2206
|
+
},
|
|
2207
|
+
"data-bar": "true",
|
|
2208
|
+
get ["data-linked"]() {
|
|
2209
|
+
return linkedItem() === bar.item.key && bar.item.firstKey !== bar.item.lastKey ? "true" : undefined;
|
|
2210
|
+
},
|
|
2211
|
+
get ["data-continues-before"]() {
|
|
2212
|
+
return bar.continuesBefore ? "true" : undefined;
|
|
2213
|
+
},
|
|
2214
|
+
get ["data-continues-after"]() {
|
|
2215
|
+
return bar.continuesAfter ? "true" : undefined;
|
|
2216
|
+
}
|
|
2217
|
+
}, () => linkProps(bar.item)), _$escape(_$createComponent(EventChip, {
|
|
1746
2218
|
get event() {
|
|
1747
|
-
return item.event;
|
|
2219
|
+
return bar.item.event;
|
|
1748
2220
|
},
|
|
1749
2221
|
get owner() {
|
|
1750
2222
|
return props.owner;
|
|
1751
2223
|
},
|
|
1752
2224
|
get href() {
|
|
1753
|
-
return eventHref(props.owner, item.event);
|
|
2225
|
+
return eventHref(props.owner, bar.item.event);
|
|
2226
|
+
},
|
|
2227
|
+
get label() {
|
|
2228
|
+
return itemLabel(bar.item);
|
|
1754
2229
|
},
|
|
1755
2230
|
compact: true,
|
|
1756
|
-
|
|
1757
|
-
|
|
2231
|
+
bar: true,
|
|
2232
|
+
get continuesBefore() {
|
|
2233
|
+
return bar.continuesBefore;
|
|
2234
|
+
},
|
|
2235
|
+
get continuesAfter() {
|
|
2236
|
+
return bar.continuesAfter;
|
|
2237
|
+
},
|
|
2238
|
+
get hintStart() {
|
|
2239
|
+
return startHint();
|
|
2240
|
+
},
|
|
2241
|
+
get hintEnd() {
|
|
2242
|
+
return endHint();
|
|
1758
2243
|
},
|
|
1759
2244
|
get moving() {
|
|
1760
|
-
return movingEventId() === item.event.id;
|
|
2245
|
+
return movingEventId() === bar.item.event.id;
|
|
1761
2246
|
},
|
|
1762
2247
|
get onMovePointerDown() {
|
|
1763
|
-
return props.owner.onEventDrop ? (pointerEvent, markDragged) => startMove(pointerEvent, item, markDragged) : undefined;
|
|
2248
|
+
return props.owner.onEventDrop ? (pointerEvent, markDragged) => startMove(pointerEvent, bar.item, markDragged) : undefined;
|
|
1764
2249
|
}
|
|
1765
|
-
})))
|
|
1766
|
-
}
|
|
1767
|
-
|
|
1768
|
-
|
|
2250
|
+
})), false);
|
|
2251
|
+
}
|
|
2252
|
+
})), _$escape(_$createComponent(For, {
|
|
2253
|
+
get each() {
|
|
2254
|
+
return cell().shown;
|
|
2255
|
+
},
|
|
2256
|
+
children: (item, index) => _$ssr(_tmpl$24, _$ssrStyleProperty("--k2b-calendar-span:", "1") + _$ssrStyleProperty(";--k2b-calendar-row:", _$escape(String(cell().top + index()), true)), _$escape(_$createComponent(EventChip, {
|
|
2257
|
+
get event() {
|
|
2258
|
+
return item.event;
|
|
1769
2259
|
},
|
|
1770
|
-
get
|
|
1771
|
-
return
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
2260
|
+
get owner() {
|
|
2261
|
+
return props.owner;
|
|
2262
|
+
},
|
|
2263
|
+
get href() {
|
|
2264
|
+
return eventHref(props.owner, item.event);
|
|
2265
|
+
},
|
|
2266
|
+
compact: true,
|
|
2267
|
+
get leadingTime() {
|
|
2268
|
+
return leadingTime(item);
|
|
2269
|
+
},
|
|
2270
|
+
get moving() {
|
|
2271
|
+
return movingEventId() === item.event.id;
|
|
2272
|
+
},
|
|
2273
|
+
get onMovePointerDown() {
|
|
2274
|
+
return props.owner.onEventDrop ? (pointerEvent, markDragged) => startMove(pointerEvent, item, markDragged) : undefined;
|
|
1780
2275
|
}
|
|
1781
|
-
})))
|
|
1782
|
-
}
|
|
1783
|
-
|
|
2276
|
+
})))
|
|
2277
|
+
})), _$escape(_$createComponent(Show, {
|
|
2278
|
+
get when() {
|
|
2279
|
+
return cell().hidden > 0;
|
|
2280
|
+
},
|
|
2281
|
+
get children() {
|
|
2282
|
+
return _$ssr(_tmpl$22, _$ssrStyleProperty("--k2b-calendar-row:", _$escape(String(cell().top + cell().shown.length), true)), _$ssrAttribute("aria-label", _$escape(calendarMessages().calendarMoreEventsOn({
|
|
2283
|
+
count: cell().hidden,
|
|
2284
|
+
label
|
|
2285
|
+
}), true), false), _$ssrAttribute("aria-expanded", (() => {
|
|
2286
|
+
const current = popover();
|
|
2287
|
+
return current?.kind === "day" && _$escape(current.dayKey, true) === _$escape(key, true);
|
|
2288
|
+
})(), false), _$escape(calendarMessages().calendarMoreEvents({
|
|
2289
|
+
count: cell().hidden
|
|
2290
|
+
})), _$escape(cell().hidden));
|
|
2291
|
+
}
|
|
2292
|
+
})));
|
|
2293
|
+
}
|
|
2294
|
+
})));
|
|
2295
|
+
};
|
|
2296
|
+
const weekdayRow = () => _$ssr(_tmpl$26, _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
|
|
2297
|
+
get when() {
|
|
2298
|
+
return props.owner.withWeekNumbers;
|
|
2299
|
+
},
|
|
2300
|
+
get children() {
|
|
2301
|
+
return _$ssr(_tmpl$25, _$escape(calendarMessages().weekShort));
|
|
1784
2302
|
}
|
|
2303
|
+
})), _$escape(_$createComponent(For, {
|
|
2304
|
+
get each() {
|
|
2305
|
+
return weekdays();
|
|
2306
|
+
},
|
|
2307
|
+
children: (day, index) => _$ssr(_tmpl$27, _$ssrAttribute("data-weekend", index() > 4 ? "true" : _$escape(undefined, true), false), _$escape(day))
|
|
1785
2308
|
})));
|
|
2309
|
+
const grid = () => _$ssr(_tmpl$28, _$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"), _$escape(weekdayRow()), _$escape(_$createComponent(For, {
|
|
2310
|
+
get each() {
|
|
2311
|
+
return weeks();
|
|
2312
|
+
},
|
|
2313
|
+
children: (week, index) => weekRow(() => week, index)
|
|
2314
|
+
})));
|
|
2315
|
+
const continuousRow = key => {
|
|
2316
|
+
const days = createMemo(() => Array.from({
|
|
2317
|
+
length: 7
|
|
2318
|
+
}, (_, offset) => {
|
|
2319
|
+
const dayKey = addDayKeys(key, offset);
|
|
2320
|
+
return {
|
|
2321
|
+
day: parseKey(dayKey),
|
|
2322
|
+
key: dayKey
|
|
2323
|
+
};
|
|
2324
|
+
}));
|
|
2325
|
+
return weekRow(days, () => monthRowOf(trackWeeks(), key) ?? 0);
|
|
2326
|
+
};
|
|
2327
|
+
const continuousGrid = () => _$ssr(_tmpl$29, _$ssrAttribute("aria-label", _$escape(formatMonth(parseKey(focusMonthKey()), dateConfig()), true), false), _$ssrAttribute("aria-rowcount", _$escape(trackWeeks().length, true) + 1, false), _$ssrStyleProperty("--k2b-calendar-lane:", "1.25rem") + _$ssrStyleProperty(";--k2b-calendar-lane-gap:", "0.125rem"), _$escape(weekdayRow()), _$ssrStyleProperty("--k2b-calendar-weeks:", _$escape(String(trackWeeks().length), true)), _$escape(_$createComponent(For, {
|
|
2328
|
+
get each() {
|
|
2329
|
+
return renderedWeeks();
|
|
2330
|
+
},
|
|
2331
|
+
children: continuousRow
|
|
2332
|
+
})), _$ssrAttribute("data-show", labelShown() ? "true" : "false", false), _$escape(formatMonth(parseKey(focusMonthKey()), dateConfig())));
|
|
1786
2333
|
const dayList = dayKey => {
|
|
1787
2334
|
const day = parseKey(dayKey);
|
|
1788
2335
|
const href = viewHref(dayKey, "day");
|
|
1789
2336
|
// Read where it renders, so a refresh while the list is open updates it as it does the grid.
|
|
1790
2337
|
const entries = () => dayEntries(dayKey);
|
|
1791
|
-
return _$ssr(_tmpl$
|
|
2338
|
+
return _$ssr(_tmpl$32, _$escape(dayLabel(day)), _$escape(_$createComponent(Show, {
|
|
1792
2339
|
get when() {
|
|
1793
2340
|
return entries().length > 0;
|
|
1794
2341
|
},
|
|
1795
2342
|
get fallback() {
|
|
1796
|
-
return _$ssr(_tmpl$
|
|
2343
|
+
return _$ssr(_tmpl$33, _$escape(calendarMessages().calendarNothingPlanned));
|
|
1797
2344
|
},
|
|
1798
2345
|
get children() {
|
|
1799
|
-
return _$ssr(_tmpl$
|
|
2346
|
+
return _$ssr(_tmpl$30, _$escape(_$createComponent(For, {
|
|
1800
2347
|
get each() {
|
|
1801
2348
|
return entries();
|
|
1802
2349
|
},
|
|
1803
|
-
children: item => _$ssr(_tmpl$
|
|
2350
|
+
children: item => _$ssr(_tmpl$34, _$escape(_$createComponent(EventChip, {
|
|
1804
2351
|
get event() {
|
|
1805
2352
|
return item.event;
|
|
1806
2353
|
},
|
|
@@ -1837,7 +2384,7 @@ const MonthView = props => {
|
|
|
1837
2384
|
size: "sm",
|
|
1838
2385
|
onClick: () => openView(dayKey, "day"),
|
|
1839
2386
|
get children() {
|
|
1840
|
-
return [_$ssr(_tmpl$
|
|
2387
|
+
return [_$ssr(_tmpl$35), calendarMessages().calendarOpenDay];
|
|
1841
2388
|
}
|
|
1842
2389
|
});
|
|
1843
2390
|
}
|
|
@@ -1856,7 +2403,7 @@ const MonthView = props => {
|
|
|
1856
2403
|
"data-size": "sm"
|
|
1857
2404
|
},
|
|
1858
2405
|
get children() {
|
|
1859
|
-
return [_$ssr(_tmpl$
|
|
2406
|
+
return [_$ssr(_tmpl$35), calendarMessages().calendarOpenDay];
|
|
1860
2407
|
}
|
|
1861
2408
|
})
|
|
1862
2409
|
})), _$escape(_$createComponent(Show, {
|
|
@@ -1878,18 +2425,19 @@ const MonthView = props => {
|
|
|
1878
2425
|
});
|
|
1879
2426
|
},
|
|
1880
2427
|
get children() {
|
|
1881
|
-
return [_$ssr(_tmpl$
|
|
2428
|
+
return [_$ssr(_tmpl$31), calendarMessages().calendarNewEvent];
|
|
1882
2429
|
}
|
|
1883
2430
|
});
|
|
1884
2431
|
}
|
|
1885
2432
|
})));
|
|
1886
2433
|
};
|
|
2434
|
+
const viewGrid = () => continuous() ? continuousGrid() : grid();
|
|
1887
2435
|
return [_$createComponent(Show, {
|
|
1888
2436
|
get when() {
|
|
1889
2437
|
return hasMenu();
|
|
1890
2438
|
},
|
|
1891
2439
|
get fallback() {
|
|
1892
|
-
return
|
|
2440
|
+
return viewGrid();
|
|
1893
2441
|
},
|
|
1894
2442
|
get children() {
|
|
1895
2443
|
return _$createComponent(GestureMenu, {
|
|
@@ -1903,11 +2451,11 @@ const MonthView = props => {
|
|
|
1903
2451
|
onOpen: onMenuOpen,
|
|
1904
2452
|
"class": "k2b-calendar-month-menu",
|
|
1905
2453
|
get children() {
|
|
1906
|
-
return
|
|
2454
|
+
return viewGrid();
|
|
1907
2455
|
}
|
|
1908
2456
|
});
|
|
1909
2457
|
}
|
|
1910
|
-
}), _$ssr(_tmpl$
|
|
2458
|
+
}), _$ssr(_tmpl$36, _$ssrAttribute("aria-label", (() => {
|
|
1911
2459
|
const current = popover();
|
|
1912
2460
|
if (current?.kind === "day") return dayLabel(parseKey(current.dayKey));
|
|
1913
2461
|
return _$escape(calendarMessages().calendarQuickCreate, true);
|
|
@@ -2151,14 +2699,14 @@ const TimeGridView = props => {
|
|
|
2151
2699
|
if (!scrollContainer || !defaultHourMarker) return;
|
|
2152
2700
|
const targetTop = defaultHourMarker.getBoundingClientRect().top - scrollContainer.getBoundingClientRect().top;
|
|
2153
2701
|
// Reduced motion jumps to the business hours instead of gliding there, like every transition of the library.
|
|
2154
|
-
const behavior =
|
|
2702
|
+
const behavior = prefersReducedMotion() ? "auto" : "smooth";
|
|
2155
2703
|
scrollContainer.scrollTo({
|
|
2156
2704
|
top: Math.max(0, scrollContainer.scrollTop + targetTop),
|
|
2157
2705
|
behavior
|
|
2158
2706
|
});
|
|
2159
2707
|
});
|
|
2160
2708
|
});
|
|
2161
|
-
return _$ssr(_tmpl$
|
|
2709
|
+
return _$ssr(_tmpl$38, _$ssrAttribute("data-view", isDayView() ? "day" : "week", false), _$ssrStyleProperty("grid-template-columns:", _$escape(columnTemplate(), true)), _$escape(_$createComponent(For, {
|
|
2162
2710
|
get each() {
|
|
2163
2711
|
return props.days;
|
|
2164
2712
|
},
|
|
@@ -2176,9 +2724,9 @@ const TimeGridView = props => {
|
|
|
2176
2724
|
class: "k2b-calendar-time-grid__day"
|
|
2177
2725
|
},
|
|
2178
2726
|
get children() {
|
|
2179
|
-
return [_$ssr(_tmpl$
|
|
2727
|
+
return [_$ssr(_tmpl$39, _$ssrAttribute("data-today", today() ? "true" : _$escape(undefined, true), false), _$escape(formatDay(day, dateConfig()))), _$createComponent(Show, {
|
|
2180
2728
|
when: dayBadge,
|
|
2181
|
-
children: badge => _$ssr(_tmpl$
|
|
2729
|
+
children: badge => _$ssr(_tmpl$40, _$escape(_$createComponent(Show, {
|
|
2182
2730
|
get when() {
|
|
2183
2731
|
return badge().icon;
|
|
2184
2732
|
},
|
|
@@ -2193,7 +2741,7 @@ const TimeGridView = props => {
|
|
|
2193
2741
|
return !props.owner.hideAllDay;
|
|
2194
2742
|
},
|
|
2195
2743
|
get children() {
|
|
2196
|
-
return _$ssr(_tmpl$
|
|
2744
|
+
return _$ssr(_tmpl$37, _$ssrStyleProperty("grid-template-columns:", _$escape(columnTemplate(), true)) + _$ssrStyleProperty(";max-height:", `${_$escape(props.owner.allDayMaxHeightRem ?? 7, true)}rem`), _$escape(props.labels.allDay), _$escape(_$createComponent(For, {
|
|
2197
2745
|
get each() {
|
|
2198
2746
|
return props.days;
|
|
2199
2747
|
},
|
|
@@ -2217,7 +2765,7 @@ const TimeGridView = props => {
|
|
|
2217
2765
|
end: calendar.addDays(start, 1, dateConfig()),
|
|
2218
2766
|
allDay: true
|
|
2219
2767
|
};
|
|
2220
|
-
}, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$
|
|
2768
|
+
}, () => performance.now() < suppressSlotClickUntil)), _$ssr(_tmpl$41, _$escape(_$createComponent(For, {
|
|
2221
2769
|
each: previewAllDay,
|
|
2222
2770
|
children: event => _$ssr(_tmpl$14, _$escape(event.title))
|
|
2223
2771
|
})), _$escape(_$createComponent(For, {
|
|
@@ -2248,7 +2796,7 @@ const TimeGridView = props => {
|
|
|
2248
2796
|
get each() {
|
|
2249
2797
|
return hours();
|
|
2250
2798
|
},
|
|
2251
|
-
children: hour => _$ssr(_tmpl$
|
|
2799
|
+
children: hour => _$ssr(_tmpl$42, _$ssrAttribute("data-outside-business", hour < businessStartHour() || hour > businessEndHour() ? "true" : _$escape(undefined, true), false), _$escape(`${hour}`.padStart(2, "0")))
|
|
2252
2800
|
})), _$escape(_$createComponent(For, {
|
|
2253
2801
|
get each() {
|
|
2254
2802
|
return props.days;
|
|
@@ -2256,12 +2804,12 @@ const TimeGridView = props => {
|
|
|
2256
2804
|
children: day => {
|
|
2257
2805
|
const dayKey = calendar.formatDateKey(day, dateConfig());
|
|
2258
2806
|
const layouts = createMemo(() => timedEventLayouts(eventsByDay().get(dayKey)?.timed ?? []));
|
|
2259
|
-
return _$ssr(_tmpl$
|
|
2807
|
+
return _$ssr(_tmpl$44, _$ssrStyleProperty("grid-template-rows:", `repeat(${_$escape(hours().length, true)}, minmax(4rem, 1fr))`), _$escape(_$createComponent(Show, {
|
|
2260
2808
|
get when() {
|
|
2261
2809
|
return currentTimeLine(day) !== null;
|
|
2262
2810
|
},
|
|
2263
2811
|
get children() {
|
|
2264
|
-
return _$ssr(_tmpl$
|
|
2812
|
+
return _$ssr(_tmpl$43, _$ssrStyleProperty("top:", `${_$escape(currentTimeLine(day) ?? 0, true)}%`));
|
|
2265
2813
|
}
|
|
2266
2814
|
})), _$escape(_$createComponent(For, {
|
|
2267
2815
|
get each() {
|
|
@@ -2290,12 +2838,12 @@ const TimeGridView = props => {
|
|
|
2290
2838
|
children: event => {
|
|
2291
2839
|
const layout = eventLayout(event);
|
|
2292
2840
|
const short = event.endDate.getTime() - event.startDate.getTime() < 60 * 60_000;
|
|
2293
|
-
return _$ssr(_tmpl$
|
|
2841
|
+
return _$ssr(_tmpl$46, _$ssrAttribute("data-short", short ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$escape(_$createComponent(Show, {
|
|
2294
2842
|
get when() {
|
|
2295
2843
|
return event.title;
|
|
2296
2844
|
},
|
|
2297
2845
|
get children() {
|
|
2298
|
-
return _$ssr(_tmpl$
|
|
2846
|
+
return _$ssr(_tmpl$45, _$escape(event.title));
|
|
2299
2847
|
}
|
|
2300
2848
|
})), _$escape(formatTime(event.startDate, dateConfig())), _$escape(formatTime(event.endDate, dateConfig())));
|
|
2301
2849
|
}
|
|
@@ -2341,7 +2889,7 @@ const TimeGridView = props => {
|
|
|
2341
2889
|
onCancel: clearInteraction
|
|
2342
2890
|
});
|
|
2343
2891
|
};
|
|
2344
|
-
return _$ssr(_tmpl$
|
|
2892
|
+
return _$ssr(_tmpl$48, _$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, {
|
|
2345
2893
|
event: event,
|
|
2346
2894
|
get owner() {
|
|
2347
2895
|
return props.owner;
|
|
@@ -2361,7 +2909,7 @@ const TimeGridView = props => {
|
|
|
2361
2909
|
return props.owner.onEventResize;
|
|
2362
2910
|
},
|
|
2363
2911
|
get children() {
|
|
2364
|
-
return _$ssr(_tmpl$
|
|
2912
|
+
return _$ssr(_tmpl$47, _$ssrAttribute("aria-label", _$escape(calendarMessages().resizeEvent, true), false));
|
|
2365
2913
|
}
|
|
2366
2914
|
})));
|
|
2367
2915
|
}
|
|
@@ -2373,14 +2921,14 @@ const TimeGridView = props => {
|
|
|
2373
2921
|
const layout = timeRangeLayout(overflow.groupStartDate, overflow.groupEndDate);
|
|
2374
2922
|
const key = `${dayKey}-${overflow.groupId}`;
|
|
2375
2923
|
const hiddenTitle = () => overflow.hiddenEvents.map(event => `${formatTime(event.startDate, dateConfig())} ${event.title}`).join("\n");
|
|
2376
|
-
return [_$ssr(_tmpl$
|
|
2924
|
+
return [_$ssr(_tmpl$49, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`) + _$ssrStyleProperty(";height:", `${_$escape(layout.height, true)}%`), _$ssrAttribute("title", _$escape(hiddenTitle(), true), false) + _$ssrAttribute("aria-label", _$escape(calendarMessages().hiddenOverlappingEvents({
|
|
2377
2925
|
count: overflow.hiddenEvents.length
|
|
2378
2926
|
}), true), false), _$escape(overflow.hiddenEvents.length)), _$createComponent(Show, {
|
|
2379
2927
|
get when() {
|
|
2380
2928
|
return expandedOverflow() === key;
|
|
2381
2929
|
},
|
|
2382
2930
|
get children() {
|
|
2383
|
-
return _$ssr(_tmpl$
|
|
2931
|
+
return _$ssr(_tmpl$50, _$ssrStyleProperty("top:", `${_$escape(layout.top, true)}%`), _$escape(formatTime(overflow.groupStartDate, dateConfig())), _$escape(formatTime(overflow.groupEndDate, dateConfig())), _$escape(_$createComponent(For, {
|
|
2384
2932
|
get each() {
|
|
2385
2933
|
return overflow.hiddenEvents;
|
|
2386
2934
|
},
|
|
@@ -2439,11 +2987,11 @@ const YearView = props => {
|
|
|
2439
2987
|
};
|
|
2440
2988
|
});
|
|
2441
2989
|
});
|
|
2442
|
-
return _$ssr(_tmpl$
|
|
2990
|
+
return _$ssr(_tmpl$51, _$escape(_$createComponent(For, {
|
|
2443
2991
|
get each() {
|
|
2444
2992
|
return months();
|
|
2445
2993
|
},
|
|
2446
|
-
children: month => _$ssr(_tmpl$
|
|
2994
|
+
children: month => _$ssr(_tmpl$52, _$escape(month.label), _$escape(_$createComponent(For, {
|
|
2447
2995
|
get each() {
|
|
2448
2996
|
return month.days;
|
|
2449
2997
|
},
|
|
@@ -2466,7 +3014,7 @@ const YearView = props => {
|
|
|
2466
3014
|
get when() {
|
|
2467
3015
|
return day.events[0];
|
|
2468
3016
|
},
|
|
2469
|
-
children: event => _$ssr(_tmpl$
|
|
3017
|
+
children: event => _$ssr(_tmpl$53, _$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 ? {
|
|
2470
3018
|
"background-color": day.isToday ? "white" : event().colorHex
|
|
2471
3019
|
} : undefined))
|
|
2472
3020
|
})];
|
|
@@ -2479,7 +3027,7 @@ const MobileMonthView = props => {
|
|
|
2479
3027
|
const dateConfig = createMemo(() => ownerDateConfig(props.owner));
|
|
2480
3028
|
const selectedDateKey = createMemo(() => calendar.formatDateKey(props.selectedDate, dateConfig()));
|
|
2481
3029
|
const selectedEvents = createMemo(() => props.events.filter(event => event.dayKey === selectedDateKey()));
|
|
2482
|
-
return _$ssr(_tmpl$
|
|
3030
|
+
return _$ssr(_tmpl$55, _$escape(_$createComponent(MonthPickerView, {
|
|
2483
3031
|
get owner() {
|
|
2484
3032
|
return {
|
|
2485
3033
|
...props.owner,
|
|
@@ -2509,10 +3057,10 @@ const MobileMonthView = props => {
|
|
|
2509
3057
|
return selectedEvents().length > 0;
|
|
2510
3058
|
},
|
|
2511
3059
|
get fallback() {
|
|
2512
|
-
return _$ssr(_tmpl$
|
|
3060
|
+
return _$ssr(_tmpl$56, _$escape(props.labels.noEvents));
|
|
2513
3061
|
},
|
|
2514
3062
|
get children() {
|
|
2515
|
-
return _$ssr(_tmpl$
|
|
3063
|
+
return _$ssr(_tmpl$54, _$escape(_$createComponent(For, {
|
|
2516
3064
|
get each() {
|
|
2517
3065
|
return selectedEvents();
|
|
2518
3066
|
},
|
|
@@ -2529,7 +3077,7 @@ const MobileMonthView = props => {
|
|
|
2529
3077
|
}
|
|
2530
3078
|
})));
|
|
2531
3079
|
};
|
|
2532
|
-
const CalendarBody = props => _$ssr(_tmpl$
|
|
3080
|
+
const CalendarBody = props => _$ssr(_tmpl$57, _$escape(props.children));
|
|
2533
3081
|
const CalendarRoot = props => {
|
|
2534
3082
|
const messages = useUiMessages();
|
|
2535
3083
|
const calendarMessages = useCalendarMessages();
|
|
@@ -2583,24 +3131,26 @@ const CalendarRoot = props => {
|
|
|
2583
3131
|
// The day and week views with `dayHours` scroll through their days; the header and the commands ask them first.
|
|
2584
3132
|
const [timeView, setTimeView] = createSignal(null);
|
|
2585
3133
|
const [monthCreate, setMonthCreate] = createSignal(null);
|
|
3134
|
+
const monthView = () => monthCreate()?.continuous() ? monthCreate() : null;
|
|
3135
|
+
const scrollingView = () => timeView() ?? monthView();
|
|
2586
3136
|
const timeMode = () => Boolean(props.dayHours) && (view() === "day" || view() === "week");
|
|
2587
3137
|
const parseKey = key => calendar.parseCalendarDate(key, dateConfig());
|
|
2588
3138
|
/** The first shown day of a day or week view, or the selected day of the month view, for the other views. */
|
|
2589
3139
|
const shownDay = () => {
|
|
2590
3140
|
const first = timeView()?.visibleKeys().first;
|
|
2591
3141
|
if (first) return parseKey(first);
|
|
2592
|
-
return view() === "month" ? focusDay() : null;
|
|
3142
|
+
return view() === "month" ? focusDay() ?? monthView()?.focusDay() ?? null : null;
|
|
2593
3143
|
};
|
|
2594
3144
|
const go = (target, nextView) => {
|
|
2595
3145
|
const href = props.getDateHref?.(target, nextView);
|
|
2596
3146
|
if (href) followCalendarHref(owner, href);else openViewAt(props, target, nextView);
|
|
2597
3147
|
};
|
|
2598
3148
|
const step = direction => {
|
|
2599
|
-
if (
|
|
2600
|
-
go(adjacentCalendarDate(shownDay() ?? date(), view(), direction, dateConfig()), view());
|
|
3149
|
+
if (scrollingView()?.step(direction)) return;
|
|
3150
|
+
go(adjacentCalendarDate(monthView()?.stepFrom() ?? shownDay() ?? date(), view(), direction, dateConfig()), view());
|
|
2601
3151
|
};
|
|
2602
3152
|
const goToday = () => {
|
|
2603
|
-
if (
|
|
3153
|
+
if (scrollingView()?.today()) return;
|
|
2604
3154
|
go(calendar.today(dateConfig()), view());
|
|
2605
3155
|
};
|
|
2606
3156
|
const goView = nextView => {
|
|
@@ -2613,7 +3163,7 @@ const CalendarRoot = props => {
|
|
|
2613
3163
|
if (href) followCalendarHref(owner, href);else props.onViewChange?.(nextView);
|
|
2614
3164
|
};
|
|
2615
3165
|
const goToKey = key => {
|
|
2616
|
-
if (
|
|
3166
|
+
if (scrollingView()?.goTo(key)) return;
|
|
2617
3167
|
go(parseKey(key), view());
|
|
2618
3168
|
};
|
|
2619
3169
|
const openGoTo = () => void openCalendarGoTo({
|
|
@@ -2708,6 +3258,7 @@ const CalendarRoot = props => {
|
|
|
2708
3258
|
});
|
|
2709
3259
|
const headerNav = {
|
|
2710
3260
|
timeView,
|
|
3261
|
+
monthView,
|
|
2711
3262
|
commands: () => props.onCommandsChange ? allCommands() : [],
|
|
2712
3263
|
// The arrow keys page like J and K, so the list names them beside those keys.
|
|
2713
3264
|
openShortcuts: () => void openCalendarShortcuts(allCommands(), calendarMessages(), custom() ? {} : {
|
|
@@ -2753,7 +3304,7 @@ const CalendarRoot = props => {
|
|
|
2753
3304
|
},
|
|
2754
3305
|
register: setTimeView
|
|
2755
3306
|
});
|
|
2756
|
-
return _$ssr(_tmpl$
|
|
3307
|
+
return _$ssr(_tmpl$58, `k2b-content-calendar ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("aria-busy", props.navigationPending ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(CalendarHeader, {
|
|
2757
3308
|
get date() {
|
|
2758
3309
|
return date();
|
|
2759
3310
|
},
|
|
@@ -2765,7 +3316,7 @@ const CalendarRoot = props => {
|
|
|
2765
3316
|
},
|
|
2766
3317
|
owner: owner,
|
|
2767
3318
|
get focusDay() {
|
|
2768
|
-
return _$memo(() => view() === "month"
|
|
3319
|
+
return _$memo(() => !!(view() === "month" || timeView()))() ? shownDay() : null;
|
|
2769
3320
|
},
|
|
2770
3321
|
nav: headerNav
|
|
2771
3322
|
})), _$escape(_$createComponent(Show, {
|
|
@@ -2802,6 +3353,7 @@ const CalendarRoot = props => {
|
|
|
2802
3353
|
return mergedLabels();
|
|
2803
3354
|
},
|
|
2804
3355
|
onFocusDay: setFocusDay,
|
|
3356
|
+
goToDate: date => go(date, view()),
|
|
2805
3357
|
register: setMonthCreate
|
|
2806
3358
|
});
|
|
2807
3359
|
}
|