@nomideusz/svelte-calendar 0.7.5 → 0.8.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 +19 -4
- package/dist/calendar/Calendar.svelte +364 -497
- package/dist/calendar/Calendar.svelte.d.ts +6 -2
- package/dist/core/clock.svelte.js +12 -5
- package/dist/core/locale.d.ts +4 -0
- package/dist/core/locale.js +4 -0
- package/dist/engine/view-state.svelte.d.ts +2 -2
- package/dist/engine/view-state.svelte.js +20 -0
- package/dist/headless/create-calendar.svelte.js +18 -2
- package/dist/headless/types.d.ts +6 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/primitives/DayHeader.svelte +9 -25
- package/dist/primitives/EmptySlot.svelte +15 -31
- package/dist/primitives/EventBlock.svelte +33 -61
- package/dist/primitives/NowIndicator.svelte +16 -42
- package/dist/primitives/TimeGutter.svelte +9 -23
- package/dist/views/agenda/Agenda.svelte +3 -10
- package/dist/views/agenda/AgendaDay.svelte +195 -167
- package/dist/views/agenda/AgendaWeek.svelte +141 -195
- package/dist/views/mobile/Mobile.svelte +3 -10
- package/dist/views/mobile/MobileDay.svelte +422 -266
- package/dist/views/mobile/MobileWeek.svelte +131 -186
- package/dist/views/month/MonthGrid.svelte +334 -0
- package/dist/views/month/MonthGrid.svelte.d.ts +15 -0
- package/dist/views/planner/Planner.svelte +3 -10
- package/dist/views/planner/PlannerDay.svelte +636 -546
- package/dist/views/planner/PlannerWeek.svelte +299 -412
- package/dist/views/shared/EventContent.svelte +16 -0
- package/dist/views/shared/EventContent.svelte.d.ts +9 -0
- package/dist/views/shared/context.svelte.d.ts +1 -0
- package/dist/views/shared/context.svelte.js +1 -0
- package/dist/widget/CalendarWidget.svelte +79 -116
- package/package.json +3 -2
- package/widget/svelte-calendar.css +321 -10
- package/widget/widget.js +1944 -1031
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
EventContent — renders the host's `event` snippet when provided, else the
|
|
3
|
+
view's default markup (passed as children). Views keep their interactive
|
|
4
|
+
shell (click/keyboard/selection/drag); only the content is swappable.
|
|
5
|
+
-->
|
|
6
|
+
<script lang="ts">import { useCalendarContext } from "./context.svelte.js";
|
|
7
|
+
let { event, children } = $props();
|
|
8
|
+
const ctx = useCalendarContext();
|
|
9
|
+
const eventSnippet = $derived(ctx.eventSnippet);
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if eventSnippet}
|
|
13
|
+
{@render eventSnippet(event)}
|
|
14
|
+
{:else}
|
|
15
|
+
{@render children()}
|
|
16
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { TimelineEvent } from '../../core/types.js';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
event: TimelineEvent;
|
|
5
|
+
children: Snippet;
|
|
6
|
+
};
|
|
7
|
+
declare const EventContent: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type EventContent = ReturnType<typeof EventContent>;
|
|
9
|
+
export default EventContent;
|
|
@@ -23,6 +23,7 @@ export interface CalendarContext {
|
|
|
23
23
|
readonly minDuration: number | undefined;
|
|
24
24
|
readonly maxDuration: number | undefined;
|
|
25
25
|
readonly oneventhover: ((event: TimelineEvent) => void) | undefined;
|
|
26
|
+
readonly ondayclick: ((date: Date) => void) | undefined;
|
|
26
27
|
readonly disabledDates: Date[] | undefined;
|
|
27
28
|
readonly disabledSet: Set<number>;
|
|
28
29
|
readonly loadRange: {
|
|
@@ -30,6 +30,7 @@ export function useCalendarContext() {
|
|
|
30
30
|
get minDuration() { return raw?.minDuration; },
|
|
31
31
|
get maxDuration() { return raw?.maxDuration; },
|
|
32
32
|
get oneventhover() { return raw?.oneventhover; },
|
|
33
|
+
get ondayclick() { return raw?.ondayclick; },
|
|
33
34
|
get disabledDates() { return raw?.disabledDates; },
|
|
34
35
|
get disabledSet() { return new Set(raw?.disabledDates?.map(d => sod(d.getTime())) ?? []); },
|
|
35
36
|
get loadRange() {
|
|
@@ -13,122 +13,85 @@
|
|
|
13
13
|
locale="en-US"
|
|
14
14
|
></day-calendar>
|
|
15
15
|
-->
|
|
16
|
-
<script lang="ts">
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function parseEvents(json?: string): TimelineEvent[] {
|
|
99
|
-
if (!json) return [];
|
|
100
|
-
try {
|
|
101
|
-
const raw = JSON.parse(json) as Array<Record<string, unknown>>;
|
|
102
|
-
const parsed = raw
|
|
103
|
-
.map((e, idx) => toEvent(e, `inline-${idx}`))
|
|
104
|
-
.filter((ev): ev is TimelineEvent => ev !== null);
|
|
105
|
-
if (parsed.length !== raw.length) {
|
|
106
|
-
console.warn(`[day-calendar] Ignored ${raw.length - parsed.length} invalid event(s) from events JSON.`);
|
|
107
|
-
}
|
|
108
|
-
return parsed;
|
|
109
|
-
} catch {
|
|
110
|
-
console.warn('[day-calendar] Failed to parse events JSON:', json);
|
|
111
|
-
return [];
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// ── Create adapter ──
|
|
116
|
-
const adapter = $derived.by(() => {
|
|
117
|
-
if (api) {
|
|
118
|
-
const parsedHeaders = parseHeaders(headers);
|
|
119
|
-
return createRestAdapter({
|
|
120
|
-
baseUrl: api,
|
|
121
|
-
headers: parsedHeaders,
|
|
122
|
-
mapEvents: (data: unknown) => {
|
|
123
|
-
const arr = Array.isArray(data) ? data : (data as Record<string, unknown>).events as unknown[] ?? [];
|
|
124
|
-
return arr
|
|
125
|
-
.map((e: unknown, idx) => toEvent(e as Record<string, unknown>, `api-${idx}`))
|
|
126
|
-
.filter((ev): ev is TimelineEvent => ev !== null);
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
return createMemoryAdapter(parseEvents(events));
|
|
131
|
-
});
|
|
16
|
+
<script lang="ts">import Calendar from "../calendar/Calendar.svelte";
|
|
17
|
+
import { createRestAdapter } from "../adapters/rest.js";
|
|
18
|
+
import { createMemoryAdapter } from "../adapters/memory.js";
|
|
19
|
+
import { presets } from "../theme/presets.js";
|
|
20
|
+
let {
|
|
21
|
+
api,
|
|
22
|
+
events,
|
|
23
|
+
theme = "neutral",
|
|
24
|
+
view = "week-planner",
|
|
25
|
+
height = "600",
|
|
26
|
+
locale,
|
|
27
|
+
dir,
|
|
28
|
+
mondaystart = "true",
|
|
29
|
+
headers
|
|
30
|
+
} = $props();
|
|
31
|
+
const heightPx = $derived(parseInt(height, 10) || 600);
|
|
32
|
+
const isMondayStart = $derived(mondaystart !== "false");
|
|
33
|
+
const themeStyle = $derived(
|
|
34
|
+
presets[theme] || presets.neutral
|
|
35
|
+
);
|
|
36
|
+
const dirValue = $derived(
|
|
37
|
+
dir === "rtl" || dir === "ltr" || dir === "auto" ? dir : void 0
|
|
38
|
+
);
|
|
39
|
+
function parseHeaders(json) {
|
|
40
|
+
if (!json) return void 0;
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(json);
|
|
43
|
+
const out = {};
|
|
44
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
45
|
+
out[k] = String(v);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
} catch {
|
|
49
|
+
console.warn("[day-calendar] Failed to parse headers JSON:", json);
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function toEvent(raw, fallbackId) {
|
|
54
|
+
const start = new Date(String(raw.start ?? ""));
|
|
55
|
+
const end = new Date(String(raw.end ?? ""));
|
|
56
|
+
if (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime()) || end <= start) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
id: String(raw.id ?? fallbackId),
|
|
61
|
+
title: String(raw.title ?? "Untitled"),
|
|
62
|
+
start,
|
|
63
|
+
end,
|
|
64
|
+
color: raw.color ? String(raw.color) : void 0
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function parseEvents(json) {
|
|
68
|
+
if (!json) return [];
|
|
69
|
+
try {
|
|
70
|
+
const raw = JSON.parse(json);
|
|
71
|
+
const parsed = raw.map((e, idx) => toEvent(e, `inline-${idx}`)).filter((ev) => ev !== null);
|
|
72
|
+
if (parsed.length !== raw.length) {
|
|
73
|
+
console.warn(`[day-calendar] Ignored ${raw.length - parsed.length} invalid event(s) from events JSON.`);
|
|
74
|
+
}
|
|
75
|
+
return parsed;
|
|
76
|
+
} catch {
|
|
77
|
+
console.warn("[day-calendar] Failed to parse events JSON:", json);
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const adapter = $derived.by(() => {
|
|
82
|
+
if (api) {
|
|
83
|
+
const parsedHeaders = parseHeaders(headers);
|
|
84
|
+
return createRestAdapter({
|
|
85
|
+
baseUrl: api,
|
|
86
|
+
headers: parsedHeaders,
|
|
87
|
+
mapEvents: (data) => {
|
|
88
|
+
const arr = Array.isArray(data) ? data : data.events ?? [];
|
|
89
|
+
return arr.map((e, idx) => toEvent(e, `api-${idx}`)).filter((ev) => ev !== null);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return createMemoryAdapter(parseEvents(events));
|
|
94
|
+
});
|
|
132
95
|
</script>
|
|
133
96
|
|
|
134
97
|
<Calendar
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nomideusz/svelte-calendar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "A themeable Svelte 5 calendar with Day and Week views — Planner and Agenda.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,10 +24,11 @@
|
|
|
24
24
|
"dev": "vite dev",
|
|
25
25
|
"build": "vite build",
|
|
26
26
|
"package": "svelte-kit sync && svelte-package",
|
|
27
|
+
"package:watch": "svelte-kit sync && svelte-package --watch",
|
|
27
28
|
"build:widget": "vite build --config vite.config.widget.ts",
|
|
28
29
|
"prepublishOnly": "npm run package",
|
|
29
30
|
"preview": "vite preview",
|
|
30
|
-
"prepare": "svelte-kit sync
|
|
31
|
+
"prepare": "svelte-kit sync && svelte-package",
|
|
31
32
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
32
33
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
33
34
|
"test": "vitest run",
|