mirror of
https://github.com/kuboon/daily-nav.git
synced 2026-07-22 06:57:03 +00:00
infinite scroll
This commit is contained in:
parent
1902a8fc6f
commit
24ad1a8f5b
6 changed files with 291 additions and 93 deletions
|
|
@ -12,6 +12,8 @@ This plugin adds two commands to the command palette:
|
|||
It is recommended to use with
|
||||
[Note Toolbar](https://github.com/chrisgurney/obsidian-note-toolbar)
|
||||
|
||||
obsidian://note-toolbar?import=%3E%20%5B!note-toolbar%7Cborder-even-sticky-mrght%5D%20daily%0A%3E%20-%20%5B%3ALiCalendarMinus%3A%5D()%3Cdata%20data-ntb-command%3D%22daily-nav%3Aopen-yesterdays-note%22%2F%3E%20%3C!--%20yesterday%20--%3E%0A%3E%20-%20%5B%3ALiCalendarDays%3A%5D()%3Cdata%20data-ntb-command%3D%22daily-notes%22%2F%3E%20%3C!--%20today%20--%3E%0A%3E%20-%20%5B%3ALiCalendarPlus%3A%5D()%3Cdata%20data-ntb-command%3D%22daily-nav%3Aopen-tomorrows-note%22%2F%3E%20%3C!--%20tomorrow%20--%3E%0A
|
||||
|
||||
## How it works
|
||||
|
||||
This plugin depends on
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "daily-nav",
|
||||
"name": "Daily Nav",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"minAppVersion": "1.12.0",
|
||||
"description": "Open prev/next note based on explorer sorting order",
|
||||
"author": "kuboon",
|
||||
|
|
|
|||
57
styles.css
57
styles.css
|
|
@ -1,5 +1,15 @@
|
|||
.daily-calendar {
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.daily-calendar-viewport {
|
||||
flex: 1 1 0;
|
||||
overflow-y: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.daily-calendar-header {
|
||||
|
|
@ -58,6 +68,7 @@
|
|||
grid-template-columns: auto repeat(7, minmax(0, 1fr));
|
||||
gap: 1px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.daily-calendar-week-header,
|
||||
|
|
@ -85,6 +96,10 @@
|
|||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
padding: 4px 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: var(--background-primary, #1e1e1e);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.daily-calendar-day {
|
||||
|
|
@ -97,6 +112,48 @@
|
|||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-height: 32px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.daily-calendar-week {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Month overlay — absolutely positioned behind day cells */
|
||||
.daily-calendar-month-overlay {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.daily-calendar-month-overlay-num {
|
||||
font-size: 7em;
|
||||
font-weight: 900;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* Odd months: green bg, number "knocked out" in bg color */
|
||||
.daily-calendar-month-overlay-odd {
|
||||
background: rgba(80, 180, 100, 0.08);
|
||||
}
|
||||
|
||||
.daily-calendar-month-overlay-odd .daily-calendar-month-overlay-num {
|
||||
color: var(--background-primary, #1e1e1e);
|
||||
}
|
||||
|
||||
/* Even months: transparent bg, green number */
|
||||
.daily-calendar-month-overlay-even {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.daily-calendar-month-overlay-even .daily-calendar-month-overlay-num {
|
||||
color: rgba(80, 180, 100, 0.08);
|
||||
}
|
||||
|
||||
.daily-calendar-day-num {
|
||||
|
|
|
|||
|
|
@ -16,110 +16,258 @@ export interface CalendarDataSource {
|
|||
onWeekClick(isoYear: number, isoWeek: number): void;
|
||||
}
|
||||
|
||||
/** Pure-DOM calendar renderer. No Obsidian dependency. */
|
||||
/**
|
||||
* Pure-DOM calendar renderer with infinite vertical scroll.
|
||||
* Renders 3x the viewport height of week rows; on scrollend,
|
||||
* re-centers the grid around the new position.
|
||||
*/
|
||||
export class CalendarRenderer {
|
||||
private displayDate: Date;
|
||||
/** Monday of the center week */
|
||||
private centerDate: Date;
|
||||
private container: HTMLElement;
|
||||
private dataSource: CalendarDataSource;
|
||||
|
||||
private viewport: HTMLElement | null = null;
|
||||
private grid: HTMLElement | null = null;
|
||||
private rangeEl: HTMLElement | null = null;
|
||||
private rowHeight = 0;
|
||||
private visibleWeeks = 0;
|
||||
private rendering = false;
|
||||
|
||||
constructor(container: HTMLElement, dataSource: CalendarDataSource, initialDate?: Date) {
|
||||
this.container = container;
|
||||
this.dataSource = dataSource;
|
||||
this.displayDate = initialDate ?? new Date();
|
||||
}
|
||||
|
||||
setDisplayDate(date: Date): void {
|
||||
this.displayDate = date;
|
||||
// Snap to Monday of the week containing initialDate
|
||||
this.centerDate = weekStart(initialDate ?? new Date());
|
||||
}
|
||||
|
||||
/** Jump to today and re-render */
|
||||
goToToday(): void {
|
||||
this.displayDate = new Date();
|
||||
this.centerDate = weekStart(new Date());
|
||||
this.renderGrid();
|
||||
}
|
||||
|
||||
shiftMonth(offset: number): void {
|
||||
const d = new Date(this.displayDate);
|
||||
d.setDate(1);
|
||||
d.setMonth(d.getMonth() + offset);
|
||||
this.displayDate = d;
|
||||
/** Shift center by N weeks and re-render */
|
||||
shiftWeeks(n: number): void {
|
||||
this.centerDate = addDays(this.centerDate, n * 7);
|
||||
this.renderGrid();
|
||||
}
|
||||
|
||||
/** Initial full render — call once */
|
||||
async render(): Promise<void> {
|
||||
this.container.innerHTML = "";
|
||||
|
||||
const wrapper = el("div", "daily-calendar");
|
||||
this.container.appendChild(wrapper);
|
||||
|
||||
// Nav
|
||||
this.renderNav(wrapper);
|
||||
|
||||
const prevMonth = monthOffset(this.displayDate, -1);
|
||||
const nextMonth = monthOffset(this.displayDate, 1);
|
||||
// Range label
|
||||
this.rangeEl = el("div", "daily-calendar-range");
|
||||
wrapper.appendChild(this.rangeEl);
|
||||
|
||||
const range = el("div", "daily-calendar-range");
|
||||
range.textContent = `${fmt(prevMonth)} ~ ${fmt(nextMonth)}`;
|
||||
wrapper.appendChild(range);
|
||||
// Scrollable viewport fills remaining height
|
||||
this.viewport = el("div", "daily-calendar-viewport");
|
||||
wrapper.appendChild(this.viewport);
|
||||
|
||||
const grid = el("div", "daily-calendar-grid");
|
||||
wrapper.appendChild(grid);
|
||||
// Grid inside viewport
|
||||
this.grid = el("div", "daily-calendar-grid");
|
||||
this.viewport.appendChild(this.grid);
|
||||
|
||||
// Header
|
||||
grid.appendChild(elText("div", "W", "daily-calendar-weekday daily-calendar-week-header"));
|
||||
// Sticky header row
|
||||
this.grid.appendChild(elText("div", "W", "daily-calendar-weekday daily-calendar-week-header"));
|
||||
for (const day of ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]) {
|
||||
grid.appendChild(elText("div", day, "daily-calendar-weekday"));
|
||||
this.grid.appendChild(elText("div", day, "daily-calendar-weekday"));
|
||||
}
|
||||
|
||||
const startOfRange = startOfMonth(prevMonth);
|
||||
const endOfRange = endOfMonth(nextMonth);
|
||||
// First render to measure row height
|
||||
await this.buildWeeks(20); // render 20 weeks to measure
|
||||
await frame();
|
||||
this.measureRow();
|
||||
|
||||
const firstDay = weekStart(startOfRange); // Monday
|
||||
const lastDay = weekEnd(endOfRange); // Sunday
|
||||
// Now re-render with correct 3x buffer
|
||||
await this.renderGrid();
|
||||
|
||||
const dayInfoMap = await this.dataSource.loadRange(firstDay, lastDay);
|
||||
const today = stripTime(new Date());
|
||||
// Scroll events
|
||||
this.viewport.addEventListener("scrollend", () => this.onScrollEnd());
|
||||
}
|
||||
|
||||
const cursor = new Date(firstDay);
|
||||
while (cursor <= lastDay) {
|
||||
// Week number on Monday
|
||||
if (isoWeekday(cursor) === 1) {
|
||||
const [isoYear, isoWeek] = isoWeekOfDate(cursor);
|
||||
const weekEl = elText("div", `W${isoWeek}`, "daily-calendar-week");
|
||||
weekEl.setAttribute("aria-label", `${isoYear}-W${pad2(isoWeek)}`);
|
||||
weekEl.addEventListener("click", () => this.dataSource.onWeekClick(isoYear, isoWeek));
|
||||
grid.appendChild(weekEl);
|
||||
}
|
||||
// ── Internal ──
|
||||
|
||||
const date = new Date(cursor);
|
||||
const key = dateKey(date);
|
||||
const isToday = key === dateKey(today);
|
||||
const info = dayInfoMap.get(key);
|
||||
const hasNote = !!info;
|
||||
private measureRow(): void {
|
||||
if (!this.viewport || !this.grid) return;
|
||||
// Find first week cell to measure row height
|
||||
const weekCell = this.grid.querySelector(".daily-calendar-week") as HTMLElement | null;
|
||||
if (!weekCell) return;
|
||||
// Row height = height of 8-cell grid row (week + 7 days)
|
||||
// Measure from one week cell to the next
|
||||
const allWeekCells = this.grid.querySelectorAll(".daily-calendar-week");
|
||||
if (allWeekCells.length >= 2) {
|
||||
const first = (allWeekCells[0] as HTMLElement).getBoundingClientRect().top;
|
||||
const second = (allWeekCells[1] as HTMLElement).getBoundingClientRect().top;
|
||||
this.rowHeight = second - first;
|
||||
} else {
|
||||
// Fallback: use cell offsetHeight + gap
|
||||
this.rowHeight = weekCell.offsetHeight + 1;
|
||||
}
|
||||
if (this.rowHeight <= 0) this.rowHeight = 34; // safety fallback
|
||||
this.visibleWeeks = Math.max(4, Math.ceil(this.viewport.clientHeight / this.rowHeight));
|
||||
}
|
||||
|
||||
const classes = ["daily-calendar-day"];
|
||||
if (isToday) classes.push("daily-calendar-day-today");
|
||||
if (hasNote) classes.push("daily-calendar-day-has-note");
|
||||
if (info?.hasUnchecked) classes.push("daily-calendar-day-unchecked");
|
||||
private async renderGrid(): Promise<void> {
|
||||
if (!this.grid || !this.viewport) return;
|
||||
if (this.rendering) return;
|
||||
this.rendering = true;
|
||||
|
||||
const dayEl = el("div", classes.join(" "));
|
||||
dayEl.appendChild(elText("div", String(date.getDate()), "daily-calendar-day-num"));
|
||||
// Clear day cells but keep sticky header (first 8 children)
|
||||
while (this.grid.children.length > 8) {
|
||||
this.grid.removeChild(this.grid.lastChild!);
|
||||
}
|
||||
|
||||
if (info?.heading) {
|
||||
const label = elText("div", info.heading, "daily-calendar-day-label");
|
||||
label.title = info.heading;
|
||||
dayEl.appendChild(label);
|
||||
}
|
||||
const totalWeeks = this.visibleWeeks * 3;
|
||||
const halfWeeks = Math.floor(totalWeeks / 2);
|
||||
|
||||
dayEl.addEventListener("click", () => this.dataSource.onDayClick(date));
|
||||
dayEl.setAttribute("aria-label", key);
|
||||
dayEl.setAttribute("tabindex", "0");
|
||||
dayEl.addEventListener("keydown", (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
this.dataSource.onDayClick(date);
|
||||
await this.buildWeeks(totalWeeks);
|
||||
await frame();
|
||||
|
||||
// Update range label (visible portion only)
|
||||
const visibleHalf = Math.floor(this.visibleWeeks / 2);
|
||||
const visibleFirst = addDays(this.centerDate, -visibleHalf * 7);
|
||||
const visibleLast = addDays(this.centerDate, (this.visibleWeeks - visibleHalf) * 7 - 1);
|
||||
if (this.rangeEl) {
|
||||
this.rangeEl.textContent = `${fmt(visibleFirst)} ~ ${fmt(visibleLast)}`;
|
||||
}
|
||||
|
||||
// Center scroll: the center week should be in the middle of viewport
|
||||
const headerHeight = (this.grid.children[0] as HTMLElement).offsetHeight;
|
||||
this.viewport.scrollTop = halfWeeks * this.rowHeight + headerHeight
|
||||
- this.viewport.clientHeight / 2
|
||||
+ this.rowHeight / 2;
|
||||
|
||||
this.rendering = false;
|
||||
}
|
||||
|
||||
private async buildWeeks(totalWeeks: number): Promise<void> {
|
||||
if (!this.grid) return;
|
||||
const halfWeeks = Math.floor(totalWeeks / 2);
|
||||
const firstMonday = addDays(this.centerDate, -halfWeeks * 7);
|
||||
const lastSunday = addDays(firstMonday, totalWeeks * 7 - 1);
|
||||
|
||||
const dayInfoMap = await this.dataSource.loadRange(firstMonday, lastSunday);
|
||||
const todayKey = dateKey(stripTime(new Date()));
|
||||
|
||||
// Track month boundaries: weekIndex where the 1st appears
|
||||
const monthMarkers: { weekIndex: number; month: number; isOdd: boolean }[] = [];
|
||||
|
||||
const cursor = new Date(firstMonday);
|
||||
for (let w = 0; w < totalWeeks; w++) {
|
||||
// Week number cell
|
||||
const [isoYear, isoWeek] = isoWeekOfDate(cursor);
|
||||
const weekEl = elText("div", `W${isoWeek}`, "daily-calendar-week");
|
||||
weekEl.setAttribute("aria-label", `${isoYear}-W${pad2(isoWeek)}`);
|
||||
weekEl.addEventListener("click", () => this.dataSource.onWeekClick(isoYear, isoWeek));
|
||||
this.grid.appendChild(weekEl);
|
||||
|
||||
// 7 day cells
|
||||
for (let d = 0; d < 7; d++) {
|
||||
const date = new Date(cursor);
|
||||
const key = dateKey(date);
|
||||
const isToday = key === todayKey;
|
||||
const info = dayInfoMap.get(key);
|
||||
|
||||
const classes = ["daily-calendar-day"];
|
||||
if (isToday) classes.push("daily-calendar-day-today");
|
||||
if (info) classes.push("daily-calendar-day-has-note");
|
||||
if (info?.hasUnchecked) classes.push("daily-calendar-day-unchecked");
|
||||
|
||||
const dayEl = el("div", classes.join(" "));
|
||||
dayEl.appendChild(elText("div", String(date.getDate()), "daily-calendar-day-num"));
|
||||
|
||||
if (info?.heading) {
|
||||
const label = elText("div", info.heading, "daily-calendar-day-label");
|
||||
label.title = info.heading;
|
||||
dayEl.appendChild(label);
|
||||
}
|
||||
});
|
||||
|
||||
grid.appendChild(dayEl);
|
||||
cursor.setDate(cursor.getDate() + 1);
|
||||
dayEl.addEventListener("click", () => this.dataSource.onDayClick(date));
|
||||
dayEl.setAttribute("aria-label", key);
|
||||
dayEl.setAttribute("tabindex", "0");
|
||||
dayEl.addEventListener("keydown", (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
this.dataSource.onDayClick(date);
|
||||
}
|
||||
});
|
||||
|
||||
this.grid.appendChild(dayEl);
|
||||
|
||||
if (date.getDate() === 1) {
|
||||
monthMarkers.push({
|
||||
weekIndex: w,
|
||||
month: date.getMonth() + 1,
|
||||
isOdd: date.getMonth() % 2 === 1,
|
||||
});
|
||||
}
|
||||
|
||||
cursor.setDate(cursor.getDate() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Add month overlays — positioned absolutely within the grid
|
||||
// Wait for layout so we can measure cell positions
|
||||
await frame();
|
||||
// Find the first day cell in each week row to get positions
|
||||
const weekCells = this.grid.querySelectorAll(".daily-calendar-week");
|
||||
const dayCells = this.grid.querySelectorAll(".daily-calendar-day");
|
||||
const gridRect = this.grid.getBoundingClientRect();
|
||||
|
||||
for (const marker of monthMarkers) {
|
||||
const weekCell = weekCells[marker.weekIndex] as HTMLElement | undefined;
|
||||
if (!weekCell) continue;
|
||||
|
||||
// Left edge: first day cell of this week (right after week cell)
|
||||
const firstDayIdx = marker.weekIndex * 7;
|
||||
const firstDayCell = dayCells[firstDayIdx] as HTMLElement | undefined;
|
||||
if (!firstDayCell) continue;
|
||||
|
||||
const top = weekCell.getBoundingClientRect().top - gridRect.top;
|
||||
const left = firstDayCell.getBoundingClientRect().left - gridRect.left;
|
||||
const right = gridRect.right - gridRect.left;
|
||||
const height = this.rowHeight * 4;
|
||||
|
||||
const cls = marker.isOdd
|
||||
? "daily-calendar-month-overlay daily-calendar-month-overlay-odd"
|
||||
: "daily-calendar-month-overlay daily-calendar-month-overlay-even";
|
||||
const overlay = el("div", cls);
|
||||
overlay.style.top = `${top}px`;
|
||||
overlay.style.left = `${left}px`;
|
||||
overlay.style.width = `${right - left}px`;
|
||||
overlay.style.height = `${height}px`;
|
||||
const num = elText("span", String(marker.month), "daily-calendar-month-overlay-num");
|
||||
overlay.appendChild(num);
|
||||
this.grid.appendChild(overlay);
|
||||
}
|
||||
}
|
||||
|
||||
private onScrollEnd(): void {
|
||||
if (!this.viewport || !this.grid || this.rendering) return;
|
||||
if (this.rowHeight <= 0) return;
|
||||
|
||||
const totalWeeks = this.visibleWeeks * 3;
|
||||
const halfWeeks = Math.floor(totalWeeks / 2);
|
||||
const headerHeight = (this.grid.children[0] as HTMLElement).offsetHeight;
|
||||
|
||||
// Current center of viewport in scroll coordinates
|
||||
const viewportCenter = this.viewport.scrollTop + this.viewport.clientHeight / 2;
|
||||
// Expected center (the center week row)
|
||||
const expectedCenter = halfWeeks * this.rowHeight + headerHeight + this.rowHeight / 2;
|
||||
|
||||
const weeksMoved = Math.round((viewportCenter - expectedCenter) / this.rowHeight);
|
||||
if (weeksMoved === 0) return;
|
||||
|
||||
this.centerDate = addDays(this.centerDate, weeksMoved * 7);
|
||||
this.renderGrid();
|
||||
}
|
||||
|
||||
private renderNav(wrapper: HTMLElement): void {
|
||||
|
|
@ -128,25 +276,29 @@ export class CalendarRenderer {
|
|||
|
||||
const prevBtn = elText("button", "\u2039", "daily-calendar-nav");
|
||||
prevBtn.setAttribute("aria-label", "Previous month");
|
||||
prevBtn.addEventListener("click", () => { this.shiftMonth(-1); this.render(); });
|
||||
prevBtn.addEventListener("click", () => this.shiftWeeks(-4));
|
||||
header.appendChild(prevBtn);
|
||||
|
||||
const titleGroup = el("div", "daily-calendar-title-group");
|
||||
const todayBtn = elText("button", "Today", "daily-calendar-today");
|
||||
todayBtn.setAttribute("aria-label", "Go to today");
|
||||
todayBtn.addEventListener("click", () => { this.goToToday(); this.render(); });
|
||||
todayBtn.addEventListener("click", () => this.goToToday());
|
||||
titleGroup.appendChild(todayBtn);
|
||||
header.appendChild(titleGroup);
|
||||
|
||||
const nextBtn = elText("button", "\u203A", "daily-calendar-nav");
|
||||
nextBtn.setAttribute("aria-label", "Next month");
|
||||
nextBtn.addEventListener("click", () => { this.shiftMonth(1); this.render(); });
|
||||
nextBtn.addEventListener("click", () => this.shiftWeeks(4));
|
||||
header.appendChild(nextBtn);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Date helpers (no moment dependency) ──
|
||||
|
||||
function frame(): Promise<void> {
|
||||
return new Promise((r) => requestAnimationFrame(() => r()));
|
||||
}
|
||||
|
||||
function el(tag: string, cls: string): HTMLElement {
|
||||
const e = document.createElement(tag);
|
||||
e.className = cls;
|
||||
|
|
@ -163,6 +315,12 @@ function stripTime(d: Date): Date {
|
|||
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
||||
}
|
||||
|
||||
function addDays(d: Date, n: number): Date {
|
||||
const r = new Date(d);
|
||||
r.setDate(r.getDate() + n);
|
||||
return r;
|
||||
}
|
||||
|
||||
function dateKey(d: Date): string {
|
||||
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
|
||||
}
|
||||
|
|
@ -175,35 +333,14 @@ function fmt(d: Date): string {
|
|||
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}`;
|
||||
}
|
||||
|
||||
function monthOffset(d: Date, offset: number): Date {
|
||||
const r = new Date(d.getFullYear(), d.getMonth() + offset, 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
function startOfMonth(d: Date): Date {
|
||||
return new Date(d.getFullYear(), d.getMonth(), 1);
|
||||
}
|
||||
|
||||
function endOfMonth(d: Date): Date {
|
||||
return new Date(d.getFullYear(), d.getMonth() + 1, 0);
|
||||
}
|
||||
|
||||
/** Monday of the week containing d (ISO: Mon=1) */
|
||||
function weekStart(d: Date): Date {
|
||||
const r = new Date(d);
|
||||
const r = new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
||||
const day = isoWeekday(r);
|
||||
r.setDate(r.getDate() - (day - 1));
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Sunday of the week containing d */
|
||||
function weekEnd(d: Date): Date {
|
||||
const r = new Date(d);
|
||||
const day = isoWeekday(r);
|
||||
r.setDate(r.getDate() + (7 - day));
|
||||
return r;
|
||||
}
|
||||
|
||||
/** 1=Mon .. 7=Sun */
|
||||
function isoWeekday(d: Date): number {
|
||||
return d.getDay() === 0 ? 7 : d.getDay();
|
||||
|
|
@ -212,7 +349,6 @@ function isoWeekday(d: Date): number {
|
|||
/** Returns [isoYear, isoWeek] */
|
||||
function isoWeekOfDate(d: Date): [number, number] {
|
||||
const tmp = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
|
||||
// Set to nearest Thursday: current date + 4 - current day number (Mon=1)
|
||||
tmp.setUTCDate(tmp.getUTCDate() + 4 - (tmp.getUTCDay() || 7));
|
||||
const yearStart = new Date(Date.UTC(tmp.getUTCFullYear(), 0, 1));
|
||||
const weekNo = Math.ceil((((tmp.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);
|
||||
|
|
|
|||
|
|
@ -34,9 +34,11 @@ export class DailyCalendarView extends ItemView {
|
|||
override async onOpen(): Promise<void> {
|
||||
await Promise.resolve();
|
||||
const container = this.containerEl.children[1] as HTMLElement;
|
||||
container.style.height = "100%";
|
||||
container.style.overflow = "hidden";
|
||||
const dataSource = new ObsidianDataSource(this.app, () => m());
|
||||
this.renderer = new CalendarRenderer(container, dataSource);
|
||||
this.renderer.render();
|
||||
await this.renderer.render();
|
||||
this.registerEvent(this.app.vault.on("create", () => this.renderer.render()));
|
||||
this.registerEvent(this.app.vault.on("delete", () => this.renderer.render()));
|
||||
this.registerEvent(this.app.vault.on("rename", () => this.renderer.render()));
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
}
|
||||
#calendar-root {
|
||||
width: 320px;
|
||||
height: 80vh;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
|
|
|
|||
Loading…
Reference in a new issue