@tasknotes/calendar 0.0.0-stage → 0.1.1

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.
Files changed (56) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +163 -2
  4. package/dist/calendar.css +1358 -0
  5. package/dist/cjs/core.cjs +716 -0
  6. package/dist/cjs/index.cjs +4240 -0
  7. package/dist/cjs/react.cjs +4068 -0
  8. package/dist/esm/chunk-6RRDNLZM.js +3435 -0
  9. package/dist/esm/chunk-DVMZ5OXN.js +694 -0
  10. package/dist/esm/chunk-L4WKZ6WT.js +0 -0
  11. package/dist/esm/core.js +85 -0
  12. package/dist/esm/index.js +223 -0
  13. package/dist/esm/react.js +46 -0
  14. package/dist/types/core/date.d.cts +30 -0
  15. package/dist/types/core/date.d.ts +30 -0
  16. package/dist/types/core/index.d.cts +7 -0
  17. package/dist/types/core/index.d.ts +7 -0
  18. package/dist/types/core/layout.d.cts +82 -0
  19. package/dist/types/core/layout.d.ts +82 -0
  20. package/dist/types/core/order.d.cts +7 -0
  21. package/dist/types/core/order.d.ts +7 -0
  22. package/dist/types/core/plan.d.cts +42 -0
  23. package/dist/types/core/plan.d.ts +42 -0
  24. package/dist/types/core/store.d.cts +60 -0
  25. package/dist/types/core/store.d.ts +60 -0
  26. package/dist/types/core/types.d.cts +69 -0
  27. package/dist/types/core/types.d.ts +69 -0
  28. package/dist/types/core/zone.d.cts +43 -0
  29. package/dist/types/core/zone.d.ts +43 -0
  30. package/dist/types/dom/calendar.d.cts +215 -0
  31. package/dist/types/dom/calendar.d.ts +215 -0
  32. package/dist/types/dom/context.d.cts +107 -0
  33. package/dist/types/dom/context.d.ts +107 -0
  34. package/dist/types/dom/dom.d.cts +8 -0
  35. package/dist/types/dom/dom.d.ts +8 -0
  36. package/dist/types/dom/format.d.cts +30 -0
  37. package/dist/types/dom/format.d.ts +30 -0
  38. package/dist/types/dom/options.d.cts +401 -0
  39. package/dist/types/dom/options.d.ts +401 -0
  40. package/dist/types/dom/views/daygrid.d.cts +42 -0
  41. package/dist/types/dom/views/daygrid.d.ts +42 -0
  42. package/dist/types/dom/views/list.d.cts +27 -0
  43. package/dist/types/dom/views/list.d.ts +27 -0
  44. package/dist/types/dom/views/timegrid.d.cts +54 -0
  45. package/dist/types/dom/views/timegrid.d.ts +54 -0
  46. package/dist/types/dom/views/timeline.d.cts +83 -0
  47. package/dist/types/dom/views/timeline.d.ts +83 -0
  48. package/dist/types/dom/views/year.d.cts +26 -0
  49. package/dist/types/dom/views/year.d.ts +26 -0
  50. package/dist/types/index.d.cts +6 -0
  51. package/dist/types/index.d.ts +6 -0
  52. package/dist/types/react/index.d.cts +20 -0
  53. package/dist/types/react/index.d.ts +20 -0
  54. package/dist/types/tasknotes/bases.d.cts +50 -0
  55. package/dist/types/tasknotes/bases.d.ts +50 -0
  56. package/package.json +108 -5
@@ -0,0 +1,401 @@
1
+ import type { Day } from "../core/date.cjs";
2
+ import type { ItemOrder } from "../core/layout.cjs";
3
+ import type { CalendarItem, DateInput, DateRange, DependencyType } from "../core/types.cjs";
4
+ /**
5
+ * How an item element is drawn: "timed" (time-grid block), "bar" (all-day or
6
+ * multi-day bar), "dot" (timed item in a day cell), "indicator" (a dot in a
7
+ * `monthDisplay: "dots"` cell), "list" (list-view row) or "timeline" (timeline bar).
8
+ */
9
+ export type ItemVariant = "timed" | "bar" | "dot" | "indicator" | "list" | "timeline";
10
+ export type ViewType = "week" | "day" | "days" | "month" | "list" | "year" | "timeline";
11
+ export interface ViewInfo {
12
+ type: ViewType;
13
+ range: DateRange;
14
+ /** Anchor date the view was built around. */
15
+ anchor: Day;
16
+ title: string;
17
+ }
18
+ /** Where a pointer is over the calendar. */
19
+ export type Hit = {
20
+ kind: "time";
21
+ day: Day;
22
+ minute: number;
23
+ } | {
24
+ kind: "allDay";
25
+ day: Day;
26
+ } | {
27
+ kind: "day";
28
+ day: Day;
29
+ } | {
30
+ kind: "timeline";
31
+ /** Row under the pointer (group rows included); null over the header, or below the last row. */
32
+ rowId: string | null;
33
+ day: Day;
34
+ minute: number;
35
+ area: TimelineArea;
36
+ /** Over a non-group row's track: where an item can be placed in a row. */
37
+ overTrack: boolean;
38
+ };
39
+ /**
40
+ * Part of the timeline under the pointer. "outside" is inside the chart but
41
+ * past the rows or the date range; points outside the chart hit nothing.
42
+ */
43
+ export type TimelineArea = "track" | "header" | "label" | "outside";
44
+ export interface ItemArg<D> {
45
+ item: CalendarItem<D>;
46
+ el: HTMLElement;
47
+ view: ViewInfo;
48
+ /** Day this element represents (items crossing midnight have one element per day). */
49
+ day: Day;
50
+ isStart: boolean;
51
+ isEnd: boolean;
52
+ isMirror: boolean;
53
+ variant: ItemVariant;
54
+ /**
55
+ * Time label in the calendar's locale and hour format: "9am – 10:30am" for
56
+ * timed, list and timeline items; the start ("9am") for bars and dots, and
57
+ * only on the day the item starts. Empty for all-day items.
58
+ */
59
+ timeText: string;
60
+ }
61
+ export interface ItemPointerArg<D> extends ItemArg<D> {
62
+ jsEvent: MouseEvent | KeyboardEvent;
63
+ }
64
+ export interface ItemChangeArg<D> {
65
+ item: CalendarItem<D>;
66
+ start: Date;
67
+ end: Date;
68
+ allDay: boolean;
69
+ /** `start` / `end` as stored by TaskNotes: "YYYY-MM-DD" or "YYYY-MM-DDTHH:mm" in the calendar zone. */
70
+ startStr: string;
71
+ endStr: string;
72
+ oldStart: Date;
73
+ oldEnd: Date;
74
+ oldAllDay: boolean;
75
+ /** Change in start, in ms. */
76
+ delta: number;
77
+ /** Row the item was dropped on (timeline view). */
78
+ rowId?: string;
79
+ jsEvent: PointerEvent | KeyboardEvent | null;
80
+ /** How the change was made. Modifier keys only mean "copy" for pointer drops. */
81
+ source: "pointer" | "keyboard";
82
+ view: ViewInfo;
83
+ /** Puts the item back where it was. Called automatically if the handler's promise rejects. */
84
+ revert: () => void;
85
+ }
86
+ export interface SelectArg {
87
+ start: Date;
88
+ end: Date;
89
+ allDay: boolean;
90
+ startStr: string;
91
+ endStr: string;
92
+ jsEvent: PointerEvent | KeyboardEvent | null;
93
+ view: ViewInfo;
94
+ rowId?: string;
95
+ }
96
+ export interface ExternalDragSource<D = unknown> {
97
+ title: string;
98
+ /** Defaults to `defaultTimedMinutes`. */
99
+ durationMinutes?: number;
100
+ color?: string;
101
+ kind?: string;
102
+ data?: D;
103
+ }
104
+ export interface ExternalDropArg<D> extends SelectArg {
105
+ source: ExternalDragSource<D> | null;
106
+ /** Where the drop landed; in the timeline this says whether it was over a row, a heading or the date header. */
107
+ hit: Hit | null;
108
+ /** Set for native (HTML5) drops. */
109
+ dataTransfer: DataTransfer | null;
110
+ }
111
+ export interface DayArg {
112
+ date: Date;
113
+ day: Day;
114
+ dateStr: string;
115
+ view: ViewInfo;
116
+ isToday: boolean;
117
+ isPast: boolean;
118
+ }
119
+ export interface DateClickArg extends DayArg {
120
+ /** Wall-clock minute of the clicked slot, snapped to `slotDuration`; null for day cells and the all-day row. */
121
+ minute: number | null;
122
+ allDay: boolean;
123
+ /** "YYYY-MM-DD" for all-day clicks, "YYYY-MM-DDTHH:mm" for slots. */
124
+ startStr: string;
125
+ jsEvent: MouseEvent | KeyboardEvent;
126
+ }
127
+ export interface DayHeaderArg extends DayArg {
128
+ el: HTMLElement;
129
+ }
130
+ export interface MoreArg<D> {
131
+ day: Day;
132
+ date: Date;
133
+ items: CalendarItem<D>[];
134
+ hidden: CalendarItem<D>[];
135
+ jsEvent: MouseEvent | KeyboardEvent;
136
+ el: HTMLElement;
137
+ view: ViewInfo;
138
+ }
139
+ export interface TimelineRow {
140
+ id: string;
141
+ title: string;
142
+ /** Indent level for nested rows. */
143
+ depth?: number;
144
+ /** Group rows are headings and do not take drops. */
145
+ group?: boolean;
146
+ color?: string;
147
+ collapsed?: boolean;
148
+ }
149
+ export interface TimelineScale {
150
+ /** Width of one `unit` in px. */
151
+ unitWidth: number;
152
+ /** Width of one day in px. Overrides `unitWidth`; the unit then only picks the header ticks. */
153
+ dayWidth?: number;
154
+ unit: "hour" | "day" | "week" | "month" | "quarter";
155
+ /** Drag snap in minutes. */
156
+ snapMinutes: number;
157
+ }
158
+ /** Days in one timeline scale unit, used to turn `unitWidth` into a day width. */
159
+ export declare const TIMELINE_UNIT_DAYS: Readonly<Record<TimelineScale["unit"], number>>;
160
+ export type LinkEdge = "start" | "finish";
161
+ export interface LinkArg<D> {
162
+ from: CalendarItem<D>;
163
+ to: CalendarItem<D>;
164
+ fromEdge: LinkEdge;
165
+ toEdge: LinkEdge;
166
+ /** `fromEdge` and `toEdge` as a relationship type. */
167
+ type: DependencyType;
168
+ }
169
+ /** A link drag in progress. `to` is the bar or link handle under the pointer. */
170
+ export interface LinkDragArg<D> {
171
+ phase: "start" | "over" | "end";
172
+ from: CalendarItem<D>;
173
+ fromEdge: LinkEdge;
174
+ to: CalendarItem<D> | null;
175
+ toEdge: LinkEdge | null;
176
+ type: DependencyType | null;
177
+ /** False when `canLink` refused the target. */
178
+ valid: boolean;
179
+ /** Reason returned by `canLink`. */
180
+ reason: string | null;
181
+ /** On "end": whether `onLink` fired. */
182
+ linked: boolean;
183
+ }
184
+ export interface TimelineRowArg {
185
+ row: TimelineRow;
186
+ /** The row's label cell. Content placed here is yours until `rowLabelWillUnmount`. */
187
+ el: HTMLElement;
188
+ }
189
+ export interface TimelineOptions<D> {
190
+ rows: TimelineRow[];
191
+ /** Row an item is drawn in. Items without a row are not drawn. */
192
+ rowOf: (item: CalendarItem<D>) => string | null | undefined;
193
+ scale?: Partial<TimelineScale>;
194
+ /** Days shown, starting at the anchor. Default 120. */
195
+ days?: number;
196
+ /** Days before the anchor to show. Default 14. */
197
+ leadDays?: number;
198
+ labelWidth?: number;
199
+ rowHeight?: number;
200
+ /** Draw `dependsOn` arrows. */
201
+ dependencies?: boolean;
202
+ /** Fills a row label. Prefer `rowLabelDidMount`, which pairs with `rowLabelWillUnmount`. */
203
+ rowContent?: (row: TimelineRow, el: HTMLElement) => void;
204
+ /**
205
+ * A row's label cell was created. Mount your content (a React portal, say)
206
+ * into `el`; the calendar leaves it alone and suppresses the click that ends
207
+ * a drag before it reaches listeners inside.
208
+ */
209
+ rowLabelDidMount?: (arg: TimelineRowArg) => void;
210
+ /** A row's label cell is about to be removed. */
211
+ rowLabelWillUnmount?: (arg: TimelineRowArg) => void;
212
+ /**
213
+ * Fires when the user drags from a bar's start or finish handle to another
214
+ * bar. Dropping on a handle picks that edge; dropping on the bar picks the
215
+ * nearer edge (a milestone's body counts as its start).
216
+ */
217
+ onLink?: (arg: LinkArg<D>) => void;
218
+ /** Return false or a reason to refuse a link target while dragging. */
219
+ canLink?: (arg: LinkArg<D>) => boolean | string;
220
+ /** Reports a link drag as it starts, changes target and ends. */
221
+ onLinkDrag?: (arg: LinkDragArg<D>) => void;
222
+ /** Label shown on the today line, e.g. "Today". */
223
+ todayLabel?: string;
224
+ /**
225
+ * Makes bar resize handles focusable buttons with this label. Arrow keys on a
226
+ * focused handle move that edge by the snap.
227
+ */
228
+ resizeHandleLabel?: (arg: {
229
+ item: CalendarItem<D>;
230
+ edge: LinkEdge;
231
+ }) => string;
232
+ onRowClick?: (row: TimelineRow, jsEvent: MouseEvent) => void;
233
+ }
234
+ /**
235
+ * Pins a timeline instant to a screen position across `setOptions`: the
236
+ * instant under `clientX`, or `date` at `clientX` (or where `date` is now).
237
+ */
238
+ export type TimelineAnchor = {
239
+ clientX: number;
240
+ date?: DateInput;
241
+ } | {
242
+ date: DateInput;
243
+ clientX?: number;
244
+ };
245
+ export interface ToolbarButton {
246
+ id: string;
247
+ text: string;
248
+ hint?: string;
249
+ icon?: () => Node;
250
+ onClick: (ev: MouseEvent) => void;
251
+ }
252
+ export interface ToolbarOptions {
253
+ /** View buttons, in order. */
254
+ views?: ViewType[];
255
+ extraButtons?: ToolbarButton[];
256
+ /** Extra buttons go before prev/next ("start") or after the view buttons ("end"). */
257
+ extraPlacement?: "start" | "end";
258
+ }
259
+ export interface CalendarText {
260
+ today: string;
261
+ prev: string;
262
+ next: string;
263
+ allDay: string;
264
+ noItems: string;
265
+ more: (n: number) => string;
266
+ /** Day-cell label suffix in `monthDisplay: "dots"`. */
267
+ itemCount: (n: number) => string;
268
+ weekNumber: (n: number) => string;
269
+ views: Partial<Record<ViewType, string>>;
270
+ viewHints: Partial<Record<ViewType, string>>;
271
+ }
272
+ export interface CalendarOptions<D = unknown> {
273
+ view: ViewType;
274
+ /** Date the view is built around. */
275
+ date: DateInput;
276
+ /** Columns for the "days" view. */
277
+ dayCount: number;
278
+ /** Days in the "list" view. */
279
+ listDayCount: number;
280
+ /**
281
+ * Where the "list" view starts: at the date ("date", FullCalendar's
282
+ * `duration: { days: n }` lists, as the TaskNotes plugin used), or at the
283
+ * start of its week ("week", like FullCalendar's stock `listWeek`).
284
+ */
285
+ listStart: "date" | "week";
286
+ /**
287
+ * Month cells: "full" draws bars and titled entries; "dots" draws every
288
+ * item as a small dot that wraps across the cell, with a "+N" count when
289
+ * they do not fit (`dayMaxEvents` caps the dots). In "dots" the day cell is
290
+ * the tap target: dots ignore the pointer and are hidden from assistive
291
+ * technology, and the cell is labelled with its item count.
292
+ */
293
+ monthDisplay: "full" | "dots";
294
+ /** "local" or an IANA name. */
295
+ timeZone: string;
296
+ locale: string | undefined;
297
+ /** 0 = Sunday. Defaults to the locale's first day. */
298
+ firstDay: number | undefined;
299
+ /** undefined = locale default. */
300
+ hour12: boolean | undefined;
301
+ weekNumbers: boolean;
302
+ weekends: boolean;
303
+ hiddenDays: number[];
304
+ allDaySlot: boolean;
305
+ /** False hides the timed part of time-grid views, leaving the all-day row. */
306
+ timeGrid: boolean;
307
+ todayHighlight: boolean;
308
+ /** Width of today's column relative to other columns (week and days views). */
309
+ todayWidth: number;
310
+ slotMinTime: string | number;
311
+ slotMaxTime: string | number;
312
+ slotDuration: string | number;
313
+ snapDuration: string | number | undefined;
314
+ scrollTime: string | number;
315
+ /** Pixel height of one slot. */
316
+ slotHeight: number;
317
+ /** Stretch slots to fill the available height ("fill" mode only). */
318
+ expandRows: boolean;
319
+ nowIndicator: boolean;
320
+ selectMirror: boolean;
321
+ slotEventOverlap: boolean;
322
+ /** Minimum item height in px in time grids. */
323
+ eventMinHeight: number;
324
+ /** Max side-by-side items in a time-grid cluster before "+N". 0 = unlimited. */
325
+ eventMaxStack: number;
326
+ /** Day cells: true = as many as fit, number = max items, false = unlimited. */
327
+ dayMaxEvents: boolean | number;
328
+ /** Day cells: max rows including the "+N more" link. 0 = unlimited. */
329
+ dayMaxEventRows: number;
330
+ eventOrder: string | ItemOrder<D>;
331
+ /** "fill" takes the host's height and scrolls inside; "auto" grows with content. */
332
+ height: "fill" | "auto";
333
+ editable: boolean;
334
+ selectable: boolean;
335
+ navLinks: boolean;
336
+ resizableFromStart: boolean;
337
+ longPressDelay: number;
338
+ defaultTimedMinutes: number;
339
+ defaultAllDayDays: number;
340
+ /** Shows a bar per day of planned minutes against this capacity. */
341
+ capacityMinutes: number | ((day: Day) => number) | null;
342
+ /** Draw due-style milestones and dependency warnings. */
343
+ planning: boolean;
344
+ toolbar: boolean | ToolbarOptions;
345
+ text: Partial<CalendarText>;
346
+ timeline: TimelineOptions<D> | null;
347
+ /** Accept native HTML5 drops (e.g. files). */
348
+ acceptNativeDrop: ((dt: DataTransfer) => boolean) | null;
349
+ /** Ids of selected items: they get `is-selected`, and in the timeline show their link handles on touch. */
350
+ selected: string | readonly string[] | null;
351
+ onRangeChange?: (view: ViewInfo) => void;
352
+ onViewChange?: (view: ViewInfo) => void;
353
+ onItemClick?: (arg: ItemPointerArg<D>) => void;
354
+ onItemDoubleClick?: (arg: ItemPointerArg<D>) => void;
355
+ onItemContextMenu?: (arg: ItemPointerArg<D>) => void;
356
+ onItemHover?: (arg: ItemPointerArg<D> & {
357
+ entering: boolean;
358
+ }) => void;
359
+ onItemDrop?: (arg: ItemChangeArg<D>) => void | Promise<unknown>;
360
+ onItemResize?: (arg: ItemChangeArg<D>) => void | Promise<unknown>;
361
+ /** Return false to forbid a drop target. */
362
+ canDrop?: (arg: {
363
+ item: CalendarItem<D>;
364
+ start: Date;
365
+ end: Date;
366
+ allDay: boolean;
367
+ rowId?: string;
368
+ }) => boolean;
369
+ onSelect?: (arg: SelectArg) => void;
370
+ onUnselect?: () => void;
371
+ /** A tap or click on a day cell, the all-day row or a time slot (without dragging). */
372
+ onDateClick?: (arg: DateClickArg) => void;
373
+ /** Date links: day headers and numbers (`target: "day"`), year-view month titles (`"month"`). Default switches to that view. */
374
+ onNavLink?: (arg: DayArg & {
375
+ target: "day" | "month";
376
+ jsEvent: MouseEvent | KeyboardEvent;
377
+ }) => void;
378
+ onExternalDrop?: (arg: ExternalDropArg<D>) => void;
379
+ /** Fires when a `beginExternalDrag` drag ends, dropped or not. */
380
+ onExternalDragEnd?: (arg: {
381
+ source: ExternalDragSource<D>;
382
+ dropped: boolean;
383
+ hit: Hit | null;
384
+ jsEvent: PointerEvent | null;
385
+ }) => void;
386
+ /** Return false to skip the built-in popover. */
387
+ onMoreClick?: (arg: MoreArg<D>) => boolean | void;
388
+ itemContent?: (arg: ItemArg<D>) => Node | string | null | undefined;
389
+ itemClassNames?: (arg: ItemArg<D>) => string[] | string | undefined;
390
+ itemDidMount?: (arg: ItemArg<D>) => void;
391
+ itemWillUnmount?: (arg: ItemArg<D>) => void;
392
+ /** Replaces a list-view row's content. */
393
+ listItemContent?: (arg: ItemArg<D>) => Node | null | undefined;
394
+ dayHeaderContent?: (arg: DayArg) => Node | string | null | undefined;
395
+ dayHeaderDidMount?: (arg: DayHeaderArg) => void;
396
+ dayClassNames?: (arg: DayArg) => string[] | string | undefined;
397
+ }
398
+ export declare const DEFAULT_TEXT: CalendarText;
399
+ export declare function defaultOptions<D>(): CalendarOptions<D>;
400
+ /** Options keys that require a full view rebuild rather than an item refresh. */
401
+ export declare const LAYOUT_KEYS: Set<keyof CalendarOptions<unknown>>;