@nomideusz/svelte-calendar 0.20.0 → 0.21.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 +3 -1
- package/dist/adapters/recurring.js +9 -9
- package/dist/core/locale.js +4 -4
- package/dist/core/time.js +4 -5
- package/dist/engine/event-store.svelte.js +2 -2
- package/dist/engine/view-state.svelte.js +3 -3
- package/dist/headless/create-agenda.svelte.js +6 -6
- package/dist/headless/create-calendar.svelte.js +4 -4
- package/dist/headless/create-range-agenda.svelte.js +6 -6
- package/dist/views/agenda/AgendaDay.svelte +3 -3
- package/dist/views/agenda/AgendaWeek.svelte +4 -4
- package/dist/views/mobile/MobileDay.svelte +2 -2
- package/dist/views/mobile/MobileWeek.svelte +3 -3
- package/dist/views/month/MonthGrid.svelte +5 -5
- package/dist/views/planner/PlannerScroll.svelte +285 -140
- package/dist/views/planner/PlannerWeek.svelte +2 -2
- package/package.json +1 -1
- package/widget/widget.js +425 -240
package/README.md
CHANGED
|
@@ -34,7 +34,9 @@ That's it — 6 views (Day/Week × Planner, Agenda, Mobile), auto-coloring, drag
|
|
|
34
34
|
## Views
|
|
35
35
|
|
|
36
36
|
Switch between **Planner** (time grid), **Scroll** (weeks stacked in one
|
|
37
|
-
vertical scroller
|
|
37
|
+
vertical scroller, Hey-Calendar style — each class at the height of its
|
|
38
|
+
start time, month names down the side; drag to move, drop onto a day,
|
|
39
|
+
scrolls under a drag),
|
|
38
40
|
**Agenda** (list) and the **Month** grid:
|
|
39
41
|
|
|
40
42
|
```svelte
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { startOfWeek, DAY_MS } from '../core/time.js';
|
|
1
|
+
import { startOfWeek, addDaysMs, diffDays, DAY_MS } from '../core/time.js';
|
|
2
2
|
import { VIVID_PALETTE } from '../core/palette.js';
|
|
3
3
|
// ── Helpers ─────────────────────────────────────────────
|
|
4
4
|
/** Parse "HH:MM" into [hours, minutes] */
|
|
@@ -100,14 +100,14 @@ function computeUntilFromCount(rec, startDateObj, mondayStart) {
|
|
|
100
100
|
const maxCycles = Math.ceil(count / days.length) + 2;
|
|
101
101
|
for (let c = 0; c < maxCycles; c++) {
|
|
102
102
|
for (const day of days) {
|
|
103
|
-
const dayMs = weekMs
|
|
103
|
+
const dayMs = addDaysMs(weekMs, isoWeekdayToOffset(day));
|
|
104
104
|
if (dayMs >= startMs) {
|
|
105
105
|
remaining--;
|
|
106
106
|
if (remaining === 0)
|
|
107
107
|
return new Date(dayMs);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
-
weekMs
|
|
110
|
+
weekMs = addDaysMs(weekMs, interval * 7);
|
|
111
111
|
}
|
|
112
112
|
return undefined;
|
|
113
113
|
}
|
|
@@ -165,16 +165,16 @@ function projectWeekly(rec, range, startDate, effectiveUntil, mondayStart, out)
|
|
|
165
165
|
weekMs = anchorWeekMs;
|
|
166
166
|
}
|
|
167
167
|
else {
|
|
168
|
-
const weeksBetween = Math.floor((rangeStartMs
|
|
168
|
+
const weeksBetween = Math.floor(diffDays(rangeStartMs, anchorWeekMs) / 7);
|
|
169
169
|
const skip = Math.floor(weeksBetween / interval);
|
|
170
|
-
weekMs = anchorWeekMs
|
|
171
|
-
if (weekMs
|
|
172
|
-
weekMs
|
|
170
|
+
weekMs = addDaysMs(anchorWeekMs, skip * interval * 7);
|
|
171
|
+
if (addDaysMs(weekMs, 7) <= rangeStartMs) {
|
|
172
|
+
weekMs = addDaysMs(weekMs, interval * 7);
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
while (weekMs < rangeEndMs) {
|
|
176
176
|
for (const day of days) {
|
|
177
|
-
const dayMs = weekMs
|
|
177
|
+
const dayMs = addDaysMs(weekMs, isoWeekdayToOffset(day));
|
|
178
178
|
if (startDateMs != null && dayMs < startDateMs)
|
|
179
179
|
continue;
|
|
180
180
|
if (dayMs >= rangeEndMs)
|
|
@@ -187,7 +187,7 @@ function projectWeekly(rec, range, startDate, effectiveUntil, mondayStart, out)
|
|
|
187
187
|
out.push(ev);
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
|
-
weekMs
|
|
190
|
+
weekMs = addDaysMs(weekMs, interval * 7);
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
function projectMonthly(rec, range, startDate, effectiveUntil, out) {
|
package/dist/core/locale.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For date-fns locale integration later, this module can import from
|
|
8
8
|
* `date-fns/locale/*` and pass to `format()`.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { addDaysMs } from './time.js';
|
|
11
11
|
/** English defaults — used unless overridden via `setLabels()`. */
|
|
12
12
|
export const defaultLabels = {
|
|
13
13
|
today: 'Today',
|
|
@@ -155,9 +155,9 @@ export function fmtDay(ms, todayMs, opts, locale) {
|
|
|
155
155
|
const L = _labels;
|
|
156
156
|
if (ms === todayMs)
|
|
157
157
|
return opts?.short ? L.today : `${L.today} · ${short}`;
|
|
158
|
-
if (ms === todayMs -
|
|
158
|
+
if (ms === addDaysMs(todayMs, -1))
|
|
159
159
|
return opts?.short ? L.yesterday : `${L.yesterday} · ${short}`;
|
|
160
|
-
if (ms === todayMs
|
|
160
|
+
if (ms === addDaysMs(todayMs, 1))
|
|
161
161
|
return opts?.short ? L.tomorrow : `${L.tomorrow} · ${short}`;
|
|
162
162
|
if (opts?.short) {
|
|
163
163
|
return new Date(ms).toLocaleDateString(loc, { weekday: 'short', day: 'numeric' });
|
|
@@ -170,7 +170,7 @@ export function fmtDay(ms, todayMs, opts, locale) {
|
|
|
170
170
|
export function fmtWeekRange(weekStartMs, locale, weekEndMs) {
|
|
171
171
|
const loc = locale ?? defaultLocale;
|
|
172
172
|
const s = new Date(weekStartMs);
|
|
173
|
-
const e = new Date(weekEndMs ?? weekStartMs
|
|
173
|
+
const e = new Date(weekEndMs ?? addDaysMs(weekStartMs, 6));
|
|
174
174
|
const sm = s.toLocaleDateString(loc, { month: 'short' });
|
|
175
175
|
const em = e.toLocaleDateString(loc, { month: 'short' });
|
|
176
176
|
const sy = s.getFullYear();
|
package/dist/core/time.js
CHANGED
|
@@ -74,8 +74,7 @@ export function isMultiDay(ev) {
|
|
|
74
74
|
export function isAllDay(ev) {
|
|
75
75
|
if (ev.allDay)
|
|
76
76
|
return true;
|
|
77
|
-
|
|
78
|
-
if (duration < DAY_MS)
|
|
77
|
+
if (ev.end.getTime() < addDaysMs(ev.start.getTime(), 1))
|
|
79
78
|
return false;
|
|
80
79
|
const s = ev.start;
|
|
81
80
|
return s.getHours() === 0 && s.getMinutes() === 0 && s.getSeconds() === 0;
|
|
@@ -86,7 +85,7 @@ export function isAllDay(ev) {
|
|
|
86
85
|
*/
|
|
87
86
|
export function segmentForDay(ev, dayMs) {
|
|
88
87
|
const dayStart = sod(dayMs);
|
|
89
|
-
const dayEnd = dayStart
|
|
88
|
+
const dayEnd = addDaysMs(dayStart, 1);
|
|
90
89
|
const evStart = ev.start.getTime();
|
|
91
90
|
const evEnd = ev.end.getTime();
|
|
92
91
|
// No overlap
|
|
@@ -95,8 +94,8 @@ export function segmentForDay(ev, dayMs) {
|
|
|
95
94
|
const firstDayMs = sod(evStart);
|
|
96
95
|
// For end time: if event ends exactly at midnight, last day is the day before
|
|
97
96
|
const lastDayMs = sod(evEnd - 1);
|
|
98
|
-
const totalDays =
|
|
99
|
-
const dayIndex =
|
|
97
|
+
const totalDays = diffDays(lastDayMs, firstDayMs) + 1;
|
|
98
|
+
const dayIndex = diffDays(dayStart, firstDayMs) + 1;
|
|
100
99
|
return {
|
|
101
100
|
ev,
|
|
102
101
|
start: new Date(Math.max(evStart, dayStart)),
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { SvelteMap } from 'svelte/reactivity';
|
|
19
19
|
import { untrack } from 'svelte';
|
|
20
|
-
import { sod,
|
|
20
|
+
import { sod, addDaysMs } from '../core/time.js';
|
|
21
21
|
/**
|
|
22
22
|
* Create a reactive event store backed by a CalendarAdapter.
|
|
23
23
|
*
|
|
@@ -103,7 +103,7 @@ export function createEventStore(adapter) {
|
|
|
103
103
|
},
|
|
104
104
|
forDay(date) {
|
|
105
105
|
const dayStart = new Date(sod(date.getTime()));
|
|
106
|
-
const dayEnd = new Date(dayStart.getTime()
|
|
106
|
+
const dayEnd = new Date(addDaysMs(dayStart.getTime(), 1));
|
|
107
107
|
return eventArray.filter((ev) => overlaps(ev, dayStart, dayEnd));
|
|
108
108
|
},
|
|
109
109
|
byId(id) {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* vs.prev() — go back one period
|
|
12
12
|
* vs.goToday() — jump to today
|
|
13
13
|
*/
|
|
14
|
-
import { startOfWeek as calcStartOfWeek, addDaysMs
|
|
14
|
+
import { startOfWeek as calcStartOfWeek, addDaysMs } from '../core/time.js';
|
|
15
15
|
function inferMode(view) {
|
|
16
16
|
if (view.startsWith('day'))
|
|
17
17
|
return 'day';
|
|
@@ -23,7 +23,7 @@ function computeRange(focus, mode, mondayStart, dayCount = 7) {
|
|
|
23
23
|
if (mode === 'day') {
|
|
24
24
|
const start = new Date(focus);
|
|
25
25
|
start.setHours(0, 0, 0, 0);
|
|
26
|
-
const end = new Date(start.getTime()
|
|
26
|
+
const end = new Date(addDaysMs(start.getTime(), 1));
|
|
27
27
|
return { start, end };
|
|
28
28
|
}
|
|
29
29
|
if (mode === 'month') {
|
|
@@ -48,7 +48,7 @@ function computeRange(focus, mode, mondayStart, dayCount = 7) {
|
|
|
48
48
|
start.setHours(0, 0, 0, 0);
|
|
49
49
|
return {
|
|
50
50
|
start,
|
|
51
|
-
end: new Date(start.getTime()
|
|
51
|
+
end: new Date(addDaysMs(start.getTime(), dayCount)),
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
export function createViewState(options = {}) {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
import { untrack } from 'svelte';
|
|
34
34
|
import { createEventStore } from '../engine/event-store.svelte.js';
|
|
35
35
|
import { createClock } from '../core/clock.svelte.js';
|
|
36
|
-
import { sod,
|
|
36
|
+
import { sod, addDaysMs, isAllDay, isMultiDay } from '../core/time.js';
|
|
37
37
|
import { fmtTime as _fmtTime, fmtDuration } from '../core/locale.js';
|
|
38
38
|
import { timeUntilMs, progress as _progress, groupIntoSlots } from '../views/shared/format.js';
|
|
39
39
|
// ─── Implementation ─────────────────────────────────────
|
|
@@ -49,17 +49,17 @@ export function createAgenda(options) {
|
|
|
49
49
|
// ── Load events for focus date range ──
|
|
50
50
|
$effect(() => {
|
|
51
51
|
const start = new Date(focusDayMs);
|
|
52
|
-
const end = new Date(focusDayMs
|
|
52
|
+
const end = new Date(addDaysMs(focusDayMs, lookahead));
|
|
53
53
|
store.load({ start, end });
|
|
54
54
|
});
|
|
55
55
|
// Eager initial load
|
|
56
56
|
untrack(() => {
|
|
57
57
|
const start = new Date(focusDayMs);
|
|
58
|
-
const end = new Date(focusDayMs
|
|
58
|
+
const end = new Date(addDaysMs(focusDayMs, lookahead));
|
|
59
59
|
store.load({ start, end });
|
|
60
60
|
});
|
|
61
61
|
// ── Day derivations ──
|
|
62
|
-
const dayEnd = $derived(focusDayMs
|
|
62
|
+
const dayEnd = $derived(addDaysMs(focusDayMs, 1));
|
|
63
63
|
const isToday = $derived(focusDayMs === clock.today);
|
|
64
64
|
const isPast = $derived(focusDayMs < clock.today);
|
|
65
65
|
const isFuture = $derived(focusDayMs > clock.today);
|
|
@@ -93,8 +93,8 @@ export function createAgenda(options) {
|
|
|
93
93
|
return { past, current, upcoming, upcomingSlots: groupIntoSlots(upcoming) };
|
|
94
94
|
});
|
|
95
95
|
// ── Navigation ──
|
|
96
|
-
function prev() { focusDayMs = focusDayMs -
|
|
97
|
-
function next() { focusDayMs = focusDayMs
|
|
96
|
+
function prev() { focusDayMs = addDaysMs(focusDayMs, -1); }
|
|
97
|
+
function next() { focusDayMs = addDaysMs(focusDayMs, 1); }
|
|
98
98
|
function goToday() { focusDayMs = clock.today; }
|
|
99
99
|
function setDate(date) { focusDayMs = sod(date.getTime()); }
|
|
100
100
|
// ── Format helpers ──
|
|
@@ -46,7 +46,7 @@ import { toZonedTime, fromZonedTime, wrapAdapterWithTimezone } from '../core/tim
|
|
|
46
46
|
import { createSelection } from '../engine/selection.svelte.js';
|
|
47
47
|
import { createDragState } from '../engine/drag.svelte.js';
|
|
48
48
|
import { createClock } from '../core/clock.svelte.js';
|
|
49
|
-
import { sod,
|
|
49
|
+
import { sod, addDaysMs, HOUR_MS, startOfWeek as sowFn, isAllDay, isMultiDay, segmentForDay, } from '../core/time.js';
|
|
50
50
|
import { monthLong, weekdayLong, weekdayShort } from '../core/locale.js';
|
|
51
51
|
export function createCalendar(options) {
|
|
52
52
|
const { adapter, mondayStart: initialMondayStart = true, initialDate: rawInitialDate, locale, visibleHours, snapInterval = 15, equalDays = false, hideDays, blockedSlots, disabledDates, days: initialDayCount = 7, readOnly = false, minDuration, maxDuration, oneventclick, oneventcreate, oneventmove, } = options;
|
|
@@ -85,14 +85,14 @@ export function createCalendar(options) {
|
|
|
85
85
|
const events = store.events;
|
|
86
86
|
const todayMs = clock.today;
|
|
87
87
|
const result = [];
|
|
88
|
-
for (let ms = startMs; ms < endMs; ms
|
|
88
|
+
for (let ms = startMs; ms < endMs; ms = addDaysMs(ms, 1)) {
|
|
89
89
|
const date = new Date(ms);
|
|
90
90
|
const jsDay = date.getDay();
|
|
91
91
|
const isoDay = jsDay === 0 ? 7 : jsDay;
|
|
92
92
|
// Skip hidden days
|
|
93
93
|
if (hideDays?.includes(isoDay))
|
|
94
94
|
continue;
|
|
95
|
-
const dayEnd = ms
|
|
95
|
+
const dayEnd = addDaysMs(ms, 1);
|
|
96
96
|
const dayEventsAll = events
|
|
97
97
|
.filter((ev) => ev.start.getTime() < dayEnd && ev.end.getTime() > ms)
|
|
98
98
|
.sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
@@ -134,7 +134,7 @@ export function createCalendar(options) {
|
|
|
134
134
|
if (chunk.length === 0)
|
|
135
135
|
continue;
|
|
136
136
|
const periodStart = chunk[0].ms;
|
|
137
|
-
const periodEnd = periodStart
|
|
137
|
+
const periodEnd = addDaysMs(periodStart, dayCount);
|
|
138
138
|
result.push({
|
|
139
139
|
periodStart,
|
|
140
140
|
isCurrent: todayMs >= periodStart && todayMs < periodEnd,
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import { untrack } from 'svelte';
|
|
34
34
|
import { createEventStore } from '../engine/event-store.svelte.js';
|
|
35
|
-
import { sod,
|
|
35
|
+
import { sod, addDaysMs } from '../core/time.js';
|
|
36
36
|
import { fmtTime as _fmtTime, fmtDuration } from '../core/locale.js';
|
|
37
37
|
// ─── Implementation ─────────────────────────────────────
|
|
38
38
|
export function createRangeAgenda(options) {
|
|
@@ -43,7 +43,7 @@ export function createRangeAgenda(options) {
|
|
|
43
43
|
const store = $derived(createEventStore(resolveAdapter()));
|
|
44
44
|
// ── Window start (reactive, writable) ──
|
|
45
45
|
let startMs = $state(sod(initialDate?.getTime() ?? Date.now()));
|
|
46
|
-
const endMs = $derived(startMs
|
|
46
|
+
const endMs = $derived(addDaysMs(startMs, dayCount));
|
|
47
47
|
// ── Load events for the window (re-runs on paging / adapter swap) ──
|
|
48
48
|
$effect(() => {
|
|
49
49
|
store.load({ start: new Date(startMs), end: new Date(endMs) });
|
|
@@ -57,8 +57,8 @@ export function createRangeAgenda(options) {
|
|
|
57
57
|
const todayMs = sod(Date.now());
|
|
58
58
|
const events = store.events;
|
|
59
59
|
return Array.from({ length: dayCount }, (_, i) => {
|
|
60
|
-
const ms = startMs
|
|
61
|
-
const dayEnd = ms
|
|
60
|
+
const ms = addDaysMs(startMs, i);
|
|
61
|
+
const dayEnd = addDaysMs(ms, 1);
|
|
62
62
|
const date = new Date(ms);
|
|
63
63
|
// JS getDay(): 0=Sun … 6=Sat → ISO 1=Mon … 7=Sun
|
|
64
64
|
const weekday = ((date.getDay() + 6) % 7) + 1;
|
|
@@ -92,10 +92,10 @@ export function createRangeAgenda(options) {
|
|
|
92
92
|
return store.error;
|
|
93
93
|
},
|
|
94
94
|
prev() {
|
|
95
|
-
startMs
|
|
95
|
+
startMs = addDaysMs(startMs, -dayCount);
|
|
96
96
|
},
|
|
97
97
|
next() {
|
|
98
|
-
startMs
|
|
98
|
+
startMs = addDaysMs(startMs, dayCount);
|
|
99
99
|
},
|
|
100
100
|
goToday() {
|
|
101
101
|
startMs = sod(Date.now());
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Clean numbered schedule list.
|
|
13
13
|
*/
|
|
14
14
|
import { createClock } from "../../core/clock.svelte.js";
|
|
15
|
-
import { sod,
|
|
15
|
+
import { sod, addDaysMs, dayNum, isAllDay, isMultiDay } from "../../core/time.js";
|
|
16
16
|
import { weekdayLong, monthLong } from "../../core/locale.js";
|
|
17
17
|
import { useCalendarContext } from "../shared/context.svelte.js";
|
|
18
18
|
import EventContent from "../shared/EventContent.svelte";
|
|
@@ -69,9 +69,9 @@ function handleClick(ev) {
|
|
|
69
69
|
}
|
|
70
70
|
// ── Day derivations ─────────────────────────────────
|
|
71
71
|
const dayMs = $derived(focusDate ? sod(focusDate.getTime()) : clock.today);
|
|
72
|
-
const dayEnd = $derived(dayMs
|
|
72
|
+
const dayEnd = $derived(addDaysMs(dayMs, 1));
|
|
73
73
|
const isToday = $derived(dayMs === clock.today);
|
|
74
|
-
const isTomorrow = $derived(dayMs === clock.today
|
|
74
|
+
const isTomorrow = $derived(dayMs === addDaysMs(clock.today, 1));
|
|
75
75
|
const isPastDay = $derived(equalDays ? false : dayMs < clock.today);
|
|
76
76
|
/** All events for this day, sorted chronologically */
|
|
77
77
|
const dayEvents = $derived.by(() => {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Answers: "What's coming up and when do I need to be ready?"
|
|
10
10
|
*/
|
|
11
11
|
import { createClock } from "../../core/clock.svelte.js";
|
|
12
|
-
import { sod,
|
|
12
|
+
import { sod, addDaysMs, startOfWeek, dayNum, isAllDay, isMultiDay, segmentForDay } from "../../core/time.js";
|
|
13
13
|
import { weekdayLong, monthLong } from "../../core/locale.js";
|
|
14
14
|
import { useCalendarContext } from "../shared/context.svelte.js";
|
|
15
15
|
import EventContent from "../shared/EventContent.svelte";
|
|
@@ -115,11 +115,11 @@ const customDays = $derived(viewState?.dayCount ?? 7);
|
|
|
115
115
|
const weekDays = $derived.by(() => {
|
|
116
116
|
const now = clock.tick;
|
|
117
117
|
const todayMs = clock.today;
|
|
118
|
-
const tomorrowMs = todayMs
|
|
118
|
+
const tomorrowMs = addDaysMs(todayMs, 1);
|
|
119
119
|
const out = [];
|
|
120
120
|
for (let i = 0; i < customDays; i++) {
|
|
121
|
-
const ms = weekStartMs
|
|
122
|
-
const dEnd = ms
|
|
121
|
+
const ms = addDaysMs(weekStartMs, i);
|
|
122
|
+
const dEnd = addDaysMs(ms, 1);
|
|
123
123
|
const dayEvts = events.filter((ev) => ev.start.getTime() < dEnd && ev.end.getTime() > ms).sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
124
124
|
const allDayEvts = dayEvts.filter((ev) => isAllDay(ev) || isMultiDay(ev));
|
|
125
125
|
const timedEvts = dayEvts.filter((ev) => !isAllDay(ev) && !isMultiDay(ev));
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { useCalendarContext } from "../shared/context.svelte.js";
|
|
10
10
|
import EventContent from "../shared/EventContent.svelte";
|
|
11
11
|
import { createClock } from "../../core/clock.svelte.js";
|
|
12
|
-
import { DAY_MS, HOUR_MS, sod, isAllDay, isMultiDay, segmentForDay } from "../../core/time.js";
|
|
12
|
+
import { DAY_MS, HOUR_MS, sod, addDaysMs, isAllDay, isMultiDay, segmentForDay } from "../../core/time.js";
|
|
13
13
|
import { fmtH, fmtTime } from "../../core/locale.js";
|
|
14
14
|
import { createSwipe } from "./swipe.js";
|
|
15
15
|
let { height = null, events = [], style = "", locale, focusDate, oneventclick, oneventcreate, selectedEventId = null, readOnly = false, visibleHours } = $props();
|
|
@@ -36,7 +36,7 @@ const hourCount = $derived(Math.max(1, endHour - startHour));
|
|
|
36
36
|
const gridHeight = $derived(hourCount * HOUR_HEIGHT);
|
|
37
37
|
// ── Day state ──────────────────────────────────────
|
|
38
38
|
const dayMs = $derived(focusDate ? sod(focusDate.getTime()) : clock.today);
|
|
39
|
-
const dayEnd = $derived(dayMs
|
|
39
|
+
const dayEnd = $derived(addDaysMs(dayMs, 1));
|
|
40
40
|
const isToday = $derived(dayMs === clock.today);
|
|
41
41
|
const isDisabled = $derived(disabledSet.has(dayMs));
|
|
42
42
|
// ── Load range ─────────────────────────────────────
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<script lang="ts">import { useCalendarContext } from "../shared/context.svelte.js";
|
|
9
9
|
import EventContent from "../shared/EventContent.svelte";
|
|
10
10
|
import { createClock } from "../../core/clock.svelte.js";
|
|
11
|
-
import { DAY_MS, sod, isAllDay, isMultiDay } from "../../core/time.js";
|
|
11
|
+
import { DAY_MS, sod, addDaysMs, isAllDay, isMultiDay } from "../../core/time.js";
|
|
12
12
|
import { startOfWeek as sowFn } from "../../core/time.js";
|
|
13
13
|
import { fmtTime as _fmtTime, weekdayShort } from "../../core/locale.js";
|
|
14
14
|
import { createSwipe } from "./swipe.js";
|
|
@@ -47,7 +47,7 @@ const dayCells = $derived.by(() => {
|
|
|
47
47
|
const result = [];
|
|
48
48
|
const hideSet = new Set(hideDays ?? []);
|
|
49
49
|
for (let i = 0; i < customDays; i++) {
|
|
50
|
-
const ms = weekStart
|
|
50
|
+
const ms = addDaysMs(weekStart, i);
|
|
51
51
|
const d = new Date(ms);
|
|
52
52
|
const jsDay = d.getDay();
|
|
53
53
|
const isoDay = jsDay === 0 ? 7 : jsDay;
|
|
@@ -56,7 +56,7 @@ const dayCells = $derived.by(() => {
|
|
|
56
56
|
const isPast = equalDays ? false : ms < todayMs;
|
|
57
57
|
const isWeekend = jsDay === 0 || jsDay === 6;
|
|
58
58
|
const isDisabled = disabledSet.has(ms);
|
|
59
|
-
const dayEnd = ms
|
|
59
|
+
const dayEnd = addDaysMs(ms, 1);
|
|
60
60
|
const dayEvents = events.filter((ev) => ev.start.getTime() < dayEnd && ev.end.getTime() > ms).sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
61
61
|
const allDayCount = dayEvents.filter((ev) => isAllDay(ev) || isMultiDay(ev)).length;
|
|
62
62
|
result.push({
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
-->
|
|
9
9
|
<script lang="ts">import { useCalendarContext } from "../shared/context.svelte.js";
|
|
10
10
|
import { createClock } from "../../core/clock.svelte.js";
|
|
11
|
-
import { DAY_MS, sod, isAllDay } from "../../core/time.js";
|
|
11
|
+
import { DAY_MS, sod, addDaysMs, isAllDay } from "../../core/time.js";
|
|
12
12
|
import { fmtTime, weekdayShort } from "../../core/locale.js";
|
|
13
13
|
let { events = [], style = "", height = null, locale, focusDate, oneventclick, selectedEventId = null } = $props();
|
|
14
14
|
const ctx = useCalendarContext();
|
|
@@ -54,7 +54,7 @@ const rovingMs = $derived.by(() => {
|
|
|
54
54
|
});
|
|
55
55
|
function moveFocus(fromMs, deltaDays) {
|
|
56
56
|
if (!range) return;
|
|
57
|
-
const target = fromMs
|
|
57
|
+
const target = addDaysMs(fromMs, deltaDays);
|
|
58
58
|
if (target < sod(range.start.getTime()) || target >= range.end.getTime()) return;
|
|
59
59
|
focusMs = target;
|
|
60
60
|
const el = bodyEl?.querySelector(`[data-ms="${target}"]`);
|
|
@@ -108,7 +108,7 @@ function cellLabel(cell) {
|
|
|
108
108
|
}
|
|
109
109
|
function eventsForDay(ms) {
|
|
110
110
|
const dayStart = ms;
|
|
111
|
-
const dayEnd = ms
|
|
111
|
+
const dayEnd = addDaysMs(ms, 1);
|
|
112
112
|
return events.filter((e) => e.start.getTime() < dayEnd && e.end.getTime() > dayStart).sort((a, b) => {
|
|
113
113
|
const aAll = isAllDay(a) ? 0 : 1;
|
|
114
114
|
const bAll = isAllDay(b) ? 0 : 1;
|
|
@@ -118,10 +118,10 @@ function eventsForDay(ms) {
|
|
|
118
118
|
const weeks = $derived.by(() => {
|
|
119
119
|
if (!range) return [];
|
|
120
120
|
const rows = [];
|
|
121
|
-
for (let ms = sod(range.start.getTime()); ms < range.end.getTime(); ms
|
|
121
|
+
for (let ms = sod(range.start.getTime()); ms < range.end.getTime(); ms = addDaysMs(ms, 7)) {
|
|
122
122
|
const row = [];
|
|
123
123
|
for (let i = 0; i < 7; i++) {
|
|
124
|
-
const cellMs = ms
|
|
124
|
+
const cellMs = addDaysMs(ms, i);
|
|
125
125
|
const date = new Date(cellMs);
|
|
126
126
|
const jsDay = date.getDay();
|
|
127
127
|
const dayEvents = eventsForDay(cellMs);
|