@tasknotes/calendar 0.1.2 → 0.1.4

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/dist/esm/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  TIMELINE_UNIT_DAYS,
8
8
  defaultOptions,
9
9
  localeFirstDay
10
- } from "./chunk-ZJQMMA6W.js";
10
+ } from "./chunk-26DEUGQH.js";
11
11
  import {
12
12
  DAY_MS,
13
13
  ItemStore,
package/dist/esm/react.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Calendar
3
- } from "./chunk-ZJQMMA6W.js";
3
+ } from "./chunk-26DEUGQH.js";
4
4
  import "./chunk-DVMZ5OXN.js";
5
5
 
6
6
  // src/react/index.tsx
@@ -6,6 +6,7 @@ import { type TimeZone } from "../core/zone.cjs";
6
6
  import { type ElMeta, type ViewContext } from "./context.cjs";
7
7
  import { Formatter } from "./format.cjs";
8
8
  import { type CalendarOptions, type CalendarText, type DayArg, type ExternalDragSource, type Hit, type TimelineAnchor, type ViewInfo, type ViewType } from "./options.cjs";
9
+ import { DateStrip } from "./views/strip.cjs";
9
10
  /**
10
11
  * A calendar bound to one element. Works in any document, including Obsidian
11
12
  * popout windows: all listeners, timers and observers use the element's window.
@@ -40,10 +41,15 @@ export declare class Calendar<D = unknown> implements ViewContext<D> {
40
41
  id: string;
41
42
  rowId: string;
42
43
  } | null;
44
+ strip: DateStrip<D> | null;
45
+ private stripSize;
46
+ private rebuilding;
43
47
  private readonly toolbarEl;
44
48
  private readonly viewHost;
45
49
  private current;
46
50
  private anchor;
51
+ /** End of an agenda list grown past its `listDayCount`. */
52
+ private listEnd;
47
53
  private session;
48
54
  private selection;
49
55
  private suppressClick;
@@ -147,6 +153,21 @@ export declare class Calendar<D = unknown> implements ViewContext<D> {
147
153
  private computeRange;
148
154
  private computeTitle;
149
155
  private rebuild;
156
+ /** Sets the visible days and view info from the anchor. */
157
+ private applyRange;
158
+ /** The range, run on to the end of the strip's days so their dots are right. */
159
+ private dataRangeFor;
160
+ /** Adds, updates or removes the date strip for the current view. */
161
+ private syncStrip;
162
+ private pickStripDay;
163
+ /** The strip moved to other days: load theirs too. */
164
+ private stripShown;
165
+ /** What is under a point, the date strip included. */
166
+ private hitAt;
167
+ private agendaList;
168
+ extendList(endDay: Day): void;
169
+ showListDay(day: Day): void;
170
+ dateClick(day: Day, jsEvent: MouseEvent | KeyboardEvent): void;
150
171
  private createView;
151
172
  private renderToolbar;
152
173
  private applyChange;
@@ -6,6 +6,7 @@ import { type TimeZone } from "../core/zone.js";
6
6
  import { type ElMeta, type ViewContext } from "./context.js";
7
7
  import { Formatter } from "./format.js";
8
8
  import { type CalendarOptions, type CalendarText, type DayArg, type ExternalDragSource, type Hit, type TimelineAnchor, type ViewInfo, type ViewType } from "./options.js";
9
+ import { DateStrip } from "./views/strip.js";
9
10
  /**
10
11
  * A calendar bound to one element. Works in any document, including Obsidian
11
12
  * popout windows: all listeners, timers and observers use the element's window.
@@ -40,10 +41,15 @@ export declare class Calendar<D = unknown> implements ViewContext<D> {
40
41
  id: string;
41
42
  rowId: string;
42
43
  } | null;
44
+ strip: DateStrip<D> | null;
45
+ private stripSize;
46
+ private rebuilding;
43
47
  private readonly toolbarEl;
44
48
  private readonly viewHost;
45
49
  private current;
46
50
  private anchor;
51
+ /** End of an agenda list grown past its `listDayCount`. */
52
+ private listEnd;
47
53
  private session;
48
54
  private selection;
49
55
  private suppressClick;
@@ -147,6 +153,21 @@ export declare class Calendar<D = unknown> implements ViewContext<D> {
147
153
  private computeRange;
148
154
  private computeTitle;
149
155
  private rebuild;
156
+ /** Sets the visible days and view info from the anchor. */
157
+ private applyRange;
158
+ /** The range, run on to the end of the strip's days so their dots are right. */
159
+ private dataRangeFor;
160
+ /** Adds, updates or removes the date strip for the current view. */
161
+ private syncStrip;
162
+ private pickStripDay;
163
+ /** The strip moved to other days: load theirs too. */
164
+ private stripShown;
165
+ /** What is under a point, the date strip included. */
166
+ private hitAt;
167
+ private agendaList;
168
+ extendList(endDay: Day): void;
169
+ showListDay(day: Day): void;
170
+ dateClick(day: Day, jsEvent: MouseEvent | KeyboardEvent): void;
150
171
  private createView;
151
172
  private renderToolbar;
152
173
  private applyChange;
@@ -5,6 +5,7 @@ import type { NormalizedItem } from "../core/types.cjs";
5
5
  import type { TimeZone } from "../core/zone.cjs";
6
6
  import type { Formatter } from "./format.cjs";
7
7
  import type { CalendarOptions, CalendarText, DayArg, Hit, ItemVariant, ViewInfo } from "./options.cjs";
8
+ import type { DateStrip } from "./views/strip.cjs";
8
9
  export type Variant = ItemVariant;
9
10
  export interface ElMeta<D = unknown> {
10
11
  n: NormalizedItem<D>;
@@ -70,6 +71,14 @@ export interface ViewContext<D = unknown> {
70
71
  id: string;
71
72
  rowId: string;
72
73
  } | null;
74
+ /** Reports a day picked outside the grid (year days) through `onDateClick`. */
75
+ dateClick(day: Day, jsEvent: MouseEvent | KeyboardEvent): void;
76
+ /** The date strip, when the view has one. */
77
+ readonly strip: DateStrip<D> | null;
78
+ /** Agenda lists: grows the range to end at `endDay`. */
79
+ extendList(endDay: Day): void;
80
+ /** Agenda lists: brings `day` to the top, moving the range to reach it. */
81
+ showListDay(day: Day): void;
73
82
  }
74
83
  export interface View {
75
84
  readonly el: HTMLElement;
@@ -5,6 +5,7 @@ import type { NormalizedItem } from "../core/types.js";
5
5
  import type { TimeZone } from "../core/zone.js";
6
6
  import type { Formatter } from "./format.js";
7
7
  import type { CalendarOptions, CalendarText, DayArg, Hit, ItemVariant, ViewInfo } from "./options.js";
8
+ import type { DateStrip } from "./views/strip.js";
8
9
  export type Variant = ItemVariant;
9
10
  export interface ElMeta<D = unknown> {
10
11
  n: NormalizedItem<D>;
@@ -70,6 +71,14 @@ export interface ViewContext<D = unknown> {
70
71
  id: string;
71
72
  rowId: string;
72
73
  } | null;
74
+ /** Reports a day picked outside the grid (year days) through `onDateClick`. */
75
+ dateClick(day: Day, jsEvent: MouseEvent | KeyboardEvent): void;
76
+ /** The date strip, when the view has one. */
77
+ readonly strip: DateStrip<D> | null;
78
+ /** Agenda lists: grows the range to end at `endDay`. */
79
+ extendList(endDay: Day): void;
80
+ /** Agenda lists: brings `day` to the top, moving the range to reach it. */
81
+ showListDay(day: Day): void;
73
82
  }
74
83
  export interface View {
75
84
  readonly el: HTMLElement;
@@ -14,6 +14,12 @@ export interface ViewInfo {
14
14
  /** Anchor date the view was built around. */
15
15
  anchor: Day;
16
16
  title: string;
17
+ /**
18
+ * The days whose items the calendar can show: `range`, extended to the
19
+ * end of the days a date strip is showing so their dots are right. Load
20
+ * items for this range; `onRangeChange` fires when it changes too.
21
+ */
22
+ dataRange: DateRange;
17
23
  }
18
24
  /** Where a pointer is over the calendar. */
19
25
  export type Hit = {
@@ -283,6 +289,39 @@ export interface CalendarOptions<D = unknown> {
283
289
  * start of its week ("week", like FullCalendar's stock `listWeek`).
284
290
  */
285
291
  listStart: "date" | "week";
292
+ /**
293
+ * Turns the "list" view into a phone-style agenda: a date strip (one week,
294
+ * or the month when expanded) above a list of every day, empty ones
295
+ * included, that loads more days as it nears its end. The strip marks the
296
+ * day at the top of the list, picking a day scrolls to it, and items
297
+ * dragged onto a strip day or another day's section move there.
298
+ */
299
+ listAgenda: boolean;
300
+ /**
301
+ * Puts the agenda's date strip above the "day", "days" and "week" views
302
+ * too. Picking a strip day moves the grid to it, and items dragged onto a
303
+ * strip day move there at the same time.
304
+ */
305
+ dateStrip: boolean;
306
+ /**
307
+ * Agenda lists: a section above the first day, titled with this text, for
308
+ * items `listLeadIncludes` picks out (overdue work, say). Those items show
309
+ * there instead of under their day. Null for none.
310
+ */
311
+ listLeadTitle: string | null;
312
+ listLeadIncludes?: (item: CalendarItem<D>) => boolean;
313
+ /** The lead section's header has an empty slot for host controls (a "Reschedule" button, say). */
314
+ listLeadDidMount?: (arg: {
315
+ el: HTMLElement;
316
+ }) => void;
317
+ listLeadWillUnmount?: (arg: {
318
+ el: HTMLElement;
319
+ }) => void;
320
+ /** Agenda lists: an add row with this label under every day, reported through `onListAdd`. Null for none. */
321
+ listAddText: string | null;
322
+ onListAdd?: (arg: DayArg & {
323
+ jsEvent: MouseEvent | KeyboardEvent;
324
+ }) => void;
286
325
  /**
287
326
  * Month cells: "full" draws bars and titled entries; "dots" draws every
288
327
  * item as a small dot that wraps across the cell, with a "+N" count when
@@ -393,6 +432,17 @@ export interface CalendarOptions<D = unknown> {
393
432
  listItemContent?: (arg: ItemArg<D>) => Node | null | undefined;
394
433
  dayHeaderContent?: (arg: DayArg) => Node | string | null | undefined;
395
434
  dayHeaderDidMount?: (arg: DayHeaderArg) => void;
435
+ /**
436
+ * The date strip's header has an empty slot after its arrows. Mount host
437
+ * controls (a layout menu, say) into `el`; the calendar leaves it alone.
438
+ */
439
+ stripSlotDidMount?: (arg: {
440
+ el: HTMLElement;
441
+ }) => void;
442
+ /** The date strip's slot is about to be removed. */
443
+ stripSlotWillUnmount?: (arg: {
444
+ el: HTMLElement;
445
+ }) => void;
396
446
  dayClassNames?: (arg: DayArg) => string[] | string | undefined;
397
447
  }
398
448
  export declare const DEFAULT_TEXT: CalendarText;
@@ -14,6 +14,12 @@ export interface ViewInfo {
14
14
  /** Anchor date the view was built around. */
15
15
  anchor: Day;
16
16
  title: string;
17
+ /**
18
+ * The days whose items the calendar can show: `range`, extended to the
19
+ * end of the days a date strip is showing so their dots are right. Load
20
+ * items for this range; `onRangeChange` fires when it changes too.
21
+ */
22
+ dataRange: DateRange;
17
23
  }
18
24
  /** Where a pointer is over the calendar. */
19
25
  export type Hit = {
@@ -283,6 +289,39 @@ export interface CalendarOptions<D = unknown> {
283
289
  * start of its week ("week", like FullCalendar's stock `listWeek`).
284
290
  */
285
291
  listStart: "date" | "week";
292
+ /**
293
+ * Turns the "list" view into a phone-style agenda: a date strip (one week,
294
+ * or the month when expanded) above a list of every day, empty ones
295
+ * included, that loads more days as it nears its end. The strip marks the
296
+ * day at the top of the list, picking a day scrolls to it, and items
297
+ * dragged onto a strip day or another day's section move there.
298
+ */
299
+ listAgenda: boolean;
300
+ /**
301
+ * Puts the agenda's date strip above the "day", "days" and "week" views
302
+ * too. Picking a strip day moves the grid to it, and items dragged onto a
303
+ * strip day move there at the same time.
304
+ */
305
+ dateStrip: boolean;
306
+ /**
307
+ * Agenda lists: a section above the first day, titled with this text, for
308
+ * items `listLeadIncludes` picks out (overdue work, say). Those items show
309
+ * there instead of under their day. Null for none.
310
+ */
311
+ listLeadTitle: string | null;
312
+ listLeadIncludes?: (item: CalendarItem<D>) => boolean;
313
+ /** The lead section's header has an empty slot for host controls (a "Reschedule" button, say). */
314
+ listLeadDidMount?: (arg: {
315
+ el: HTMLElement;
316
+ }) => void;
317
+ listLeadWillUnmount?: (arg: {
318
+ el: HTMLElement;
319
+ }) => void;
320
+ /** Agenda lists: an add row with this label under every day, reported through `onListAdd`. Null for none. */
321
+ listAddText: string | null;
322
+ onListAdd?: (arg: DayArg & {
323
+ jsEvent: MouseEvent | KeyboardEvent;
324
+ }) => void;
286
325
  /**
287
326
  * Month cells: "full" draws bars and titled entries; "dots" draws every
288
327
  * item as a small dot that wraps across the cell, with a "+N" count when
@@ -393,6 +432,17 @@ export interface CalendarOptions<D = unknown> {
393
432
  listItemContent?: (arg: ItemArg<D>) => Node | null | undefined;
394
433
  dayHeaderContent?: (arg: DayArg) => Node | string | null | undefined;
395
434
  dayHeaderDidMount?: (arg: DayHeaderArg) => void;
435
+ /**
436
+ * The date strip's header has an empty slot after its arrows. Mount host
437
+ * controls (a layout menu, say) into `el`; the calendar leaves it alone.
438
+ */
439
+ stripSlotDidMount?: (arg: {
440
+ el: HTMLElement;
441
+ }) => void;
442
+ /** The date strip's slot is about to be removed. */
443
+ stripSlotWillUnmount?: (arg: {
444
+ el: HTMLElement;
445
+ }) => void;
396
446
  dayClassNames?: (arg: DayArg) => string[] | string | undefined;
397
447
  }
398
448
  export declare const DEFAULT_TEXT: CalendarText;
@@ -1,19 +1,42 @@
1
+ import { type Day } from "../../core/date.cjs";
1
2
  import type { StoreChange } from "../../core/store.cjs";
2
3
  import { type Selection, type View, type ViewContext } from "../context.cjs";
3
4
  import type { Hit } from "../options.cjs";
4
- /** N-day agenda: one section per day that has items. */
5
+ /**
6
+ * N-day agenda: one section per day that has items. With `listAgenda`, every
7
+ * day gets a section, the calendar's date strip follows the day at the top,
8
+ * and more days load as the list nears its end. A lead section above the
9
+ * first day can collect items such as overdue work.
10
+ */
5
11
  export declare class ListView<D> implements View {
6
12
  private readonly ctx;
7
13
  readonly el: HTMLElement;
8
14
  private readonly scroller;
9
15
  private readonly body;
16
+ private readonly agenda;
10
17
  private pools;
11
18
  private sections;
19
+ private lead;
20
+ private readonly sentinel;
21
+ private readonly loader;
22
+ private frame;
23
+ /** A picked day stays marked until the list is scrolled by hand. */
24
+ private pinned;
12
25
  constructor(ctx: ViewContext<D>);
13
26
  private itemsOn;
14
27
  render(_change: StoreChange | null): void;
28
+ /** Places items in a pool, keeping DOM order equal to item order. */
29
+ private fill;
30
+ private renderLead;
31
+ private addRow;
32
+ /** Brings a day's section to the top, under the strip; the first day brings the lead section too. */
33
+ scrollToDay(day: Day): void;
34
+ private readonly fold;
35
+ private readonly onScroll;
36
+ /** Marks the first day not hidden under the strip. */
37
+ private followTop;
15
38
  showSelection(_sel: Selection | null): void;
16
- hit(_x: number, _y: number): Hit | null;
39
+ hit(x: number, y: number): Hit | null;
17
40
  getScroll(): {
18
41
  top: number;
19
42
  left: number;
@@ -1,19 +1,42 @@
1
+ import { type Day } from "../../core/date.js";
1
2
  import type { StoreChange } from "../../core/store.js";
2
3
  import { type Selection, type View, type ViewContext } from "../context.js";
3
4
  import type { Hit } from "../options.js";
4
- /** N-day agenda: one section per day that has items. */
5
+ /**
6
+ * N-day agenda: one section per day that has items. With `listAgenda`, every
7
+ * day gets a section, the calendar's date strip follows the day at the top,
8
+ * and more days load as the list nears its end. A lead section above the
9
+ * first day can collect items such as overdue work.
10
+ */
5
11
  export declare class ListView<D> implements View {
6
12
  private readonly ctx;
7
13
  readonly el: HTMLElement;
8
14
  private readonly scroller;
9
15
  private readonly body;
16
+ private readonly agenda;
10
17
  private pools;
11
18
  private sections;
19
+ private lead;
20
+ private readonly sentinel;
21
+ private readonly loader;
22
+ private frame;
23
+ /** A picked day stays marked until the list is scrolled by hand. */
24
+ private pinned;
12
25
  constructor(ctx: ViewContext<D>);
13
26
  private itemsOn;
14
27
  render(_change: StoreChange | null): void;
28
+ /** Places items in a pool, keeping DOM order equal to item order. */
29
+ private fill;
30
+ private renderLead;
31
+ private addRow;
32
+ /** Brings a day's section to the top, under the strip; the first day brings the lead section too. */
33
+ scrollToDay(day: Day): void;
34
+ private readonly fold;
35
+ private readonly onScroll;
36
+ /** Marks the first day not hidden under the strip. */
37
+ private followTop;
15
38
  showSelection(_sel: Selection | null): void;
16
- hit(_x: number, _y: number): Hit | null;
39
+ hit(x: number, y: number): Hit | null;
17
40
  getScroll(): {
18
41
  top: number;
19
42
  left: number;
@@ -0,0 +1,63 @@
1
+ import { type Day } from "../../core/date.cjs";
2
+ import type { ViewContext } from "../context.cjs";
3
+ /**
4
+ * A date strip above the agenda or a time grid: one week, or the whole month
5
+ * when expanded. Days with items carry a dot; the focus day (the top of the
6
+ * list, or the grid's first day) is marked, and the rest of a grid's range is
7
+ * tinted. Picking a day hands it to the calendar, and swipes step a week (or
8
+ * a month).
9
+ */
10
+ export declare class DateStrip<D> {
11
+ private readonly ctx;
12
+ private readonly pick;
13
+ /** Called when the days on show change, so their items can be loaded. */
14
+ private readonly onShown;
15
+ readonly el: HTMLElement;
16
+ private readonly title;
17
+ private readonly dows;
18
+ private readonly grid;
19
+ private readonly slot;
20
+ private readonly todayBtn;
21
+ /** Day at the top of the list. */
22
+ private focus;
23
+ /** First day of the week shown, or the month shown when expanded. */
24
+ private shown;
25
+ private target;
26
+ /** Days tinted as on screen besides the focus (a time grid's range). */
27
+ private range;
28
+ private shownKey;
29
+ private swipe;
30
+ private swallowClick;
31
+ expanded: boolean;
32
+ constructor(ctx: ViewContext<D>, pick: (day: Day, ev: MouseEvent | KeyboardEvent) => void, focus: Day,
33
+ /** Called when the days on show change, so their items can be loaded. */
34
+ onShown: () => void);
35
+ /** The list scrolled or the grid moved: mark the day and keep it in view. */
36
+ setFocus(day: Day, range?: {
37
+ start: Day;
38
+ end: Day;
39
+ } | null): void;
40
+ /** Publishes the strip's height as `--tnc-strip-h`, for what sticks below it. */
41
+ measure(): void;
42
+ /** First day and end (exclusive) of the days on show. */
43
+ window(): {
44
+ start: Day;
45
+ end: Day;
46
+ };
47
+ setExpanded(on: boolean): void;
48
+ /** Highlights the day a dragged item would land on. */
49
+ markTarget(day: Day | null): void;
50
+ dayAt(el: Element): Day | null;
51
+ private step;
52
+ private days;
53
+ /** Redraws the cells; also called on every list render to refresh the dots. */
54
+ draw(): void;
55
+ private readonly onClick;
56
+ private readonly onKeyDown;
57
+ private readonly onPointerDown;
58
+ private readonly onPointerUp;
59
+ private readonly onPointerCancel;
60
+ /** A swipe that ends on a day is not a pick. */
61
+ private readonly onClickCapture;
62
+ destroy(): void;
63
+ }
@@ -0,0 +1,63 @@
1
+ import { type Day } from "../../core/date.js";
2
+ import type { ViewContext } from "../context.js";
3
+ /**
4
+ * A date strip above the agenda or a time grid: one week, or the whole month
5
+ * when expanded. Days with items carry a dot; the focus day (the top of the
6
+ * list, or the grid's first day) is marked, and the rest of a grid's range is
7
+ * tinted. Picking a day hands it to the calendar, and swipes step a week (or
8
+ * a month).
9
+ */
10
+ export declare class DateStrip<D> {
11
+ private readonly ctx;
12
+ private readonly pick;
13
+ /** Called when the days on show change, so their items can be loaded. */
14
+ private readonly onShown;
15
+ readonly el: HTMLElement;
16
+ private readonly title;
17
+ private readonly dows;
18
+ private readonly grid;
19
+ private readonly slot;
20
+ private readonly todayBtn;
21
+ /** Day at the top of the list. */
22
+ private focus;
23
+ /** First day of the week shown, or the month shown when expanded. */
24
+ private shown;
25
+ private target;
26
+ /** Days tinted as on screen besides the focus (a time grid's range). */
27
+ private range;
28
+ private shownKey;
29
+ private swipe;
30
+ private swallowClick;
31
+ expanded: boolean;
32
+ constructor(ctx: ViewContext<D>, pick: (day: Day, ev: MouseEvent | KeyboardEvent) => void, focus: Day,
33
+ /** Called when the days on show change, so their items can be loaded. */
34
+ onShown: () => void);
35
+ /** The list scrolled or the grid moved: mark the day and keep it in view. */
36
+ setFocus(day: Day, range?: {
37
+ start: Day;
38
+ end: Day;
39
+ } | null): void;
40
+ /** Publishes the strip's height as `--tnc-strip-h`, for what sticks below it. */
41
+ measure(): void;
42
+ /** First day and end (exclusive) of the days on show. */
43
+ window(): {
44
+ start: Day;
45
+ end: Day;
46
+ };
47
+ setExpanded(on: boolean): void;
48
+ /** Highlights the day a dragged item would land on. */
49
+ markTarget(day: Day | null): void;
50
+ dayAt(el: Element): Day | null;
51
+ private step;
52
+ private days;
53
+ /** Redraws the cells; also called on every list render to refresh the dots. */
54
+ draw(): void;
55
+ private readonly onClick;
56
+ private readonly onKeyDown;
57
+ private readonly onPointerDown;
58
+ private readonly onPointerUp;
59
+ private readonly onPointerCancel;
60
+ /** A swipe that ends on a day is not a pick. */
61
+ private readonly onClickCapture;
62
+ destroy(): void;
63
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tasknotes/calendar",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Task-native calendar engine for TaskNotes: incremental layout, time grid, month, list, year and timeline views.",
5
5
  "license": "MIT",
6
6
  "type": "module",