@k2b/ui 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/browser/content/Calendar.js +1086 -1049
  2. package/dist/browser/content/Calendar.js.map +1 -1
  3. package/dist/browser/content/CalendarDayView.js +1187 -0
  4. package/dist/browser/content/CalendarDayView.js.map +1 -0
  5. package/dist/browser/content/CalendarWeekView.js +1571 -0
  6. package/dist/browser/content/CalendarWeekView.js.map +1 -0
  7. package/dist/browser/content/ChartExplorer.js +174 -82
  8. package/dist/browser/content/ChartExplorer.js.map +1 -1
  9. package/dist/browser/content/ChartFilterControls.js +90 -33
  10. package/dist/browser/content/ChartFilterControls.js.map +1 -1
  11. package/dist/browser/content/DataTable.js +199 -171
  12. package/dist/browser/content/DataTable.js.map +1 -1
  13. package/dist/browser/content/calendar-day-scroll.js +98 -0
  14. package/dist/browser/content/calendar-day-scroll.js.map +1 -0
  15. package/dist/browser/content/calendar-days.js +408 -0
  16. package/dist/browser/content/calendar-days.js.map +1 -0
  17. package/dist/browser/content/calendar-dialogs.js +236 -0
  18. package/dist/browser/content/calendar-dialogs.js.map +1 -0
  19. package/dist/browser/content/calendar-messages.js +210 -2
  20. package/dist/browser/content/calendar-messages.js.map +1 -1
  21. package/dist/browser/content/calendar-pointer.js +15 -3
  22. package/dist/browser/content/calendar-pointer.js.map +1 -1
  23. package/dist/browser/content/calendar-shared.js +328 -0
  24. package/dist/browser/content/calendar-shared.js.map +1 -0
  25. package/dist/browser/content/calendar-time-view.js +1649 -0
  26. package/dist/browser/content/calendar-time-view.js.map +1 -0
  27. package/dist/browser/content/chart-messages.js +10 -0
  28. package/dist/browser/content/chart-messages.js.map +1 -1
  29. package/dist/browser/content/index.js.map +1 -1
  30. package/dist/browser/inputs/Combobox.js +0 -1
  31. package/dist/browser/inputs/Combobox.js.map +1 -1
  32. package/dist/browser/layout/AppWorkspace.js +123 -97
  33. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  34. package/dist/browser/layout/PageTitle.js +4 -1
  35. package/dist/browser/layout/PageTitle.js.map +1 -1
  36. package/dist/browser/layout/app-workspace-controller.js +164 -86
  37. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  38. package/dist/browser/surfaces/StatCell.js +18 -6
  39. package/dist/browser/surfaces/StatCell.js.map +1 -1
  40. package/dist/ssr/content/Calendar.js +524 -335
  41. package/dist/ssr/content/Calendar.js.map +1 -1
  42. package/dist/ssr/content/CalendarDayView.js +800 -0
  43. package/dist/ssr/content/CalendarDayView.js.map +1 -0
  44. package/dist/ssr/content/CalendarWeekView.js +1069 -0
  45. package/dist/ssr/content/CalendarWeekView.js.map +1 -0
  46. package/dist/ssr/content/ChartExplorer.js +93 -34
  47. package/dist/ssr/content/ChartExplorer.js.map +1 -1
  48. package/dist/ssr/content/ChartFilterControls.js +49 -7
  49. package/dist/ssr/content/ChartFilterControls.js.map +1 -1
  50. package/dist/ssr/content/DataTable.js +69 -51
  51. package/dist/ssr/content/DataTable.js.map +1 -1
  52. package/dist/ssr/content/calendar-day-scroll.js +98 -0
  53. package/dist/ssr/content/calendar-day-scroll.js.map +1 -0
  54. package/dist/ssr/content/calendar-days.js +408 -0
  55. package/dist/ssr/content/calendar-days.js.map +1 -0
  56. package/dist/ssr/content/calendar-dialogs.js +159 -0
  57. package/dist/ssr/content/calendar-dialogs.js.map +1 -0
  58. package/dist/ssr/content/calendar-messages.js +210 -2
  59. package/dist/ssr/content/calendar-messages.js.map +1 -1
  60. package/dist/ssr/content/calendar-pointer.js +15 -3
  61. package/dist/ssr/content/calendar-pointer.js.map +1 -1
  62. package/dist/ssr/content/calendar-shared.js +261 -0
  63. package/dist/ssr/content/calendar-shared.js.map +1 -0
  64. package/dist/ssr/content/calendar-time-view.js +1306 -0
  65. package/dist/ssr/content/calendar-time-view.js.map +1 -0
  66. package/dist/ssr/content/chart-messages.js +10 -0
  67. package/dist/ssr/content/chart-messages.js.map +1 -1
  68. package/dist/ssr/content/index.js.map +1 -1
  69. package/dist/ssr/inputs/Combobox.js.map +1 -1
  70. package/dist/ssr/layout/AppWorkspace.js +38 -29
  71. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  72. package/dist/ssr/layout/PageTitle.js +4 -1
  73. package/dist/ssr/layout/PageTitle.js.map +1 -1
  74. package/dist/ssr/layout/app-workspace-controller.js +164 -86
  75. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  76. package/dist/ssr/surfaces/StatCell.js +2 -2
  77. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  78. package/dist/styles.css +1 -1
  79. package/dist/types/content/Calendar.d.ts +91 -0
  80. package/dist/types/content/CalendarDayView.d.ts +7 -0
  81. package/dist/types/content/CalendarWeekView.d.ts +7 -0
  82. package/dist/types/content/ChartExplorer.d.ts +36 -1
  83. package/dist/types/content/ChartFilterControls.d.ts +6 -1
  84. package/dist/types/content/DataTable.d.ts +5 -0
  85. package/dist/types/content/calendar-day-scroll.d.ts +42 -0
  86. package/dist/types/content/calendar-days.d.ts +192 -0
  87. package/dist/types/content/calendar-dialogs.d.ts +22 -0
  88. package/dist/types/content/calendar-messages.d.ts +99 -0
  89. package/dist/types/content/calendar-pointer.d.ts +9 -0
  90. package/dist/types/content/calendar-shared.d.ts +69 -0
  91. package/dist/types/content/calendar-time-view.d.ts +252 -0
  92. package/dist/types/content/chart-messages.d.ts +5 -0
  93. package/dist/types/content/index.d.ts +2 -2
  94. package/dist/types/layout/AppWorkspace.d.ts +25 -3
  95. package/dist/types/layout/PageTitle.d.ts +2 -1
  96. package/dist/types/layout/app-workspace-controller.d.ts +9 -1
  97. package/dist/types/surfaces/StatCell.d.ts +5 -0
  98. package/package.json +1 -1
@@ -0,0 +1,1571 @@
1
+ import { template as _$template } from "solid-js/web";
2
+ import { delegateEvents as _$delegateEvents } from "solid-js/web";
3
+ import { memo as _$memo } from "solid-js/web";
4
+ import { addEventListener as _$addEventListener } from "solid-js/web";
5
+ import { className as _$className } from "solid-js/web";
6
+ import { runHydrationEvents as _$runHydrationEvents } from "solid-js/web";
7
+ import { setStyleProperty as _$setStyleProperty } from "solid-js/web";
8
+ import { effect as _$effect } from "solid-js/web";
9
+ import { getNextElement as _$getNextElement } from "solid-js/web";
10
+ import { getNextMarker as _$getNextMarker } from "solid-js/web";
11
+ import { createComponent as _$createComponent } from "solid-js/web";
12
+ import { insert as _$insert } from "solid-js/web";
13
+ import { setAttribute as _$setAttribute } from "solid-js/web";
14
+ import { use as _$use } from "solid-js/web";
15
+ var _tmpl$ = /*#__PURE__*/_$template(`<span class=k2b-calendar-week__now-time aria-hidden=true>`),
16
+ _tmpl$2 = /*#__PURE__*/_$template(`<span class=k2b-calendar-night>`),
17
+ _tmpl$3 = /*#__PURE__*/_$template(`<span class=k2b-calendar-week__now-line>`),
18
+ _tmpl$4 = /*#__PURE__*/_$template(`<div class=k2b-calendar-week data-view=week><div class=k2b-calendar-week__scroll role=group><div class=k2b-calendar-week__grid><div class=k2b-calendar-week__top><div class=k2b-calendar-week__corner aria-hidden=true></div><!$><!/><div class=k2b-calendar-week__all-day-label aria-hidden=true><span class=k2b-calendar-week__all-day-long></span><span class=k2b-calendar-week__all-day-short></span></div><div class=k2b-calendar-week__all-day role=group><!$><!/><!$><!/></div></div><div class=k2b-calendar-week__body><div class=k2b-calendar-week__gutter><!$><!/><!$><!/><button type=button class=k2b-calendar-week__moon><i class="ti ti-moon"aria-hidden=true></i><i aria-hidden=true></i></button><!$><!/></div><div class=k2b-calendar-week__lines aria-hidden=true><!$><!/><!$><!/><!$><!/></div><!$><!/></div></div></div><p class=k2b-calendar-sr></p><!$><!/>`),
19
+ _tmpl$5 = /*#__PURE__*/_$template(`<button type=button class=k2b-calendar-week__head data-minute=-2><span class=k2b-calendar-week__weekday></span><span class=k2b-calendar-week__number></span><span class=k2b-calendar-week__extra></span><span class=k2b-calendar-week__load aria-hidden=true></span><span class=k2b-calendar-week__cheer aria-hidden=true><i class="ti ti-confetti"aria-hidden=true></i><span class=k2b-calendar-week__cheer-long></span><span class=k2b-calendar-week__cheer-short>`),
20
+ _tmpl$6 = /*#__PURE__*/_$template(`<span class=k2b-calendar-week__badge><!$><!/><!$><!/>`),
21
+ _tmpl$7 = /*#__PURE__*/_$template(`<i aria-hidden=true>`),
22
+ _tmpl$8 = /*#__PURE__*/_$template(`<span>`),
23
+ _tmpl$9 = /*#__PURE__*/_$template(`<div class=k2b-calendar-week__range aria-hidden=true style="grid-row:1 / -1">`),
24
+ _tmpl$0 = /*#__PURE__*/_$template(`<div class=k2b-calendar-week__slot><!$><!/><!$><!/>`),
25
+ _tmpl$1 = /*#__PURE__*/_$template(`<span class=k2b-calendar-week__hour aria-hidden=true>`),
26
+ _tmpl$10 = /*#__PURE__*/_$template(`<span class=k2b-calendar-week__hour data-night=true aria-hidden=true>`),
27
+ _tmpl$11 = /*#__PURE__*/_$template(`<span class=k2b-calendar-week__line>`),
28
+ _tmpl$12 = /*#__PURE__*/_$template(`<span class=k2b-calendar-week__fold>`),
29
+ _tmpl$13 = /*#__PURE__*/_$template(`<div class=k2b-calendar-week__fold-cell><ul class=k2b-calendar-fold__chips>`),
30
+ _tmpl$14 = /*#__PURE__*/_$template(`<span class=k2b-calendar-hover aria-hidden=true>`),
31
+ _tmpl$15 = /*#__PURE__*/_$template(`<div class=k2b-calendar-now aria-hidden=true>`),
32
+ _tmpl$16 = /*#__PURE__*/_$template(`<div class=k2b-calendar-week__column data-calendar-column role=group><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`),
33
+ _tmpl$17 = /*#__PURE__*/_$template(`<li><!$><!/><!$><!/>`);
34
+ import { dates as calendar } from "@k2b/stdlib";
35
+ import { createComputed, createEffect, createMemo, createSignal, createUniqueId, For, on, onCleanup, onMount, Show, untrack } from "solid-js";
36
+ import { GESTURE_GAP_MS, snapToColumn, wheelAxis, wheelDelta, wheelPixels } from "./calendar-day-scroll";
37
+ import { addDayKeys, DAY_MINUTES, dayHeightTerms, dayKeyNumber, dayKeyRange, dayMinuteAt, dayY, dayYTerms, markerLanes, readDayGeometry, termsCss } from "./calendar-days";
38
+ import { layoutMonthWeek } from "./calendar-month-layout";
39
+ import { startCalendarPointerSession } from "./calendar-pointer";
40
+ import { EventChip, eventHref, followCalendarHref, textWidth } from "./calendar-shared";
41
+ import { createTimeView, dayBands, dayGaps, dayLoad, eventAccent, foldedEntries, gapAside, isNearNow, longDay, markerAbove, nightHours, reducedMotion, swallowNextClick, TimeBand, TimeCheck, TimeGap, TimeMarker, TimeOverlays, TimeQuickCreate, weekKeysOf } from "./calendar-time-view";
42
+
43
+ /** Room a bar keeps beside its title and date hint: padding, torn edge, gap, and an icon such as a task box. */
44
+ const HINT_SLACK_PX = 36;
45
+
46
+ /**
47
+ * The week view with `dayHours`: the loaded days side by side in one strip, seven on a wide screen and three on a
48
+ * phone. A trackpad, Shift with the wheel, or a finger scroll it sideways day by day; each gesture keeps the axis it
49
+ * started on, and the strip settles on a day start. The arrows move by whole weeks.
50
+ */
51
+ export const CalendarWeekView = props => {
52
+ const view = createTimeView(props);
53
+ const [mounted, setMounted] = createSignal(false);
54
+ const [firstIndex, setFirstIndex] = createSignal(0);
55
+ const [visibleCount, setVisibleCount] = createSignal(7);
56
+ /** The week whose nights decide whether the night rows open, set by navigation, not by free scrolling. */
57
+ const [nightWeek, setNightWeek] = createSignal(untrack(view.anchorKey));
58
+ const [nightOverride, setNightOverride] = createSignal(null);
59
+ const [roving, setRoving] = createSignal("");
60
+ let scroller;
61
+ const helpId = createUniqueId();
62
+ const anchorWeek = () => weekKeysOf(view, view.anchorKey());
63
+ // The server and the first render draw only the shown week, so the strip never flashes the days before it.
64
+ const keys = createMemo(() => {
65
+ const {
66
+ first,
67
+ last
68
+ } = view.range();
69
+ if (mounted()) return dayKeyRange(first, last);
70
+ const week = anchorWeek();
71
+ return week[0] >= first && week[6] <= last ? week : dayKeyRange(first, last);
72
+ });
73
+ const indexOf = key => dayKeyNumber(key) - dayKeyNumber(keys()[0]);
74
+ const nightsOpen = createMemo(() => {
75
+ const override = nightOverride();
76
+ if (override !== null) return override;
77
+ return weekKeysOf(view, nightWeek()).some(key => view.dayOf(key).night);
78
+ });
79
+ createEffect(on(nightWeek, () => setNightOverride(null), {
80
+ defer: true
81
+ }));
82
+ const wake = () => view.wake();
83
+
84
+ // Columns and scrolling.
85
+ /** The exact width of a day column: columns are a seventh or a third of the strip, rarely whole pixels. */
86
+ const columnWidth = () => scroller?.querySelector("[data-calendar-column]")?.getBoundingClientRect().width ?? 0;
87
+ const gutterWidth = () => scroller?.querySelector(".k2b-calendar-week__gutter")?.offsetWidth ?? 0;
88
+ const leftOf = index => index * columnWidth();
89
+ const visibleIndex = () => {
90
+ const width = columnWidth();
91
+ return width > 0 && scroller ? Math.round(scroller.scrollLeft / width) : 0;
92
+ };
93
+ const visibleKeys = () => {
94
+ const first = keys()[Math.min(keys().length - 1, Math.max(0, firstIndex()))] ?? view.anchorKey();
95
+ return {
96
+ first,
97
+ last: addDayKeys(first, visibleCount() - 1)
98
+ };
99
+ };
100
+ /** Now shows in the hours while today is among the days in view, like the prototype's week. */
101
+ const nowShown = () => {
102
+ const {
103
+ first,
104
+ last
105
+ } = visibleKeys();
106
+ const today = view.nowKey();
107
+ return today >= first && today <= last && view.nowMinute() >= 0 && view.nowMinute() < (nightsOpen() ? DAY_MINUTES : wake());
108
+ };
109
+ let settling = false;
110
+ let glideTarget = null;
111
+ let glideTimer = 0;
112
+ const glideTo = (left, top) => {
113
+ if (!scroller) return;
114
+ const target = Math.max(0, Math.min(left, scroller.scrollWidth - scroller.clientWidth));
115
+ glideTarget = target;
116
+ window.clearTimeout(glideTimer);
117
+ glideTimer = window.setTimeout(() => {
118
+ glideTarget = null;
119
+ }, 1600);
120
+ scroller.scrollTo({
121
+ left: target,
122
+ ...(top === undefined ? {} : {
123
+ top
124
+ }),
125
+ behavior: reducedMotion() ? "instant" : "smooth"
126
+ });
127
+ };
128
+ /** The scroll position of a minute in the timeline, with now in the upper third. */
129
+ const topFor = minute => {
130
+ if (!scroller) return 0;
131
+ const body = scroller.querySelector("[data-calendar-body]");
132
+ const head = scroller.querySelector(".k2b-calendar-week__top");
133
+ if (!body || !head) return 0;
134
+ const geometry = readDayGeometry(body, wake(), nightsOpen());
135
+ const offset = body.getBoundingClientRect().top - scroller.getBoundingClientRect().top + scroller.scrollTop - head.offsetHeight;
136
+ return Math.max(0, offset + dayY(geometry, minute) - (scroller.clientHeight - head.offsetHeight) / 3);
137
+ };
138
+ /** The first column of a week: its first day, or on a phone a day of it kept inside the week. */
139
+ const columnFor = (key, phoneDay) => {
140
+ const week = weekKeysOf(view, key);
141
+ if (visibleCount() >= 7 || !phoneDay) return indexOf(week[0]);
142
+ const day = Math.max(0, Math.min(7 - visibleCount(), dayKeyNumber(phoneDay) - dayKeyNumber(week[0])));
143
+ return indexOf(week[day]);
144
+ };
145
+ const positionAt = key => {
146
+ if (!scroller) return;
147
+ measureCount();
148
+ const today = view.nowKey();
149
+ const inWeek = weekKeysOf(view, key).includes(today);
150
+ scroller.scrollLeft = leftOf(columnFor(key, key));
151
+ scroller.scrollTop = inWeek ? topFor(view.nowMinute()) : topFor(60);
152
+ lastLeft = scroller.scrollLeft;
153
+ syncFirst();
154
+ };
155
+ const measureCount = () => {
156
+ const width = columnWidth();
157
+ if (!scroller || width <= 0) return;
158
+ // Whole-pixel columns leave a few pixels at the right edge; the strip ends at its last whole day instead of
159
+ // showing a sliver of the next one.
160
+ const room = scroller.clientWidth + (Number.parseFloat(scroller.style.marginRight) || 0) - gutterWidth();
161
+ const count = Math.max(1, Math.round(room / width));
162
+ setVisibleCount(count);
163
+ const rest = Math.floor(room - count * width);
164
+ scroller.style.marginRight = rest > 0 ? `${rest}px` : "";
165
+ };
166
+ let reportTimer = 0;
167
+ let reported = "";
168
+ const syncFirst = () => {
169
+ const index = visibleIndex();
170
+ if (index !== untrack(firstIndex)) setFirstIndex(index);
171
+ if (!untrack(keys)[index]) return;
172
+ // The host learns the days the reader sees once they changed, after the scroll calmed down.
173
+ const {
174
+ first,
175
+ last
176
+ } = untrack(visibleKeys);
177
+ if (`${first}/${last}` === reported) return;
178
+ reported = `${first}/${last}`;
179
+ window.clearTimeout(reportTimer);
180
+ reportTimer = window.setTimeout(() => props.owner.onVisibleDateChange?.(view.parseKey(first), view.parseKey(last)), 250);
181
+ };
182
+
183
+ // A gesture keeps its axis; the strip settles on a day start once the scroll rests.
184
+ let axis = null;
185
+ let lastWheel = 0;
186
+ let fingers = 0;
187
+ let restTimer = 0;
188
+ let ready = false;
189
+ const settle = () => {
190
+ if (!scroller || fingers > 0 || settling || glideTarget !== null || view.dragging()) return;
191
+ const width = columnWidth();
192
+ const target = snapToColumn(scroller.scrollLeft, width);
193
+ if (Math.abs(target - scroller.scrollLeft) <= 0.5) return;
194
+ settling = true;
195
+ scroller.scrollTo({
196
+ left: target,
197
+ behavior: reducedMotion() ? "instant" : "smooth"
198
+ });
199
+ window.setTimeout(() => {
200
+ settling = false;
201
+ }, 450);
202
+ };
203
+ const onWheel = event => {
204
+ if (!scroller || event.ctrlKey || view.dragging()) return;
205
+ // A gesture that goes on takes over from a glide onto a day start; the strip settles again once it rests.
206
+ settling = false;
207
+ if (event.timeStamp - lastWheel > GESTURE_GAP_MS || axis === null) axis = wheelAxis(event.deltaX, event.deltaY, event.shiftKey);
208
+ lastWheel = event.timeStamp;
209
+ const delta = wheelPixels(wheelDelta(axis, event.deltaX, event.deltaY, event.shiftKey), event.deltaMode, axis === "x" ? scroller.clientWidth : scroller.clientHeight);
210
+ if (axis === "x") {
211
+ event.preventDefault();
212
+ glideTarget = null;
213
+ scroller.scrollLeft += delta;
214
+ } else if (event.deltaX !== 0) {
215
+ // A trackpad's slight sideways drift in a vertical gesture would move the days; only the vertical part counts.
216
+ event.preventDefault();
217
+ scroller.scrollTop += delta;
218
+ }
219
+ };
220
+ let askedEarlier = "";
221
+ let askedLater = "";
222
+ /** The last scroll position the strip read, to tell which way the reader moves. */
223
+ let lastLeft = 0;
224
+ /**
225
+ * Asks for the week before or after once the reader moves within a week of an end. Days loaded before the strip push
226
+ * it on by a week, so only moving toward an end asks; a glide may load later days, which push nothing.
227
+ */
228
+ const loadMore = () => {
229
+ if (!scroller || !ready || view.dragging()) return;
230
+ const width = columnWidth();
231
+ const {
232
+ first,
233
+ last
234
+ } = view.range();
235
+ const left = scroller.scrollLeft;
236
+ const direction = Math.sign(left - lastLeft);
237
+ lastLeft = left;
238
+ if (direction < 0 && glideTarget === null && left < width * 7 - 1 && props.owner.onLoadEarlier && askedEarlier !== first) {
239
+ askedEarlier = first;
240
+ void props.owner.onLoadEarlier();
241
+ }
242
+ if (direction > 0 && left + scroller.clientWidth > scroller.scrollWidth - width * 7 + 1 && props.owner.onLoadLater && askedLater !== last) {
243
+ askedLater = last;
244
+ void props.owner.onLoadLater();
245
+ }
246
+ };
247
+ let frame = 0;
248
+ const onScroll = () => {
249
+ if (!scroller) return;
250
+ if (glideTarget !== null && Math.abs(scroller.scrollLeft - glideTarget) < 2) glideTarget = null;
251
+ if (!frame) frame = requestAnimationFrame(() => {
252
+ frame = 0;
253
+ syncFirst();
254
+ loadMore();
255
+ rememberAnchor();
256
+ });
257
+ window.clearTimeout(restTimer);
258
+ restTimer = window.setTimeout(settle, fingers > 0 ? 160 : 140);
259
+ };
260
+
261
+ // Days loaded before the strip's first day shift it; the view keeps its days in place.
262
+ let anchor = null;
263
+ /** A day the host moved to before its days loaded; it goes on screen once they arrive. */
264
+ let pendingTarget = null;
265
+ /** Notes the day at the start of the strip, read against the days the strip draws, which may still be the old ones. */
266
+ const rememberAnchor = (drawn = untrack(keys)) => {
267
+ if (!scroller) return;
268
+ const width = columnWidth();
269
+ if (width <= 0) return;
270
+ const index = Math.floor(scroller.scrollLeft / width);
271
+ const key = drawn[index];
272
+ if (key) anchor = {
273
+ key,
274
+ offset: scroller.scrollLeft - index * width
275
+ };
276
+ };
277
+ // Before the days change the strip, note its place from the page as it stands. A computation runs before any render
278
+ // effect touches the page, so no row has shrunk the strip yet.
279
+ createComputed(on(keys, (next, drawn) => {
280
+ if (!untrack(mounted) || !drawn) return;
281
+ rememberAnchor(drawn);
282
+ // Days that come in before the strip move every index; the first day in view stays the same day, so what
283
+ // depends on the days in view, such as the all-day row, never sees the days that came in.
284
+ const shift = dayKeyNumber(drawn[0]) - dayKeyNumber(next[0]);
285
+ if (shift !== 0) setFirstIndex(index => index + shift);
286
+ }, {
287
+ defer: true
288
+ }));
289
+ createEffect(on(keys, () => {
290
+ if (!untrack(mounted) || !scroller) return;
291
+ if (pendingTarget && loaded(pendingTarget)) {
292
+ positionAt(pendingTarget);
293
+ pendingTarget = null;
294
+ rememberAnchor();
295
+ syncFirst();
296
+ return;
297
+ }
298
+ if (!anchor) return;
299
+ const index = indexOf(anchor.key);
300
+ const left = leftOf(index) + anchor.offset;
301
+ if (Math.abs(scroller.scrollLeft - left) > 0.5) scroller.scrollLeft = left;
302
+ lastLeft = scroller.scrollLeft;
303
+ }, {
304
+ defer: true
305
+ }));
306
+ onMount(() => {
307
+ setMounted(true);
308
+ queueMicrotask(() => {
309
+ positionAt(view.anchorKey());
310
+ rememberAnchor();
311
+ ready = true;
312
+ });
313
+ const observer = typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver(() => {
314
+ const before = untrack(firstIndex);
315
+ measureCount();
316
+ if (!scroller) return;
317
+ scroller.scrollLeft = leftOf(before);
318
+ lastLeft = scroller.scrollLeft;
319
+ syncFirst();
320
+ });
321
+ if (scroller) observer?.observe(scroller);
322
+ onCleanup(() => {
323
+ observer?.disconnect();
324
+ window.clearTimeout(restTimer);
325
+ window.clearTimeout(reportTimer);
326
+ window.clearTimeout(glideTimer);
327
+ if (frame) cancelAnimationFrame(frame);
328
+ });
329
+ });
330
+ createEffect(on(view.anchorKey, key => {
331
+ if (!untrack(mounted)) return;
332
+ setNightWeek(key);
333
+ pendingTarget = loaded(key) ? null : key;
334
+ if (pendingTarget) return;
335
+ if (key === untrack(visibleKeys).first) {
336
+ rememberAnchor();
337
+ return;
338
+ }
339
+ queueMicrotask(() => {
340
+ positionAt(key);
341
+ rememberAnchor();
342
+ });
343
+ }, {
344
+ defer: true
345
+ }));
346
+ const loaded = key => key >= view.range().first && key <= view.range().last;
347
+ const handle = {
348
+ visibleKeys,
349
+ step: direction => {
350
+ const first = visibleKeys().first;
351
+ const week = weekKeysOf(view, first);
352
+ // From the middle of a week the arrows go to the start of a week first.
353
+ const target = direction > 0 ? addDayKeys(week[0], 7) : first === week[0] ? addDayKeys(week[0], -7) : week[0];
354
+ const last = addDayKeys(target, Math.min(6, visibleCount() - 1));
355
+ if (!loaded(target) || !loaded(last)) return false;
356
+ setNightWeek(target);
357
+ glideTo(leftOf(indexOf(target)));
358
+ return true;
359
+ },
360
+ goTo: key => {
361
+ if (!loaded(key)) return false;
362
+ setNightWeek(key);
363
+ view.setSelection({
364
+ key
365
+ });
366
+ glideTo(leftOf(columnFor(key, key)));
367
+ return true;
368
+ },
369
+ today: () => {
370
+ const today = view.nowKey();
371
+ const week = weekKeysOf(view, today);
372
+ if (!loaded(week[0]) || !loaded(week[6])) return false;
373
+ setNightWeek(today);
374
+ queueMicrotask(() => glideTo(leftOf(columnFor(today, today)), topFor(view.nowMinute())));
375
+ return true;
376
+ },
377
+ todayDirection: () => {
378
+ const today = view.nowKey();
379
+ const {
380
+ first,
381
+ last
382
+ } = visibleKeys();
383
+ if (today < first) return "left";
384
+ if (today > last) return "right";
385
+ return "";
386
+ },
387
+ controller: {
388
+ quickCreate: create => {
389
+ const target = view.createTarget(visibleKeys());
390
+ const column = scroller?.querySelector(`[data-calendar-body="${target.key}"]`);
391
+ view.openQuickCreate(target.key, target.start, target.end, slotRect(target.key, target.start, target.end) ?? column ?? scroller, create);
392
+ },
393
+ createTarget: () => view.rangeOfSelection(view.createTarget(visibleKeys())),
394
+ dragIn: (event, item, onDrop) => view.dragIn(event, item, onDrop, scroller)
395
+ }
396
+ };
397
+ const slotRect = (key, start, end) => {
398
+ const body = scroller?.querySelector(`[data-calendar-body="${key}"]`);
399
+ if (!body || !scroller) return null;
400
+ const rect = body.getBoundingClientRect();
401
+ const bounds = scroller.getBoundingClientRect();
402
+ if (rect.right < bounds.left + gutterWidth() || rect.left > bounds.right) return null;
403
+ const geometry = readDayGeometry(body, wake(), nightsOpen());
404
+ const top = rect.top + dayY(geometry, start);
405
+ const bottom = rect.top + dayY(geometry, end);
406
+ if (bottom < bounds.top + 40 || top > bounds.bottom - 20) return null;
407
+ return new DOMRect(rect.left, Math.max(bounds.top, top), rect.width, Math.max(8, Math.min(bottom, bounds.bottom) - Math.max(bounds.top, top)));
408
+ };
409
+ onMount(() => props.register(handle));
410
+ onCleanup(() => props.register(null));
411
+
412
+ // The all-day row: one bar per week, with a torn edge where an event goes on in the week before or after.
413
+ const allDay = createMemo(() => {
414
+ const all = keys();
415
+ const spans = new Map();
416
+ for (const key of all) for (const span of view.dayOf(key).spans) spans.set(span.item, span);
417
+ const entries = [...spans.values()].sort((left, right) => left.firstKey.localeCompare(right.firstKey) || right.lastKey.localeCompare(left.lastKey)).map(span => ({
418
+ item: span,
419
+ firstKey: span.firstKey,
420
+ lastKey: span.lastKey,
421
+ bar: !span.marker
422
+ }));
423
+ const weeks = [];
424
+ for (let index = 0; index < all.length;) {
425
+ const week = weekKeysOf(view, all[index]).filter(key => key >= all[0] && key <= all[all.length - 1]);
426
+ const offset = indexOf(week[0]);
427
+ weeks.push({
428
+ offset,
429
+ keys: week
430
+ });
431
+ index = offset + week.length;
432
+ }
433
+ return weeks.map(week => {
434
+ const layout = layoutMonthWeek(week.keys, entries);
435
+ const lanes = Math.max(0, ...layout.bars.map(bar => bar.lane + 1));
436
+ return {
437
+ ...week,
438
+ layout,
439
+ rows: lanes + Math.max(0, ...layout.singles.map(singles => singles.length))
440
+ };
441
+ });
442
+ });
443
+ /**
444
+ * The rows the weeks in view need, as in a week of its own. A week that loads off screen never changes them, so the
445
+ * hours stay where they are; its entries below these rows wait hidden until it comes into view.
446
+ */
447
+ const allDayRows = createMemo(() => {
448
+ const first = firstIndex();
449
+ const last = first + visibleCount() - 1;
450
+ return Math.max(1, ...allDay().filter(week => week.offset <= last && week.offset + week.keys.length - 1 >= first).map(week => week.rows));
451
+ });
452
+
453
+ // Keyboard: one tab stop in the grid; the arrows move between days, entries, and free time. Only what is drawn can
454
+ // take the focus.
455
+ const stops = () => [...(scroller?.querySelectorAll("[data-stop]") ?? [])].filter(stop => stop.getClientRects().length > 0);
456
+ const focusDayKey = () => {
457
+ const current = view.selection()?.key;
458
+ const {
459
+ first,
460
+ last
461
+ } = visibleKeys();
462
+ if (current && current >= first && current <= last) return current;
463
+ return view.nowKey() >= first && view.nowKey() <= last ? view.nowKey() : first;
464
+ };
465
+ const rovingId = () => roving() || `h:${focusDayKey()}`;
466
+ const tabOf = id => rovingId() === id ? 0 : -1;
467
+ // An entry that leaves the days gives the grid's tab stop back to a heading after the page has updated.
468
+ createEffect(on(view.days, () => {
469
+ queueMicrotask(() => {
470
+ if (!scroller || !roving()) return;
471
+ if ([...scroller.querySelectorAll("[data-stop]")].some(stop => stop.dataset.stop === roving())) return;
472
+ setRoving("");
473
+ if (!document.activeElement || document.activeElement === document.body) {
474
+ scroller.querySelector(`[data-stop="h:${focusDayKey()}"]`)?.focus({
475
+ preventScroll: true
476
+ });
477
+ }
478
+ });
479
+ }, {
480
+ defer: true
481
+ }));
482
+ const onKeyDown = event => {
483
+ const current = event.target instanceof HTMLElement ? event.target.closest("[data-stop]") : null;
484
+ if (!current || event.altKey || event.metaKey || event.ctrlKey) return;
485
+ const direction = {
486
+ ArrowUp: "up",
487
+ ArrowDown: "down",
488
+ ArrowLeft: "left",
489
+ ArrowRight: "right",
490
+ Home: "home",
491
+ End: "end"
492
+ }[event.key];
493
+ if (!direction) return;
494
+ event.preventDefault();
495
+ const all = stops();
496
+ const column = Number(current.dataset.col);
497
+ const minute = Number(current.dataset.minute);
498
+ const inColumn = index => all.filter(stop => Number(stop.dataset.col) === index).sort((left, right) => Number(left.dataset.minute) - Number(right.dataset.minute));
499
+ const list = inColumn(column);
500
+ const position = list.indexOf(current);
501
+ let next;
502
+ if (direction === "down") next = list[position + 1];else if (direction === "up") next = list[position - 1];else if (direction === "home") next = list[0];else if (direction === "end") next = list[list.length - 1];else {
503
+ const other = inColumn(column + (direction === "left" ? -1 : 1));
504
+ next = other.reduce((best, stop) => Math.abs(Number(stop.dataset.minute) - minute) < Math.abs(Number(best?.dataset.minute ?? Number.POSITIVE_INFINITY) - minute) ? stop : best, undefined);
505
+ }
506
+ if (!next) return;
507
+ setRoving(next.dataset.stop ?? "");
508
+ next.focus({
509
+ preventScroll: Boolean(next.closest(".k2b-calendar-week__top"))
510
+ });
511
+ const index = Number(next.dataset.col);
512
+ const first = untrack(firstIndex);
513
+ if (index < first) glideTo(leftOf(index));else if (index >= first + visibleCount()) glideTo(leftOf(index - visibleCount() + 1));
514
+ };
515
+ const openDay = key => {
516
+ const href = props.owner.views && !props.owner.views.includes("day") ? undefined : props.owner.getDateHref?.(view.parseKey(key), "day");
517
+ if (href) followCalendarHref(props.owner, href);else {
518
+ props.owner.onViewChange?.("day");
519
+ props.owner.onDateChange?.(view.parseKey(key), "day");
520
+ }
521
+ };
522
+ let lastPointer = "mouse";
523
+
524
+ // The all-day row: drag across days for one all-day event; a double-click creates on one day.
525
+ const startAllDayRange = (pointerEvent, row) => {
526
+ if (pointerEvent.pointerType !== "mouse" || pointerEvent.button !== 0 || !view.canCreate()) return;
527
+ const keyAt = clientX => {
528
+ const width = columnWidth();
529
+ const rect = row.getBoundingClientRect();
530
+ const index = Math.max(0, Math.min(keys().length - 1, Math.floor((clientX - rect.left) / width)));
531
+ return keys()[index];
532
+ };
533
+ const origin = keyAt(pointerEvent.clientX);
534
+ startCalendarPointerSession({
535
+ event: pointerEvent,
536
+ resolve: clientX => keyAt(clientX),
537
+ onPreview: key => setRangeSelection(origin < key ? {
538
+ first: origin,
539
+ last: key
540
+ } : {
541
+ first: key,
542
+ last: origin
543
+ }),
544
+ onCommit: key => {
545
+ swallowNextClick();
546
+ const range = origin < key ? {
547
+ first: origin,
548
+ last: key
549
+ } : {
550
+ first: key,
551
+ last: origin
552
+ };
553
+ const cells = scroller?.querySelector(".k2b-calendar-week__range");
554
+ setRangeSelection(null);
555
+ const start = view.parseKey(range.first);
556
+ const end = calendar.addDays(view.parseKey(range.last), 1, view.dateConfig());
557
+ if (props.owner.renderQuickCreate) view.setQuick({
558
+ range: {
559
+ start,
560
+ end,
561
+ allDay: true
562
+ },
563
+ anchor: cells?.getBoundingClientRect() ?? row,
564
+ key: range.first
565
+ });else props.owner.onSlotActivate?.({
566
+ start,
567
+ end,
568
+ allDay: true
569
+ });
570
+ },
571
+ onCancel: () => setRangeSelection(null)
572
+ });
573
+ };
574
+ const [rangeSelection, setRangeSelection] = createSignal(null);
575
+ return (() => {
576
+ var _el$ = _$getNextElement(_tmpl$4),
577
+ _el$2 = _el$.firstChild,
578
+ _el$3 = _el$2.firstChild,
579
+ _el$4 = _el$3.firstChild,
580
+ _el$5 = _el$4.firstChild,
581
+ _el$12 = _el$5.nextSibling,
582
+ [_el$13, _co$3] = _$getNextMarker(_el$12.nextSibling),
583
+ _el$6 = _el$13.nextSibling,
584
+ _el$7 = _el$6.firstChild,
585
+ _el$8 = _el$7.nextSibling,
586
+ _el$9 = _el$6.nextSibling,
587
+ _el$0 = _el$9.firstChild,
588
+ [_el$1, _co$] = _$getNextMarker(_el$0.nextSibling),
589
+ _el$10 = _el$1.nextSibling,
590
+ [_el$11, _co$2] = _$getNextMarker(_el$10.nextSibling),
591
+ _el$14 = _el$4.nextSibling,
592
+ _el$15 = _el$14.firstChild,
593
+ _el$20 = _el$15.firstChild,
594
+ [_el$21, _co$4] = _$getNextMarker(_el$20.nextSibling),
595
+ _el$22 = _el$21.nextSibling,
596
+ [_el$23, _co$5] = _$getNextMarker(_el$22.nextSibling),
597
+ _el$16 = _el$23.nextSibling,
598
+ _el$17 = _el$16.firstChild,
599
+ _el$18 = _el$17.nextSibling,
600
+ _el$24 = _el$16.nextSibling,
601
+ [_el$25, _co$6] = _$getNextMarker(_el$24.nextSibling),
602
+ _el$26 = _el$15.nextSibling,
603
+ _el$29 = _el$26.firstChild,
604
+ [_el$30, _co$7] = _$getNextMarker(_el$29.nextSibling),
605
+ _el$31 = _el$30.nextSibling,
606
+ [_el$32, _co$8] = _$getNextMarker(_el$31.nextSibling),
607
+ _el$33 = _el$32.nextSibling,
608
+ [_el$34, _co$9] = _$getNextMarker(_el$33.nextSibling),
609
+ _el$35 = _el$26.nextSibling,
610
+ [_el$36, _co$0] = _$getNextMarker(_el$35.nextSibling),
611
+ _el$37 = _el$2.nextSibling,
612
+ _el$38 = _el$37.nextSibling,
613
+ [_el$39, _co$1] = _$getNextMarker(_el$38.nextSibling);
614
+ _el$2.addEventListener("touchcancel", event => {
615
+ fingers = event.touches.length;
616
+ });
617
+ _el$2.$$touchend = event => {
618
+ fingers = event.touches.length;
619
+ onScroll();
620
+ };
621
+ _el$2.$$touchstart = event => {
622
+ fingers = event.touches.length;
623
+ glideTarget = null;
624
+ };
625
+ _el$2.$$focusin = event => {
626
+ const stop = event.target instanceof HTMLElement ? event.target.closest("[data-stop]") : null;
627
+ if (stop?.dataset.stop) setRoving(stop.dataset.stop);
628
+ };
629
+ _el$2.$$keydown = onKeyDown;
630
+ _el$2.addEventListener("wheel", onWheel);
631
+ _el$2.addEventListener("scroll", onScroll);
632
+ var _ref$ = scroller;
633
+ typeof _ref$ === "function" ? _$use(_ref$, _el$2) : scroller = _el$2;
634
+ _$setAttribute(_el$2, "aria-describedby", helpId);
635
+ _$insert(_el$5, () => view.messages().calendarWeekNumber({
636
+ week: isoWeek(visibleKeys().first)
637
+ }));
638
+ _$insert(_el$4, _$createComponent(For, {
639
+ get each() {
640
+ return keys();
641
+ },
642
+ children: key => {
643
+ const today = () => key === view.calendarToday();
644
+ const selected = () => {
645
+ const current = view.selection();
646
+ return Boolean(current && current.key === key && current.start === undefined);
647
+ };
648
+ const badge = () => props.owner.dayBadges?.[key];
649
+ const load = () => dayLoad(view, key);
650
+ const date = () => view.parseKey(key);
651
+ return (() => {
652
+ var _el$40 = _$getNextElement(_tmpl$5),
653
+ _el$41 = _el$40.firstChild,
654
+ _el$42 = _el$41.nextSibling,
655
+ _el$43 = _el$42.nextSibling,
656
+ _el$44 = _el$43.nextSibling,
657
+ _el$45 = _el$44.nextSibling,
658
+ _el$46 = _el$45.firstChild,
659
+ _el$47 = _el$46.nextSibling,
660
+ _el$48 = _el$47.nextSibling;
661
+ _el$40.$$click = event => {
662
+ if (event.detail >= 2 || selected() && lastPointer !== "mouse") {
663
+ openDay(key);
664
+ return;
665
+ }
666
+ view.setTouchDraft(null);
667
+ view.setSelection(selected() ? null : {
668
+ key
669
+ });
670
+ };
671
+ _el$40.$$pointerdown = event => {
672
+ lastPointer = event.pointerType;
673
+ // The heading stays on top: focusing it must not scroll the grid.
674
+ if (event.button === 0) {
675
+ event.preventDefault();
676
+ event.currentTarget.focus({
677
+ preventScroll: true
678
+ });
679
+ }
680
+ };
681
+ _$setAttribute(_el$40, "data-calendar-head", key);
682
+ _$setAttribute(_el$40, "data-stop", `h:${key}`);
683
+ _$insert(_el$41, () => date().toLocaleDateString(view.dateConfig().locale ?? "en", {
684
+ weekday: "short",
685
+ timeZone: view.dateConfig().timeZone
686
+ }).replace(/\.$/, ""));
687
+ _$insert(_el$42, () => calendar.formatDayNumber(date(), view.dateConfig()));
688
+ _$insert(_el$43, _$createComponent(Show, {
689
+ get when() {
690
+ return badge();
691
+ },
692
+ children: current => (() => {
693
+ var _el$49 = _$getNextElement(_tmpl$6),
694
+ _el$50 = _el$49.firstChild,
695
+ [_el$51, _co$10] = _$getNextMarker(_el$50.nextSibling),
696
+ _el$52 = _el$51.nextSibling,
697
+ [_el$53, _co$11] = _$getNextMarker(_el$52.nextSibling);
698
+ _$insert(_el$49, _$createComponent(Show, {
699
+ get when() {
700
+ return current().icon;
701
+ },
702
+ children: icon => (() => {
703
+ var _el$54 = _$getNextElement(_tmpl$7);
704
+ _$effect(() => _$className(_el$54, `ti ti-${icon()}`));
705
+ return _el$54;
706
+ })()
707
+ }), _el$51, _co$10);
708
+ _$insert(_el$49, () => current().label, _el$53, _co$11);
709
+ return _el$49;
710
+ })()
711
+ }));
712
+ _$insert(_el$44, _$createComponent(For, {
713
+ get each() {
714
+ return load();
715
+ },
716
+ children: piece => (() => {
717
+ var _el$55 = _$getNextElement(_tmpl$8);
718
+ _$effect(_p$ => {
719
+ var _v$21 = `${(piece.end - piece.start) / wake() * 100}%`,
720
+ _v$22 = piece.color;
721
+ _v$21 !== _p$.e && _$setStyleProperty(_el$55, "width", _p$.e = _v$21);
722
+ _v$22 !== _p$.t && _$setStyleProperty(_el$55, "background", _p$.t = _v$22);
723
+ return _p$;
724
+ }, {
725
+ e: undefined,
726
+ t: undefined
727
+ });
728
+ return _el$55;
729
+ })()
730
+ }));
731
+ _$insert(_el$47, () => view.messages().calendarAllDone);
732
+ _$insert(_el$48, () => view.messages().calendarAllDoneShort);
733
+ _$effect(_p$ => {
734
+ var _v$13 = indexOf(key),
735
+ _v$14 = tabOf(`h:${key}`),
736
+ _v$15 = selected() ? "true" : "false",
737
+ _v$16 = [longDay(view, key), today() ? view.props.labels.today : "", badge()?.label ?? ""].filter(Boolean).join(", "),
738
+ _v$17 = today() ? "true" : undefined,
739
+ _v$18 = key < view.calendarToday() ? "true" : undefined,
740
+ _v$19 = view.cheered() === key ? "true" : undefined,
741
+ _v$20 = String(indexOf(key) + 2);
742
+ _v$13 !== _p$.e && _$setAttribute(_el$40, "data-col", _p$.e = _v$13);
743
+ _v$14 !== _p$.t && _$setAttribute(_el$40, "tabindex", _p$.t = _v$14);
744
+ _v$15 !== _p$.a && _$setAttribute(_el$40, "aria-pressed", _p$.a = _v$15);
745
+ _v$16 !== _p$.o && _$setAttribute(_el$40, "aria-label", _p$.o = _v$16);
746
+ _v$17 !== _p$.i && _$setAttribute(_el$40, "data-today", _p$.i = _v$17);
747
+ _v$18 !== _p$.n && _$setAttribute(_el$40, "data-past", _p$.n = _v$18);
748
+ _v$19 !== _p$.s && _$setAttribute(_el$40, "data-cheer", _p$.s = _v$19);
749
+ _v$20 !== _p$.h && _$setStyleProperty(_el$40, "grid-column", _p$.h = _v$20);
750
+ return _p$;
751
+ }, {
752
+ e: undefined,
753
+ t: undefined,
754
+ a: undefined,
755
+ o: undefined,
756
+ i: undefined,
757
+ n: undefined,
758
+ s: undefined,
759
+ h: undefined
760
+ });
761
+ _$runHydrationEvents();
762
+ return _el$40;
763
+ })();
764
+ }
765
+ }), _el$13, _co$3);
766
+ _$insert(_el$7, () => view.messages().calendarAllDayRow);
767
+ _$insert(_el$8, () => view.messages().calendarAllDayRowShort);
768
+ _el$9.$$dblclick = event => {
769
+ if (!(event.target instanceof Element) || event.target.closest("a,button,[data-calendar-event]")) return;
770
+ const width = columnWidth();
771
+ const rect = event.currentTarget.getBoundingClientRect();
772
+ const key = keys()[Math.max(0, Math.min(keys().length - 1, Math.floor((event.clientX - rect.left) / width)))];
773
+ const start = view.parseKey(key);
774
+ const range = {
775
+ start,
776
+ end: calendar.addDays(start, 1, view.dateConfig()),
777
+ allDay: true
778
+ };
779
+ if (props.owner.renderQuickCreate) view.setQuick({
780
+ range,
781
+ anchor: new DOMRect(rect.left + indexOf(key) * width, rect.top, width, rect.height),
782
+ key
783
+ });else props.owner.onSlotActivate?.(range);
784
+ };
785
+ _el$9.$$pointerdown = event => {
786
+ if (event.target instanceof Element && event.target.closest("a,button,[data-calendar-event]")) return;
787
+ startAllDayRange(event, event.currentTarget);
788
+ };
789
+ _$insert(_el$9, _$createComponent(Show, {
790
+ get when() {
791
+ return rangeSelection();
792
+ },
793
+ children: range => (() => {
794
+ var _el$56 = _$getNextElement(_tmpl$9);
795
+ _$effect(_$p => _$setStyleProperty(_el$56, "grid-column", `${indexOf(range().first) + 1} / ${indexOf(range().last) + 2}`));
796
+ return _el$56;
797
+ })()
798
+ }), _el$1, _co$);
799
+ _$insert(_el$9, _$createComponent(For, {
800
+ get each() {
801
+ return allDay();
802
+ },
803
+ children: week => [_$createComponent(For, {
804
+ get each() {
805
+ return week.layout.bars;
806
+ },
807
+ children: bar => {
808
+ const span = bar.endColumn - bar.startColumn + 1;
809
+ const event = bar.item.item;
810
+ const checked = () => view.checkedOf(event);
811
+ const hint = (target, kind, before = "") => {
812
+ const text = kind === "from" ? view.messages().calendarContinuesFrom(hintDate(view, target, visibleKeys().first)) : view.messages().calendarContinuesUntil(hintDate(view, target, visibleKeys().first));
813
+ const font = `600 11px ${typeof document === "undefined" ? "sans-serif" : getComputedStyle(document.body).fontFamily}`;
814
+ return textWidth(`${event.title}${before}`, font) + textWidth(text, font) + HINT_SLACK_PX <= span * columnWidthSignal() ? text : undefined;
815
+ };
816
+ const start = () => bar.continuesBefore ? hint(bar.item.firstKey, "from") : undefined;
817
+ const end = () => bar.continuesAfter ? hint(bar.item.lastKey, "until", start() ?? "") : undefined;
818
+ return (() => {
819
+ var _el$57 = _$getNextElement(_tmpl$0),
820
+ _el$58 = _el$57.firstChild,
821
+ [_el$59, _co$12] = _$getNextMarker(_el$58.nextSibling),
822
+ _el$60 = _el$59.nextSibling,
823
+ [_el$61, _co$13] = _$getNextMarker(_el$60.nextSibling);
824
+ _$insert(_el$57, _$createComponent(Show, {
825
+ get when() {
826
+ return checked() !== undefined;
827
+ },
828
+ get children() {
829
+ return _$createComponent(TimeCheck, {
830
+ view: view,
831
+ event: event,
832
+ tabIndex: -1
833
+ });
834
+ }
835
+ }), _el$59, _co$12);
836
+ _$insert(_el$57, _$createComponent(EventChip, {
837
+ get event() {
838
+ return view.normalized(event, bar.item.firstKey);
839
+ },
840
+ get owner() {
841
+ return props.owner;
842
+ },
843
+ get href() {
844
+ return eventHref(props.owner, event);
845
+ },
846
+ get label() {
847
+ return spanLabel(view, bar.item);
848
+ },
849
+ compact: true,
850
+ timeline: true,
851
+ bar: true,
852
+ get checkbox() {
853
+ return checked() !== undefined;
854
+ },
855
+ get onCheck() {
856
+ return view.checkOf(event);
857
+ },
858
+ get continuesBefore() {
859
+ return bar.continuesBefore;
860
+ },
861
+ get continuesAfter() {
862
+ return bar.continuesAfter;
863
+ },
864
+ get hintStart() {
865
+ return start();
866
+ },
867
+ get hintEnd() {
868
+ return end();
869
+ },
870
+ get tabIndex() {
871
+ return tabOf(`a:${event.id}:${week.offset}`);
872
+ },
873
+ get stop() {
874
+ return {
875
+ id: `a:${event.id}:${week.offset}`,
876
+ column: week.offset + bar.startColumn,
877
+ minute: -1 + bar.lane / 100
878
+ };
879
+ }
880
+ }), _el$61, _co$13);
881
+ _$effect(_p$ => {
882
+ var _v$23 = checked() !== undefined ? "true" : undefined,
883
+ _v$24 = checked() ? "true" : undefined,
884
+ _v$25 = view.justChecked().has(event.id) ? "true" : undefined,
885
+ _v$26 = `${week.offset + bar.startColumn + 1} / ${week.offset + bar.endColumn + 2}`,
886
+ _v$27 = String(bar.lane + 1),
887
+ _v$28 = eventAccent(event),
888
+ _v$29 = bar.lane + 1 > allDayRows() ? "none" : undefined;
889
+ _v$23 !== _p$.e && _$setAttribute(_el$57, "data-checkbox", _p$.e = _v$23);
890
+ _v$24 !== _p$.t && _$setAttribute(_el$57, "data-checked", _p$.t = _v$24);
891
+ _v$25 !== _p$.a && _$setAttribute(_el$57, "data-just-checked", _p$.a = _v$25);
892
+ _v$26 !== _p$.o && _$setStyleProperty(_el$57, "grid-column", _p$.o = _v$26);
893
+ _v$27 !== _p$.i && _$setStyleProperty(_el$57, "grid-row", _p$.i = _v$27);
894
+ _v$28 !== _p$.n && _$setStyleProperty(_el$57, "--k2b-calendar-accent", _p$.n = _v$28);
895
+ _v$29 !== _p$.s && _$setStyleProperty(_el$57, "display", _p$.s = _v$29);
896
+ return _p$;
897
+ }, {
898
+ e: undefined,
899
+ t: undefined,
900
+ a: undefined,
901
+ o: undefined,
902
+ i: undefined,
903
+ n: undefined,
904
+ s: undefined
905
+ });
906
+ return _el$57;
907
+ })();
908
+ }
909
+ }), _$createComponent(For, {
910
+ get each() {
911
+ return week.layout.singles;
912
+ },
913
+ children: (singles, column) => {
914
+ const lanes = () => Math.max(0, ...week.layout.bars.filter(bar => bar.startColumn <= column() && bar.endColumn >= column()).map(bar => bar.lane + 1));
915
+ return _$createComponent(For, {
916
+ each: singles,
917
+ children: (span, row) => {
918
+ const event = span.item;
919
+ const checked = () => view.checkedOf(event);
920
+ const id = `a:${event.id}:${week.offset}`;
921
+ return (() => {
922
+ var _el$62 = _$getNextElement(_tmpl$0),
923
+ _el$63 = _el$62.firstChild,
924
+ [_el$64, _co$14] = _$getNextMarker(_el$63.nextSibling),
925
+ _el$65 = _el$64.nextSibling,
926
+ [_el$66, _co$15] = _$getNextMarker(_el$65.nextSibling);
927
+ _$insert(_el$62, _$createComponent(Show, {
928
+ get when() {
929
+ return checked() !== undefined;
930
+ },
931
+ get children() {
932
+ return _$createComponent(TimeCheck, {
933
+ view: view,
934
+ event: event,
935
+ tabIndex: -1
936
+ });
937
+ }
938
+ }), _el$64, _co$14);
939
+ _$insert(_el$62, _$createComponent(EventChip, {
940
+ get event() {
941
+ return view.normalized(event, span.firstKey);
942
+ },
943
+ get owner() {
944
+ return props.owner;
945
+ },
946
+ get href() {
947
+ return eventHref(props.owner, event);
948
+ },
949
+ compact: true,
950
+ timeline: true,
951
+ get checkbox() {
952
+ return checked() !== undefined;
953
+ },
954
+ get onCheck() {
955
+ return view.checkOf(event);
956
+ },
957
+ get tabIndex() {
958
+ return tabOf(id);
959
+ },
960
+ get stop() {
961
+ return {
962
+ id,
963
+ column: week.offset + column(),
964
+ minute: -1 + (lanes() + row()) / 100
965
+ };
966
+ }
967
+ }), _el$66, _co$15);
968
+ _$effect(_p$ => {
969
+ var _v$30 = checked() !== undefined ? "true" : undefined,
970
+ _v$31 = checked() ? "true" : undefined,
971
+ _v$32 = view.justChecked().has(event.id) ? "true" : undefined,
972
+ _v$33 = String(week.offset + column() + 1),
973
+ _v$34 = String(lanes() + row() + 1),
974
+ _v$35 = eventAccent(event),
975
+ _v$36 = lanes() + row() + 1 > allDayRows() ? "none" : undefined;
976
+ _v$30 !== _p$.e && _$setAttribute(_el$62, "data-checkbox", _p$.e = _v$30);
977
+ _v$31 !== _p$.t && _$setAttribute(_el$62, "data-checked", _p$.t = _v$31);
978
+ _v$32 !== _p$.a && _$setAttribute(_el$62, "data-just-checked", _p$.a = _v$32);
979
+ _v$33 !== _p$.o && _$setStyleProperty(_el$62, "grid-column", _p$.o = _v$33);
980
+ _v$34 !== _p$.i && _$setStyleProperty(_el$62, "grid-row", _p$.i = _v$34);
981
+ _v$35 !== _p$.n && _$setStyleProperty(_el$62, "--k2b-calendar-accent", _p$.n = _v$35);
982
+ _v$36 !== _p$.s && _$setStyleProperty(_el$62, "display", _p$.s = _v$36);
983
+ return _p$;
984
+ }, {
985
+ e: undefined,
986
+ t: undefined,
987
+ a: undefined,
988
+ o: undefined,
989
+ i: undefined,
990
+ n: undefined,
991
+ s: undefined
992
+ });
993
+ return _el$62;
994
+ })();
995
+ }
996
+ });
997
+ }
998
+ })]
999
+ }), _el$11, _co$2);
1000
+ _$insert(_el$15, _$createComponent(For, {
1001
+ get each() {
1002
+ return Array.from({
1003
+ length: wake() / 60 + 1
1004
+ }, (_, index) => index * 60);
1005
+ },
1006
+ children: minute => (() => {
1007
+ var _el$67 = _$getNextElement(_tmpl$1);
1008
+ _$insert(_el$67, () => view.clock(minute));
1009
+ _$effect(_p$ => {
1010
+ var _v$37 = nowShown() && isNearNow(view, view.nowKey(), minute) ? "true" : undefined,
1011
+ _v$38 = termsCss(dayYTerms(wake(), nightsOpen(), minute));
1012
+ _v$37 !== _p$.e && _$setAttribute(_el$67, "data-near-now", _p$.e = _v$37);
1013
+ _v$38 !== _p$.t && _$setStyleProperty(_el$67, "top", _p$.t = _v$38);
1014
+ return _p$;
1015
+ }, {
1016
+ e: undefined,
1017
+ t: undefined
1018
+ });
1019
+ return _el$67;
1020
+ })()
1021
+ }), _el$21, _co$4);
1022
+ _$insert(_el$15, _$createComponent(Show, {
1023
+ get when() {
1024
+ return nightsOpen();
1025
+ },
1026
+ get children() {
1027
+ return _$createComponent(For, {
1028
+ get each() {
1029
+ return nightHours(wake());
1030
+ },
1031
+ children: minute => (() => {
1032
+ var _el$68 = _$getNextElement(_tmpl$10);
1033
+ _$insert(_el$68, () => view.clock(minute));
1034
+ _$effect(_$p => _$setStyleProperty(_el$68, "top", termsCss(dayYTerms(wake(), true, minute))));
1035
+ return _el$68;
1036
+ })()
1037
+ });
1038
+ }
1039
+ }), _el$23, _co$5);
1040
+ _el$16.$$click = () => setNightOverride(!nightsOpen());
1041
+ _$insert(_el$15, _$createComponent(Show, {
1042
+ get when() {
1043
+ return nowShown();
1044
+ },
1045
+ get children() {
1046
+ var _el$19 = _$getNextElement(_tmpl$);
1047
+ _$insert(_el$19, () => view.clock(view.nowMinute()));
1048
+ _$effect(_$p => _$setStyleProperty(_el$19, "top", termsCss(dayYTerms(wake(), nightsOpen(), view.nowMinute()))));
1049
+ return _el$19;
1050
+ }
1051
+ }), _el$25, _co$6);
1052
+ _$insert(_el$26, _$createComponent(For, {
1053
+ get each() {
1054
+ return Array.from({
1055
+ length: wake() / 60 + 1
1056
+ }, (_, index) => index * 60);
1057
+ },
1058
+ children: minute => (() => {
1059
+ var _el$69 = _$getNextElement(_tmpl$11);
1060
+ _$effect(_$p => _$setStyleProperty(_el$69, "top", termsCss(dayYTerms(wake(), nightsOpen(), minute))));
1061
+ return _el$69;
1062
+ })()
1063
+ }), _el$30, _co$7);
1064
+ _$insert(_el$26, _$createComponent(Show, {
1065
+ get when() {
1066
+ return nightsOpen();
1067
+ },
1068
+ get fallback() {
1069
+ return (() => {
1070
+ var _el$70 = _$getNextElement(_tmpl$12);
1071
+ _$effect(_$p => _$setStyleProperty(_el$70, "top", `calc(${termsCss(dayYTerms(wake(), false, wake()))} + 3px)`));
1072
+ return _el$70;
1073
+ })();
1074
+ },
1075
+ get children() {
1076
+ return [(() => {
1077
+ var _el$27 = _$getNextElement(_tmpl$2);
1078
+ _$effect(_p$ => {
1079
+ var _v$ = termsCss(dayYTerms(wake(), true, wake())),
1080
+ _v$2 = termsCss([0, (DAY_MINUTES - wake()) / 60, 1, 0]);
1081
+ _v$ !== _p$.e && _$setStyleProperty(_el$27, "top", _p$.e = _v$);
1082
+ _v$2 !== _p$.t && _$setStyleProperty(_el$27, "height", _p$.t = _v$2);
1083
+ return _p$;
1084
+ }, {
1085
+ e: undefined,
1086
+ t: undefined
1087
+ });
1088
+ return _el$27;
1089
+ })(), _$createComponent(For, {
1090
+ get each() {
1091
+ return nightHours(wake());
1092
+ },
1093
+ children: minute => (() => {
1094
+ var _el$71 = _$getNextElement(_tmpl$11);
1095
+ _$effect(_p$ => {
1096
+ var _v$39 = view.clock(minute) === "00:00" ? "true" : undefined,
1097
+ _v$40 = termsCss(dayYTerms(wake(), true, minute));
1098
+ _v$39 !== _p$.e && _$setAttribute(_el$71, "data-midnight", _p$.e = _v$39);
1099
+ _v$40 !== _p$.t && _$setStyleProperty(_el$71, "top", _p$.t = _v$40);
1100
+ return _p$;
1101
+ }, {
1102
+ e: undefined,
1103
+ t: undefined
1104
+ });
1105
+ return _el$71;
1106
+ })()
1107
+ })];
1108
+ }
1109
+ }), _el$32, _co$8);
1110
+ _$insert(_el$26, _$createComponent(Show, {
1111
+ get when() {
1112
+ return nowShown();
1113
+ },
1114
+ get children() {
1115
+ var _el$28 = _$getNextElement(_tmpl$3);
1116
+ _$effect(_$p => _$setStyleProperty(_el$28, "top", termsCss(dayYTerms(wake(), nightsOpen(), view.nowMinute()))));
1117
+ return _el$28;
1118
+ }
1119
+ }), _el$34, _co$9);
1120
+ _$insert(_el$14, _$createComponent(For, {
1121
+ get each() {
1122
+ return keys();
1123
+ },
1124
+ children: key => _$createComponent(WeekColumn, {
1125
+ view: view,
1126
+ dayKey: key,
1127
+ get column() {
1128
+ return indexOf(key);
1129
+ },
1130
+ get expanded() {
1131
+ return nightsOpen();
1132
+ },
1133
+ tabOf: tabOf,
1134
+ lastPointer: () => lastPointer,
1135
+ setLastPointer: value => {
1136
+ lastPointer = value;
1137
+ },
1138
+ scroller: () => scroller
1139
+ })
1140
+ }), _el$36, _co$0);
1141
+ _$setAttribute(_el$37, "id", helpId);
1142
+ _$insert(_el$37, () => view.messages().calendarKeyboardHelp);
1143
+ _$insert(_el$, _$createComponent(TimeQuickCreate, {
1144
+ view: view
1145
+ }), _el$39, _co$1);
1146
+ _$effect(_p$ => {
1147
+ var _v$3 = view.dragging() || undefined,
1148
+ _v$4 = view.messages().calendarWeek,
1149
+ _v$5 = String(keys().length),
1150
+ _v$6 = view.messages().calendarAllDayAndDue,
1151
+ _v$7 = `repeat(${allDayRows()}, var(--k2b-calendar-all-day-row))`,
1152
+ _v$8 = termsCss(dayHeightTerms(wake(), nightsOpen())),
1153
+ _v$9 = nightsOpen() ? "true" : "false",
1154
+ _v$0 = nightsOpen() ? view.messages().calendarFoldNights : view.messages().calendarOpenNights({
1155
+ from: view.clock(wake()).slice(0, 2),
1156
+ to: view.clock(DAY_MINUTES).slice(0, 2)
1157
+ }),
1158
+ _v$1 = nightsOpen() ? view.messages().calendarFoldNights : view.messages().calendarOpenNights({
1159
+ from: view.clock(wake()).slice(0, 2),
1160
+ to: view.clock(DAY_MINUTES).slice(0, 2)
1161
+ }),
1162
+ _v$10 = nightsOpen() ? "true" : undefined,
1163
+ _v$11 = termsCss(dayYTerms(wake(), nightsOpen(), nightsOpen() ? wake() : wake() + 1)),
1164
+ _v$12 = `ti ${nightsOpen() ? "ti-chevron-up" : "ti-chevron-down"}`;
1165
+ _v$3 !== _p$.e && _$setAttribute(_el$, "data-dragging", _p$.e = _v$3);
1166
+ _v$4 !== _p$.t && _$setAttribute(_el$2, "aria-label", _p$.t = _v$4);
1167
+ _v$5 !== _p$.a && _$setStyleProperty(_el$2, "--k2b-calendar-days", _p$.a = _v$5);
1168
+ _v$6 !== _p$.o && _$setAttribute(_el$9, "aria-label", _p$.o = _v$6);
1169
+ _v$7 !== _p$.i && _$setStyleProperty(_el$9, "grid-template-rows", _p$.i = _v$7);
1170
+ _v$8 !== _p$.n && _$setStyleProperty(_el$14, "height", _p$.n = _v$8);
1171
+ _v$9 !== _p$.s && _$setAttribute(_el$16, "aria-expanded", _p$.s = _v$9);
1172
+ _v$0 !== _p$.h && _$setAttribute(_el$16, "aria-label", _p$.h = _v$0);
1173
+ _v$1 !== _p$.r && _$setAttribute(_el$16, "title", _p$.r = _v$1);
1174
+ _v$10 !== _p$.d && _$setAttribute(_el$16, "data-open", _p$.d = _v$10);
1175
+ _v$11 !== _p$.l && _$setStyleProperty(_el$16, "top", _p$.l = _v$11);
1176
+ _v$12 !== _p$.u && _$className(_el$18, _p$.u = _v$12);
1177
+ return _p$;
1178
+ }, {
1179
+ e: undefined,
1180
+ t: undefined,
1181
+ a: undefined,
1182
+ o: undefined,
1183
+ i: undefined,
1184
+ n: undefined,
1185
+ s: undefined,
1186
+ h: undefined,
1187
+ r: undefined,
1188
+ d: undefined,
1189
+ l: undefined,
1190
+ u: undefined
1191
+ });
1192
+ _$runHydrationEvents();
1193
+ return _el$;
1194
+ })();
1195
+ function columnWidthSignal() {
1196
+ // Read through the visible count so a resize recomputes the hints.
1197
+ visibleCount();
1198
+ return columnWidth();
1199
+ }
1200
+ };
1201
+ const WeekColumn = props => {
1202
+ const view = props.view;
1203
+ const model = createMemo(() => view.dayOf(props.dayKey));
1204
+ const wake = () => view.wake();
1205
+ const bands = createMemo(() => dayBands(view, props.dayKey, props.expanded));
1206
+ const gaps = createMemo(() => dayGaps(view, props.dayKey));
1207
+ const markers = () => model().markers.filter(marker => marker.minute < (props.expanded ? DAY_MINUTES : wake()));
1208
+ /** Deadlines whose pills would cover each other share the width; keyed by marker, so rows keep their elements. */
1209
+ const lanes = createMemo(() => new Map(markerLanes(markers(), wake()).map(entry => [entry.item, entry])));
1210
+ const folded = () => props.expanded ? [] : foldedEntries(view, props.dayKey);
1211
+ const isEmptyTarget = target => target instanceof Element && !target.closest("a,button,[data-calendar-event],.k2b-calendar-band,.k2b-calendar-marker,.k2b-calendar-draft,.k2b-calendar-week__fold-cell");
1212
+ const minuteAt = (element, clientY) => {
1213
+ const geometry = readDayGeometry(element, wake(), props.expanded);
1214
+ return Math.max(0, Math.min((props.expanded ? DAY_MINUTES : wake()) - 15, dayMinuteAt(geometry, clientY - element.getBoundingClientRect().top)));
1215
+ };
1216
+ const nowMinute = () => props.dayKey === view.nowKey() ? view.nowMinute() : null;
1217
+ const selected = () => view.selection()?.key === props.dayKey;
1218
+ /** The quarter hour under the mouse on empty time, as a line with its time, to aim a drag at. */
1219
+ const [hover, setHover] = createSignal(null);
1220
+ const timeline = createMemo(() => [...gaps().map(gap => ({
1221
+ at: gap.start,
1222
+ kind: "gap",
1223
+ gap
1224
+ })), ...bands().map(band => ({
1225
+ at: Math.max(0, band.start),
1226
+ kind: "band",
1227
+ band
1228
+ })), ...markers().map(marker => ({
1229
+ at: marker.minute,
1230
+ kind: "marker",
1231
+ marker
1232
+ }))].sort((left, right) => left.at - right.at));
1233
+ return (() => {
1234
+ var _el$72 = _$getNextElement(_tmpl$16),
1235
+ _el$77 = _el$72.firstChild,
1236
+ [_el$78, _co$16] = _$getNextMarker(_el$77.nextSibling),
1237
+ _el$79 = _el$78.nextSibling,
1238
+ [_el$80, _co$17] = _$getNextMarker(_el$79.nextSibling),
1239
+ _el$81 = _el$80.nextSibling,
1240
+ [_el$82, _co$18] = _$getNextMarker(_el$81.nextSibling),
1241
+ _el$83 = _el$82.nextSibling,
1242
+ [_el$84, _co$19] = _$getNextMarker(_el$83.nextSibling),
1243
+ _el$85 = _el$84.nextSibling,
1244
+ [_el$86, _co$20] = _$getNextMarker(_el$85.nextSibling);
1245
+ _el$72.addEventListener("pointerleave", () => setHover(null));
1246
+ _el$72.$$pointermove = event => {
1247
+ if (event.pointerType !== "mouse" || view.dragging() || !isEmptyTarget(event.target)) return setHover(null);
1248
+ setHover(Math.floor(minuteAt(event.currentTarget, event.clientY) / 15) * 15);
1249
+ };
1250
+ _el$72.$$dblclick = event => {
1251
+ if (!isEmptyTarget(event.target) || props.lastPointer() !== "mouse") return;
1252
+ const minute = Math.floor(minuteAt(event.currentTarget, event.clientY) / 30) * 30;
1253
+ view.openQuickCreate(props.dayKey, minute, Math.min(minute + 60, props.expanded ? DAY_MINUTES : wake()), event.currentTarget);
1254
+ };
1255
+ _$addEventListener(_el$72, "click", event => {
1256
+ if (!isEmptyTarget(event.target)) return;
1257
+ const minute = Math.floor(minuteAt(event.currentTarget, event.clientY) / 30) * 30;
1258
+ const end = Math.min(minute + 60, props.expanded ? DAY_MINUTES : wake());
1259
+ if (props.lastPointer() === "mouse") {
1260
+ if (!view.canCreate()) return;
1261
+ view.setTouchDraft(null);
1262
+ view.setSelection({
1263
+ key: props.dayKey,
1264
+ start: minute,
1265
+ end
1266
+ });
1267
+ return;
1268
+ }
1269
+ // A first tap on a column shows its free time; the next one proposes an hour there.
1270
+ if (view.activeKey() !== props.dayKey) {
1271
+ view.setActiveKey(props.dayKey);
1272
+ view.setTouchDraft(null);
1273
+ view.setSelection({
1274
+ key: props.dayKey
1275
+ });
1276
+ return;
1277
+ }
1278
+ if (!view.canCreate()) return;
1279
+ view.setTouchDraft({
1280
+ key: props.dayKey,
1281
+ start: minute,
1282
+ end
1283
+ });
1284
+ view.setSelection({
1285
+ key: props.dayKey,
1286
+ start: minute,
1287
+ end
1288
+ });
1289
+ });
1290
+ _el$72.$$touchstart = () => props.setLastPointer("touch");
1291
+ _el$72.$$pointerdown = event => {
1292
+ props.setLastPointer(event.pointerType);
1293
+ if (event.button !== 0 || !isEmptyTarget(event.target)) return;
1294
+ view.startDraw(event, props.dayKey, props.scroller());
1295
+ };
1296
+ _$use(element => view.registerBody(props.dayKey, element, () => props.expanded), _el$72);
1297
+ _$insert(_el$72, _$createComponent(For, {
1298
+ get each() {
1299
+ return timeline();
1300
+ },
1301
+ children: entry => entry.kind === "gap" ? _$createComponent(TimeGap, {
1302
+ view: view,
1303
+ get gap() {
1304
+ return entry.gap;
1305
+ },
1306
+ get dayKey() {
1307
+ return props.dayKey;
1308
+ },
1309
+ get expanded() {
1310
+ return props.expanded;
1311
+ },
1312
+ get aside() {
1313
+ return gapAside(model(), entry.gap);
1314
+ },
1315
+ get tabIndex() {
1316
+ return props.tabOf(`g:${props.dayKey}:${entry.gap.start}`);
1317
+ },
1318
+ get stop() {
1319
+ return {
1320
+ id: `g:${props.dayKey}:${entry.gap.start}`,
1321
+ column: props.column,
1322
+ minute: entry.gap.start + 0.5
1323
+ };
1324
+ }
1325
+ }) : entry.kind === "band" ? _$createComponent(TimeBand, {
1326
+ view: view,
1327
+ get band() {
1328
+ return entry.band;
1329
+ },
1330
+ get dayKey() {
1331
+ return props.dayKey;
1332
+ },
1333
+ get expanded() {
1334
+ return props.expanded;
1335
+ },
1336
+ hourPx: 48,
1337
+ get tabIndex() {
1338
+ return props.tabOf(`b:${entry.band.item.id}:${props.dayKey}`);
1339
+ },
1340
+ get stop() {
1341
+ return {
1342
+ id: `b:${entry.band.item.id}:${props.dayKey}`,
1343
+ column: props.column,
1344
+ minute: entry.band.start
1345
+ };
1346
+ },
1347
+ get scroller() {
1348
+ return props.scroller;
1349
+ }
1350
+ }) : _$createComponent(TimeMarker, {
1351
+ view: view,
1352
+ get event() {
1353
+ return entry.marker.item;
1354
+ },
1355
+ get minute() {
1356
+ return entry.marker.minute;
1357
+ },
1358
+ get dayKey() {
1359
+ return props.dayKey;
1360
+ },
1361
+ get expanded() {
1362
+ return props.expanded;
1363
+ },
1364
+ get above() {
1365
+ return markerAbove(model(), entry.marker.minute);
1366
+ },
1367
+ get lane() {
1368
+ return lanes().get(entry.marker)?.lane ?? 0;
1369
+ },
1370
+ get lanes() {
1371
+ return lanes().get(entry.marker)?.lanes ?? 1;
1372
+ },
1373
+ showTime: false,
1374
+ get tabIndex() {
1375
+ return props.tabOf(`m:${entry.marker.item.id}`);
1376
+ },
1377
+ get stop() {
1378
+ return {
1379
+ id: `m:${entry.marker.item.id}`,
1380
+ column: props.column,
1381
+ minute: entry.marker.minute
1382
+ };
1383
+ },
1384
+ get scroller() {
1385
+ return props.scroller;
1386
+ }
1387
+ })
1388
+ }), _el$78, _co$16);
1389
+ _$insert(_el$72, _$createComponent(Show, {
1390
+ get when() {
1391
+ return _$memo(() => !!!props.expanded)() && folded().length > 0;
1392
+ },
1393
+ get children() {
1394
+ var _el$73 = _$getNextElement(_tmpl$13),
1395
+ _el$74 = _el$73.firstChild;
1396
+ _$insert(_el$74, _$createComponent(For, {
1397
+ get each() {
1398
+ return folded();
1399
+ },
1400
+ children: (entry, index) => {
1401
+ const checked = () => view.checkedOf(entry.event);
1402
+ return (() => {
1403
+ var _el$87 = _$getNextElement(_tmpl$17),
1404
+ _el$88 = _el$87.firstChild,
1405
+ [_el$89, _co$21] = _$getNextMarker(_el$88.nextSibling),
1406
+ _el$90 = _el$89.nextSibling,
1407
+ [_el$91, _co$22] = _$getNextMarker(_el$90.nextSibling);
1408
+ _$insert(_el$87, _$createComponent(Show, {
1409
+ get when() {
1410
+ return checked() !== undefined;
1411
+ },
1412
+ get children() {
1413
+ return _$createComponent(TimeCheck, {
1414
+ view: view,
1415
+ get event() {
1416
+ return entry.event;
1417
+ },
1418
+ tabIndex: -1
1419
+ });
1420
+ }
1421
+ }), _el$89, _co$21);
1422
+ _$insert(_el$87, _$createComponent(EventChip, {
1423
+ get event() {
1424
+ return view.normalized(entry.event, props.dayKey);
1425
+ },
1426
+ get owner() {
1427
+ return view.props.owner;
1428
+ },
1429
+ get href() {
1430
+ return eventHref(view.props.owner, entry.event);
1431
+ },
1432
+ compact: true,
1433
+ timeline: true,
1434
+ get leadingTime() {
1435
+ return entry.time;
1436
+ },
1437
+ get checkbox() {
1438
+ return checked() !== undefined;
1439
+ },
1440
+ get onCheck() {
1441
+ return view.checkOf(entry.event);
1442
+ },
1443
+ get tabIndex() {
1444
+ return props.tabOf(`f:${entry.event.id}:${props.dayKey}`);
1445
+ },
1446
+ get stop() {
1447
+ return {
1448
+ id: `f:${entry.event.id}:${props.dayKey}`,
1449
+ column: props.column,
1450
+ minute: wake() + index() / 100
1451
+ };
1452
+ }
1453
+ }), _el$91, _co$22);
1454
+ _$effect(_p$ => {
1455
+ var _v$49 = checked() !== undefined ? "true" : undefined,
1456
+ _v$50 = checked() ? "true" : undefined,
1457
+ _v$51 = eventAccent(entry.event);
1458
+ _v$49 !== _p$.e && _$setAttribute(_el$87, "data-checkbox", _p$.e = _v$49);
1459
+ _v$50 !== _p$.t && _$setAttribute(_el$87, "data-checked", _p$.t = _v$50);
1460
+ _v$51 !== _p$.a && _$setStyleProperty(_el$87, "--k2b-calendar-accent", _p$.a = _v$51);
1461
+ return _p$;
1462
+ }, {
1463
+ e: undefined,
1464
+ t: undefined,
1465
+ a: undefined
1466
+ });
1467
+ return _el$87;
1468
+ })();
1469
+ }
1470
+ }));
1471
+ _$effect(_$p => _$setStyleProperty(_el$73, "top", `calc(${termsCss(dayYTerms(wake(), false, wake()))} + 3px)`));
1472
+ return _el$73;
1473
+ }
1474
+ }), _el$80, _co$17);
1475
+ _$insert(_el$72, _$createComponent(TimeOverlays, {
1476
+ view: view,
1477
+ get dayKey() {
1478
+ return props.dayKey;
1479
+ },
1480
+ get expanded() {
1481
+ return props.expanded;
1482
+ }
1483
+ }), _el$82, _co$18);
1484
+ _$insert(_el$72, _$createComponent(Show, {
1485
+ get when() {
1486
+ return hover() !== null;
1487
+ },
1488
+ get children() {
1489
+ var _el$75 = _$getNextElement(_tmpl$14);
1490
+ _$insert(_el$75, () => view.clock(hover()));
1491
+ _$effect(_$p => _$setStyleProperty(_el$75, "top", termsCss(dayYTerms(wake(), props.expanded, hover()))));
1492
+ return _el$75;
1493
+ }
1494
+ }), _el$84, _co$19);
1495
+ _$insert(_el$72, _$createComponent(Show, {
1496
+ get when() {
1497
+ return _$memo(() => !!(nowMinute() !== null && nowMinute() >= 0))() && nowMinute() < (props.expanded ? DAY_MINUTES : wake());
1498
+ },
1499
+ get children() {
1500
+ var _el$76 = _$getNextElement(_tmpl$15);
1501
+ _$effect(_$p => _$setStyleProperty(_el$76, "top", termsCss(dayYTerms(wake(), props.expanded, nowMinute()))));
1502
+ return _el$76;
1503
+ }
1504
+ }), _el$86, _co$20);
1505
+ _$effect(_p$ => {
1506
+ var _v$41 = props.dayKey,
1507
+ _v$42 = props.expanded ? "true" : "false",
1508
+ _v$43 = props.dayKey === view.calendarToday() ? "true" : undefined,
1509
+ _v$44 = selected() ? "true" : undefined,
1510
+ _v$45 = view.activeKey() === props.dayKey ? "true" : undefined,
1511
+ _v$46 = longDay(view, props.dayKey),
1512
+ _v$47 = String(props.column + 2),
1513
+ _v$48 = termsCss(dayHeightTerms(wake(), props.expanded));
1514
+ _v$41 !== _p$.e && _$setAttribute(_el$72, "data-calendar-body", _p$.e = _v$41);
1515
+ _v$42 !== _p$.t && _$setAttribute(_el$72, "data-expanded", _p$.t = _v$42);
1516
+ _v$43 !== _p$.a && _$setAttribute(_el$72, "data-today", _p$.a = _v$43);
1517
+ _v$44 !== _p$.o && _$setAttribute(_el$72, "data-selected", _p$.o = _v$44);
1518
+ _v$45 !== _p$.i && _$setAttribute(_el$72, "data-active", _p$.i = _v$45);
1519
+ _v$46 !== _p$.n && _$setAttribute(_el$72, "aria-label", _p$.n = _v$46);
1520
+ _v$47 !== _p$.s && _$setStyleProperty(_el$72, "grid-column", _p$.s = _v$47);
1521
+ _v$48 !== _p$.h && _$setStyleProperty(_el$72, "height", _p$.h = _v$48);
1522
+ return _p$;
1523
+ }, {
1524
+ e: undefined,
1525
+ t: undefined,
1526
+ a: undefined,
1527
+ o: undefined,
1528
+ i: undefined,
1529
+ n: undefined,
1530
+ s: undefined,
1531
+ h: undefined
1532
+ });
1533
+ _$runHydrationEvents();
1534
+ return _el$72;
1535
+ })();
1536
+ };
1537
+
1538
+ /** ISO week number of a day key. */
1539
+ const isoWeek = key => {
1540
+ const date = new Date(`${key}T00:00:00Z`);
1541
+ const day = date.getUTCDay() || 7;
1542
+ date.setUTCDate(date.getUTCDate() + 4 - day);
1543
+ const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
1544
+ return Math.ceil(((date.getTime() - yearStart.getTime()) / 86_400_000 + 1) / 7);
1545
+ };
1546
+
1547
+ /** The day at a torn end of a bar, with its month when it lies in another month than the shown week. */
1548
+ const hintDate = (view, target, shown) => ({
1549
+ day: Number(target.slice(8, 10)),
1550
+ month: target.slice(0, 7) === shown.slice(0, 7) ? undefined : view.parseKey(target).toLocaleDateString(view.dateConfig().locale ?? "en", {
1551
+ month: "short",
1552
+ timeZone: view.dateConfig().timeZone
1553
+ }).replace(/\.$/, "")
1554
+ });
1555
+
1556
+ /** A long entry's accessible name names the days it spans. */
1557
+ const spanLabel = (view, span) => {
1558
+ if (span.firstKey === span.lastKey) return undefined;
1559
+ const format = key => view.parseKey(key).toLocaleDateString(view.dateConfig().locale ?? "en", {
1560
+ month: "long",
1561
+ day: "numeric",
1562
+ timeZone: view.dateConfig().timeZone
1563
+ });
1564
+ return view.messages().calendarEventTime({
1565
+ title: span.item.title,
1566
+ start: format(span.firstKey),
1567
+ end: format(span.lastKey)
1568
+ });
1569
+ };
1570
+ _$delegateEvents(["keydown", "focusin", "touchstart", "touchend", "pointerdown", "dblclick", "click", "pointermove"]);
1571
+ //# sourceMappingURL=CalendarWeekView.js.map