@nomideusz/svelte-calendar 0.3.1 → 0.4.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 +568 -544
- package/dist/calendar/Calendar.svelte +21 -1
- package/dist/calendar/Calendar.svelte.d.ts +1 -0
- package/dist/calendar/Toolbar.svelte +5 -2
- package/dist/calendar/Toolbar.svelte.d.ts +2 -0
- package/dist/engine/view-state.svelte.d.ts +1 -0
- package/dist/engine/view-state.svelte.js +3 -0
- package/dist/views/agenda/Agenda.svelte +7 -5
- package/dist/views/agenda/Agenda.svelte.d.ts +1 -0
- package/dist/views/day/DayGrid.svelte +6 -3
- package/dist/views/day/DayGrid.svelte.d.ts +2 -0
- package/dist/views/day/DayTimeline.svelte +4 -3
- package/dist/views/day/DayTimeline.svelte.d.ts +5 -1
- package/dist/views/schedule/WeekSchedule.svelte +4 -0
- package/dist/views/schedule/WeekSchedule.svelte.d.ts +2 -0
- package/dist/views/settings/Settings.svelte +451 -173
- package/dist/views/settings/Settings.svelte.d.ts +22 -6
- package/dist/views/week/WeekGrid.svelte +9 -8
- package/dist/views/week/WeekGrid.svelte.d.ts +1 -0
- package/dist/views/week/WeekHeatmap.svelte +8 -7
- package/dist/views/week/WeekHeatmap.svelte.d.ts +1 -0
- package/dist/widget/CalendarWidget.svelte +0 -2
- package/dist/widget/widget.d.ts +1 -7
- package/dist/widget/widget.js +44 -3
- package/package.json +65 -67
- package/widget/widget.js +260 -260
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
oneventclick?: (event: TimelineEvent) => void;
|
|
73
73
|
oneventcreate?: (range: { start: Date; end: Date }) => void;
|
|
74
74
|
oneventmove?: (event: TimelineEvent, newStart: Date, newEnd: Date) => void;
|
|
75
|
+
onviewchange?: (viewId: CalendarViewId) => void;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
let {
|
|
@@ -90,6 +91,7 @@
|
|
|
90
91
|
oneventclick,
|
|
91
92
|
oneventcreate,
|
|
92
93
|
oneventmove,
|
|
94
|
+
onviewchange,
|
|
93
95
|
}: Props = $props();
|
|
94
96
|
|
|
95
97
|
// In readOnly mode, suppress mutation callbacks
|
|
@@ -153,6 +155,23 @@
|
|
|
153
155
|
store.load({ start, end });
|
|
154
156
|
});
|
|
155
157
|
|
|
158
|
+
// Keep active view in sync when external defaultView changes after mount.
|
|
159
|
+
$effect(() => {
|
|
160
|
+
viewState.setView(defaultView);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Keep view state's week-start rule in sync with incoming prop changes.
|
|
164
|
+
$effect(() => {
|
|
165
|
+
if (viewState.mondayStart !== mondayStart) {
|
|
166
|
+
viewState.setMondayStart(mondayStart);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Notify host when active view changes (e.g. via toolbar concept/granularity toggles).
|
|
171
|
+
$effect(() => {
|
|
172
|
+
onviewchange?.(viewState.view);
|
|
173
|
+
});
|
|
174
|
+
|
|
156
175
|
// ── Resolve active view ──
|
|
157
176
|
const activeView = $derived(views.find((v) => v.id === viewState.view) ?? views[0]);
|
|
158
177
|
|
|
@@ -170,7 +189,7 @@
|
|
|
170
189
|
lang={locale}
|
|
171
190
|
>
|
|
172
191
|
{#if showToolbar}
|
|
173
|
-
<Toolbar {viewState} views={toolbarViews} {links} />
|
|
192
|
+
<Toolbar {viewState} views={toolbarViews} {links} {locale} />
|
|
174
193
|
{/if}
|
|
175
194
|
|
|
176
195
|
<div class="cal-body">
|
|
@@ -181,6 +200,7 @@
|
|
|
181
200
|
style={theme}
|
|
182
201
|
height={height - (showToolbar ? 48 : 0)}
|
|
183
202
|
mondayStart={viewState.mondayStart}
|
|
203
|
+
{locale}
|
|
184
204
|
focusDate={viewState.focusDate}
|
|
185
205
|
oneventclick={oneventclick}
|
|
186
206
|
oneventcreate={effectiveCreate}
|
|
@@ -47,6 +47,7 @@ interface Props {
|
|
|
47
47
|
end: Date;
|
|
48
48
|
}) => void;
|
|
49
49
|
oneventmove?: (event: TimelineEvent, newStart: Date, newEnd: Date) => void;
|
|
50
|
+
onviewchange?: (viewId: CalendarViewId) => void;
|
|
50
51
|
}
|
|
51
52
|
declare const Calendar: Component<Props, {}, "">;
|
|
52
53
|
type Calendar = ReturnType<typeof Calendar>;
|
|
@@ -19,20 +19,23 @@
|
|
|
19
19
|
views?: ViewOption[];
|
|
20
20
|
/** Links to show in the toolbar */
|
|
21
21
|
links?: { href: string; label: string }[];
|
|
22
|
+
/** Locale used for labels */
|
|
23
|
+
locale?: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
let {
|
|
25
27
|
viewState,
|
|
26
28
|
views = [],
|
|
27
29
|
links = [],
|
|
30
|
+
locale,
|
|
28
31
|
}: Props = $props();
|
|
29
32
|
|
|
30
33
|
const dateLabel = $derived(() => {
|
|
31
34
|
if (viewState.granularity === 'day') {
|
|
32
|
-
return `${weekdayLong(viewState.focusDate.getTime())}, ${fmtDay(viewState.focusDate.getTime(), Date.now())}`;
|
|
35
|
+
return `${weekdayLong(viewState.focusDate.getTime(), locale)}, ${fmtDay(viewState.focusDate.getTime(), Date.now(), undefined, locale)}`;
|
|
33
36
|
}
|
|
34
37
|
const ws = viewState.range.start.getTime();
|
|
35
|
-
return fmtWeekRange(ws);
|
|
38
|
+
return fmtWeekRange(ws, locale);
|
|
36
39
|
});
|
|
37
40
|
|
|
38
41
|
// Which granularities are available?
|
|
@@ -28,6 +28,7 @@ export interface ViewState {
|
|
|
28
28
|
/** IANA timezone, or undefined for local */
|
|
29
29
|
readonly timezone: string | undefined;
|
|
30
30
|
setView(id: CalendarViewId): void;
|
|
31
|
+
setMondayStart(value: boolean): void;
|
|
31
32
|
setFocusDate(date: Date): void;
|
|
32
33
|
next(): void;
|
|
33
34
|
prev(): void;
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
/** 'day' = single-day timeline rail, 'week' = rolling 7-day view */
|
|
26
26
|
mode?: 'day' | 'week';
|
|
27
27
|
mondayStart?: boolean;
|
|
28
|
+
locale?: string;
|
|
28
29
|
height?: number;
|
|
29
30
|
events?: TimelineEvent[];
|
|
30
31
|
style?: string;
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
let {
|
|
39
40
|
mode = 'day',
|
|
40
41
|
mondayStart = true,
|
|
42
|
+
locale,
|
|
41
43
|
height = 520,
|
|
42
44
|
events = [],
|
|
43
45
|
style = '',
|
|
@@ -51,7 +53,7 @@
|
|
|
51
53
|
// ── Format helpers ──────────────────────────────────
|
|
52
54
|
function fmtTime(d: Date): string {
|
|
53
55
|
return d
|
|
54
|
-
.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true })
|
|
56
|
+
.toLocaleTimeString(locale ?? 'en-US', { hour: 'numeric', minute: '2-digit', hour12: true })
|
|
55
57
|
.toLowerCase();
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -220,7 +222,7 @@
|
|
|
220
222
|
? startOfWeek(sod(focusDate.getTime()), mondayStart)
|
|
221
223
|
: startOfWeek(clock.today, mondayStart),
|
|
222
224
|
);
|
|
223
|
-
const weekLabel = $derived(fmtWeekRange(weekStartMs));
|
|
225
|
+
const weekLabel = $derived(fmtWeekRange(weekStartMs, locale));
|
|
224
226
|
|
|
225
227
|
const weekDays = $derived.by((): DayGroup[] => {
|
|
226
228
|
if (mode !== 'week') return [];
|
|
@@ -255,8 +257,8 @@
|
|
|
255
257
|
|
|
256
258
|
out.push({
|
|
257
259
|
ms,
|
|
258
|
-
dayName: tier === 'today' || tier === 'tomorrow' ? weekdayLong(ms) : weekdayShort(ms),
|
|
259
|
-
dateLabel: `${monthShort(ms)} ${dayNum(ms)}`,
|
|
260
|
+
dayName: tier === 'today' || tier === 'tomorrow' ? weekdayLong(ms, locale) : weekdayShort(ms, locale),
|
|
261
|
+
dateLabel: `${monthShort(ms, locale)} ${dayNum(ms)}`,
|
|
260
262
|
tier,
|
|
261
263
|
events: dayEvts,
|
|
262
264
|
pastEvents,
|
|
@@ -325,7 +327,7 @@
|
|
|
325
327
|
<header class="ag-header">
|
|
326
328
|
{#if mode === 'day'}
|
|
327
329
|
<div class="ag-header-left">
|
|
328
|
-
<span class="ag-title">{fmtDay(dayMs, clock.today, { short: false })}</span>
|
|
330
|
+
<span class="ag-title">{fmtDay(dayMs, clock.today, { short: false }, locale)}</span>
|
|
329
331
|
{#if isToday}
|
|
330
332
|
<span class="ag-clock">{clock.hm}</span>
|
|
331
333
|
{:else if isPastDay}
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
style?: string;
|
|
36
36
|
/** The date to centre this view on */
|
|
37
37
|
focusDate?: Date;
|
|
38
|
+
/** Locale for labels */
|
|
39
|
+
locale?: string;
|
|
38
40
|
/** Called when the user clicks an event */
|
|
39
41
|
oneventclick?: (event: TimelineEvent) => void;
|
|
40
42
|
/** Called when the user clicks an empty time slot */
|
|
@@ -58,6 +60,7 @@
|
|
|
58
60
|
height = 520,
|
|
59
61
|
events = [],
|
|
60
62
|
style = '',
|
|
63
|
+
locale,
|
|
61
64
|
focusDate,
|
|
62
65
|
oneventclick,
|
|
63
66
|
oneventcreate,
|
|
@@ -130,7 +133,7 @@
|
|
|
130
133
|
|
|
131
134
|
layouts.push({
|
|
132
135
|
ms,
|
|
133
|
-
name: fmtDay(ms, clock.today, { short: true }),
|
|
136
|
+
name: fmtDay(ms, clock.today, { short: true }, locale),
|
|
134
137
|
today: isToday,
|
|
135
138
|
past: isPast,
|
|
136
139
|
dayX: x,
|
|
@@ -579,7 +582,7 @@
|
|
|
579
582
|
{@const hour = NIGHT_END + h}
|
|
580
583
|
{@const x = h * hourWidth}
|
|
581
584
|
<div class="fs-tick" style:left="{x}px">
|
|
582
|
-
<span class="fs-tick-lb">{fmtH(hour)}</span>
|
|
585
|
+
<span class="fs-tick-lb">{fmtH(hour, locale)}</span>
|
|
583
586
|
</div>
|
|
584
587
|
<div class="fs-tick fs-tick--half" style:left="{x + hourWidth * 0.5}px"></div>
|
|
585
588
|
{/each}
|
|
@@ -605,7 +608,7 @@
|
|
|
605
608
|
{@const hour = (NIGHT_START + h) % 24}
|
|
606
609
|
{@const x = h * hourWidth}
|
|
607
610
|
<div class="fs-tick fs-tick--night" style:left="{x}px">
|
|
608
|
-
<span class="fs-tick-lb">{fmtH(hour)}</span>
|
|
611
|
+
<span class="fs-tick-lb">{fmtH(hour, locale)}</span>
|
|
609
612
|
</div>
|
|
610
613
|
{/each}
|
|
611
614
|
<button class="fs-night-toggle" onclick={(e) => { e.stopPropagation(); toggleNight(i); }}>
|
|
@@ -16,6 +16,8 @@ interface Props {
|
|
|
16
16
|
style?: string;
|
|
17
17
|
/** The date to centre this view on */
|
|
18
18
|
focusDate?: Date;
|
|
19
|
+
/** Locale for labels */
|
|
20
|
+
locale?: string;
|
|
19
21
|
/** Called when the user clicks an event */
|
|
20
22
|
oneventclick?: (event: TimelineEvent) => void;
|
|
21
23
|
/** Called when the user clicks an empty time slot */
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
nowPosition = 0.25,
|
|
15
15
|
events = [],
|
|
16
16
|
style = '',
|
|
17
|
+
locale,
|
|
17
18
|
focusDate,
|
|
18
19
|
oneventclick,
|
|
19
20
|
selectedEventId = null,
|
|
20
|
-
}: DayTimelineProps = $props();
|
|
21
|
+
}: DayTimelineProps & { locale?: string; [key: string]: unknown } = $props();
|
|
21
22
|
|
|
22
23
|
// ── Drag support (available when inside Calendar) ──
|
|
23
24
|
const drag = getContext<DragState>('calendar:drag') as DragState | undefined;
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
out.push({
|
|
49
50
|
ms,
|
|
50
51
|
x: i * dayW,
|
|
51
|
-
name: fmtDay(ms, clock.today),
|
|
52
|
+
name: fmtDay(ms, clock.today, undefined, locale),
|
|
52
53
|
today: ms === clock.today
|
|
53
54
|
});
|
|
54
55
|
}
|
|
@@ -242,7 +243,7 @@
|
|
|
242
243
|
{#each HOURS as h}
|
|
243
244
|
{@const x = d.x + h * hourWidth}
|
|
244
245
|
<div class="dt-tick" style:left="{x}px">
|
|
245
|
-
<span class="dt-tick-lb">{fmtH(h)}</span>
|
|
246
|
+
<span class="dt-tick-lb">{fmtH(h, locale)}</span>
|
|
246
247
|
</div>
|
|
247
248
|
<div class="dt-tick dt-tick--h" style:left="{x + hourWidth * 0.5}px"></div>
|
|
248
249
|
{/each}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { DayTimelineProps } from '../../core/types.js';
|
|
2
|
-
|
|
2
|
+
type $$ComponentProps = DayTimelineProps & {
|
|
3
|
+
locale?: string;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
};
|
|
6
|
+
declare const DayTimeline: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
3
7
|
type DayTimeline = ReturnType<typeof DayTimeline>;
|
|
4
8
|
export default DayTimeline;
|
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
theme?: string;
|
|
41
41
|
/** BCP 47 locale */
|
|
42
42
|
locale?: string;
|
|
43
|
+
/** Text direction */
|
|
44
|
+
dir?: 'ltr' | 'rtl' | 'auto';
|
|
43
45
|
/** Total height */
|
|
44
46
|
height?: number;
|
|
45
47
|
/** Start week on Monday */
|
|
@@ -67,6 +69,7 @@
|
|
|
67
69
|
schedule,
|
|
68
70
|
theme = '',
|
|
69
71
|
locale,
|
|
72
|
+
dir,
|
|
70
73
|
height = 560,
|
|
71
74
|
mondayStart = true,
|
|
72
75
|
readOnly = true,
|
|
@@ -123,6 +126,7 @@
|
|
|
123
126
|
defaultView="week-grid"
|
|
124
127
|
{theme}
|
|
125
128
|
{locale}
|
|
129
|
+
{dir}
|
|
126
130
|
{height}
|
|
127
131
|
{mondayStart}
|
|
128
132
|
{readOnly}
|