Files
ink-note-app/src/lib/components/DailyCalendar.svelte
T
Your NameandClaude Sonnet 5.5 27fafa0bcd feat(ui): components, routes and styles
Sidebar (lazy tree, keyboard navigation, saved searches), page view with
typed properties, tasks, tags, calendar and clip dialogs, settings with
shortcut rebinding, canvas, database and board views.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-15 11:57:09 +02:00

69 lines
2.8 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script>
import Icon from './Icon.svelte';
import { store } from '$lib/state.svelte.js';
let closing = $state(false);
const start = store.currentDay ? new Date(store.currentDay + 'T12:00:00') : new Date();
let year = $state(start.getFullYear());
let month = $state(start.getMonth());
const iso = (y, m, d) => `${y}-${String(m + 1).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
const now = new Date();
const today = iso(now.getFullYear(), now.getMonth(), now.getDate());
const mondayFirst = $derived(store.prefs.weekStart !== 'sunday');
const locale = $derived(store.prefs.locale || undefined);
let title = $derived(new Date(year, month, 1).toLocaleDateString(locale, { month: 'long', year: 'numeric' }));
let heads = $derived(Array.from({ length: 7 }, (_, i) => new Date(2024, 0, (mondayFirst ? 1 : 7) + i).toLocaleDateString(locale, { weekday: 'short' }).slice(0, 2)));
let cells = $derived.by(() => {
const first = new Date(year, month, 1);
const lead = (first.getDay() + (mondayFirst ? 6 : 0)) % 7;
const count = new Date(year, month + 1, 0).getDate();
const out = [];
for (let i = 0; i < lead; i++) out.push(null);
for (let d = 1; d <= count; d++) out.push(iso(year, month, d));
return out;
});
const have = $derived(store.dailyDays);
function go(delta) {
const d = new Date(year, month + delta, 1);
year = d.getFullYear();
month = d.getMonth();
}
function pick(day) {
close();
setTimeout(() => store.openDaily(new Date(day + 'T12:00:00')), 120);
}
function close() {
closing = true;
setTimeout(() => { store.calendarOpen = false; closing = false; }, 150);
}
</script>
<svelte:window onkeydown={(e) => e.key === 'Escape' && close()} />
<div class="overlay" class:closing role="presentation" onmousedown={(e) => e.target === e.currentTarget && close()}>
<div class="panel cal-panel" role="dialog" aria-label="Daily notes calendar">
<div class="cal-top">
<button class="btn-icon" aria-label="Previous month" onclick={() => go(-1)}><Icon name="chevLeft" /></button>
<b>{title}</b>
<button class="btn-icon" aria-label="Next month" onclick={() => go(1)}><Icon name="chevRight" /></button>
</div>
<div class="cal-grid">
{#each heads as h}<span class="cal-h">{h}</span>{/each}
{#each cells as day, i (i)}
{#if day}
<button class="cal-d" class:today={day === today} class:has={have.has(day)} class:cur={day === store.currentDay} onclick={() => pick(day)} title={have.has(day) ? 'Open this day' : 'Create this day’s note'}>
{Number(day.slice(8))}
</button>
{:else}<span></span>{/if}
{/each}
</div>
<div class="cal-foot">
<span><i class="cal-dot"></i> has a note</span>
<button class="btn" onclick={() => pick(today)}>Today</button>
</div>
</div>
</div>