@tasknotes/calendar 0.1.0 → 0.1.2
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/CHANGELOG.md +18 -0
- package/dist/calendar.css +47 -1
- package/dist/cjs/index.cjs +47 -7
- package/dist/cjs/react.cjs +47 -7
- package/dist/esm/{chunk-UWCSL5AN.js → chunk-ZJQMMA6W.js} +47 -7
- package/dist/esm/index.js +1 -1
- package/dist/esm/react.js +1 -1
- package/dist/types/dom/calendar.d.cts +11 -2
- package/dist/types/dom/calendar.d.ts +11 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Year views narrower than 520px (phones, sidebars) show two compact months a row. Days are shaded by how busy they are, with no dots, and any day with items is visibly shaded.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Clicking or tapping a day in the year view reports it through `onDateClick`. Before, only Enter or Space on a focused day did.
|
|
12
|
+
- The calendar keeps its sticky headers and popovers in its own stacking context, so host overlays such as side sheets and dialogs draw above the week header and all-day row.
|
|
13
|
+
|
|
14
|
+
## 0.1.1
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Calendars moved into another window after creation (e.g. Obsidian "Move to new window") rebind their listeners, timers and observers to that window, so dragging, selection and resizing keep working. `adopt()` is also public for hosts that move a calendar programmatically.
|
|
19
|
+
- Time-grid day columns keep a minimum width (`--tnc-col-min`, 64px); narrow containers scroll sideways with the time axis pinned instead of crushing week views on phones.
|
|
20
|
+
|
|
3
21
|
## 0.1.0
|
|
4
22
|
|
|
5
23
|
Initial public release.
|
package/dist/calendar.css
CHANGED
|
@@ -32,12 +32,16 @@
|
|
|
32
32
|
--tnc-dot-size: 8px;
|
|
33
33
|
--tnc-dot-gap: 3px;
|
|
34
34
|
--tnc-gutter-w: 52px;
|
|
35
|
+
/* Narrowest a time-grid day column gets; narrower containers scroll sideways. */
|
|
36
|
+
--tnc-col-min: 64px;
|
|
35
37
|
--tnc-weeknum-w: 32px;
|
|
36
38
|
--tnc-dg-top-h: 24px;
|
|
37
39
|
--tnc-day-min-h: 92px;
|
|
38
40
|
--tnc-item-c: var(--tnc-accent);
|
|
39
41
|
|
|
40
42
|
position: relative;
|
|
43
|
+
/* Keep the calendar's own layers (sticky headers, popovers) below host overlays. */
|
|
44
|
+
isolation: isolate;
|
|
41
45
|
display: flex;
|
|
42
46
|
flex-direction: column;
|
|
43
47
|
min-height: 0;
|
|
@@ -462,6 +466,18 @@
|
|
|
462
466
|
display: grid;
|
|
463
467
|
grid-template-columns: var(--tnc-cols);
|
|
464
468
|
}
|
|
469
|
+
.tnc-tg-top,
|
|
470
|
+
.tnc-tg-body {
|
|
471
|
+
min-width: calc(var(--tnc-gutter-w) + var(--tnc-ncols, 1) * var(--tnc-col-min));
|
|
472
|
+
}
|
|
473
|
+
.tnc-gutter-head,
|
|
474
|
+
.tnc-gutter-label,
|
|
475
|
+
.tnc-gutter {
|
|
476
|
+
position: sticky;
|
|
477
|
+
left: 0;
|
|
478
|
+
z-index: 6;
|
|
479
|
+
background: var(--tnc-surface);
|
|
480
|
+
}
|
|
465
481
|
.tnc-gutter-head {
|
|
466
482
|
display: flex;
|
|
467
483
|
align-items: flex-end;
|
|
@@ -557,7 +573,6 @@
|
|
|
557
573
|
position: relative;
|
|
558
574
|
}
|
|
559
575
|
.tnc-gutter {
|
|
560
|
-
position: relative;
|
|
561
576
|
border-right: 1px solid var(--tnc-line);
|
|
562
577
|
}
|
|
563
578
|
.tnc-slot-label {
|
|
@@ -865,6 +880,8 @@
|
|
|
865
880
|
display: flex;
|
|
866
881
|
flex-direction: column;
|
|
867
882
|
min-height: 0;
|
|
883
|
+
/* Narrow calendars (phones, sidebars) use the compact year below. */
|
|
884
|
+
container-type: inline-size;
|
|
868
885
|
}
|
|
869
886
|
.tnc-year-scroll {
|
|
870
887
|
flex: 1 1 auto;
|
|
@@ -935,6 +952,35 @@
|
|
|
935
952
|
background: var(--tnc-c, var(--tnc-accent));
|
|
936
953
|
}
|
|
937
954
|
|
|
955
|
+
/* Two months a row: each day is a shaded square, and its count is in its label. */
|
|
956
|
+
@container (max-width: 520px) {
|
|
957
|
+
.tnc-year-scroll {
|
|
958
|
+
padding: 8px 4px;
|
|
959
|
+
}
|
|
960
|
+
.tnc-year-grid {
|
|
961
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
962
|
+
gap: 14px 12px;
|
|
963
|
+
}
|
|
964
|
+
.tnc-ym-title {
|
|
965
|
+
font-size: 12px;
|
|
966
|
+
padding-bottom: 4px;
|
|
967
|
+
}
|
|
968
|
+
.tnc-ym-days {
|
|
969
|
+
gap: 1px;
|
|
970
|
+
}
|
|
971
|
+
.tnc-ym-day {
|
|
972
|
+
border-radius: 4px;
|
|
973
|
+
font-size: 10px;
|
|
974
|
+
}
|
|
975
|
+
/* Without dots, one item must still read as busy. */
|
|
976
|
+
.tnc-ym-day.has-items {
|
|
977
|
+
background: color-mix(in srgb, var(--tnc-accent) calc((0.3 + var(--tnc-heat) * 0.7) * 50%), transparent);
|
|
978
|
+
}
|
|
979
|
+
.tnc-ym-dots {
|
|
980
|
+
display: none;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
938
984
|
/* -------------------------------------------------------------- timeline */
|
|
939
985
|
.tnc-tl {
|
|
940
986
|
display: flex;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1515,8 +1515,9 @@ var TimeGridView = class {
|
|
|
1515
1515
|
const { ctx } = this;
|
|
1516
1516
|
const { doc, opts, days, today } = ctx;
|
|
1517
1517
|
this.weights = days.map((d) => d === today && opts.todayWidth > 1 && days.length > 1 ? opts.todayWidth : 1);
|
|
1518
|
-
const tpl = `var(--tnc-gutter-w) ${this.weights.map((w) => `minmax(
|
|
1518
|
+
const tpl = `var(--tnc-gutter-w) ${this.weights.map((w) => `minmax(var(--tnc-col-min), ${w}fr)`).join(" ")}`;
|
|
1519
1519
|
this.el.style.setProperty("--tnc-cols", tpl);
|
|
1520
|
+
this.el.style.setProperty("--tnc-ncols", String(days.length));
|
|
1520
1521
|
const gutterHead = h(doc, "div", "tnc-gutter-head", { role: "columnheader" });
|
|
1521
1522
|
if (opts.weekNumbers && days[0] !== void 0) gutterHead.textContent = ctx.text.weekNumber(isoWeekNumber(days[0]));
|
|
1522
1523
|
this.headRow.replaceChildren(gutterHead);
|
|
@@ -2624,13 +2625,10 @@ var Calendar = class {
|
|
|
2624
2625
|
this.bindEvents();
|
|
2625
2626
|
this.rebuild(true);
|
|
2626
2627
|
this.scheduleTick();
|
|
2627
|
-
|
|
2628
|
-
if (RO) {
|
|
2629
|
-
this.resizeObs = new RO(() => this.current?.resize?.());
|
|
2630
|
-
this.resizeObs.observe(this.root);
|
|
2631
|
-
}
|
|
2628
|
+
this.observeResize();
|
|
2632
2629
|
}
|
|
2633
2630
|
host;
|
|
2631
|
+
/** The document/window the calendar currently lives in; see `adopt()`. */
|
|
2634
2632
|
doc;
|
|
2635
2633
|
win;
|
|
2636
2634
|
root;
|
|
@@ -2663,6 +2661,37 @@ var Calendar = class {
|
|
|
2663
2661
|
destroyed = false;
|
|
2664
2662
|
pendingChange = null;
|
|
2665
2663
|
frame = null;
|
|
2664
|
+
observeResize() {
|
|
2665
|
+
this.resizeObs?.disconnect();
|
|
2666
|
+
const RO = this.win.ResizeObserver;
|
|
2667
|
+
if (RO) {
|
|
2668
|
+
this.resizeObs = new RO(() => this.current?.resize?.());
|
|
2669
|
+
this.resizeObs.observe(this.root);
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
onAdoptCheck = () => {
|
|
2673
|
+
this.adopt();
|
|
2674
|
+
};
|
|
2675
|
+
/**
|
|
2676
|
+
* Hosts may move a live calendar into another window (e.g. Obsidian's
|
|
2677
|
+
* "Move to new window"). Listeners, timers and observers belong to a window,
|
|
2678
|
+
* so rebind them to the root's current document and rebuild the view there.
|
|
2679
|
+
*/
|
|
2680
|
+
adopt() {
|
|
2681
|
+
const doc = this.root.ownerDocument;
|
|
2682
|
+
if (this.destroyed || doc === this.doc || this.session) return;
|
|
2683
|
+
const old = this.win;
|
|
2684
|
+
if (this.timer !== null) old.clearTimeout(this.timer);
|
|
2685
|
+
if (this.frame !== null) old.cancelAnimationFrame(this.frame);
|
|
2686
|
+
this.timer = this.frame = null;
|
|
2687
|
+
this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true);
|
|
2688
|
+
this.doc = doc;
|
|
2689
|
+
this.win = doc.defaultView ?? old;
|
|
2690
|
+
this.doc.addEventListener("pointerdown", this.onDocPointerDown, true);
|
|
2691
|
+
this.observeResize();
|
|
2692
|
+
this.rebuild(false);
|
|
2693
|
+
this.scheduleTick();
|
|
2694
|
+
}
|
|
2666
2695
|
/* ================================================================ public */
|
|
2667
2696
|
/** Replaces all items, re-rendering only what changed. */
|
|
2668
2697
|
setItems(items) {
|
|
@@ -3227,6 +3256,7 @@ var Calendar = class {
|
|
|
3227
3256
|
applyChange(change) {
|
|
3228
3257
|
if (!change.added.length && !change.updated.length && !change.removed.length && !change.days.size && !change.spans) return;
|
|
3229
3258
|
this.conflicts = dependencyConflicts(this.store);
|
|
3259
|
+
this.adopt();
|
|
3230
3260
|
this.pendingChange = this.pendingChange ? this.merge(this.pendingChange, change) : change;
|
|
3231
3261
|
if (this.session?.active) {
|
|
3232
3262
|
this.flush();
|
|
@@ -3387,6 +3417,8 @@ var Calendar = class {
|
|
|
3387
3417
|
r.addEventListener("dragleave", this.onNativeDragLeave);
|
|
3388
3418
|
r.addEventListener("drop", this.onNativeDrop);
|
|
3389
3419
|
r.addEventListener("touchmove", this.onTouchMove, { passive: false });
|
|
3420
|
+
r.addEventListener("pointerover", this.onAdoptCheck);
|
|
3421
|
+
r.addEventListener("focusin", this.onAdoptCheck);
|
|
3390
3422
|
this.doc.addEventListener("pointerdown", this.onDocPointerDown, true);
|
|
3391
3423
|
}
|
|
3392
3424
|
unbindEvents() {
|
|
@@ -3403,6 +3435,8 @@ var Calendar = class {
|
|
|
3403
3435
|
r.removeEventListener("dragleave", this.onNativeDragLeave);
|
|
3404
3436
|
r.removeEventListener("drop", this.onNativeDrop);
|
|
3405
3437
|
r.removeEventListener("touchmove", this.onTouchMove);
|
|
3438
|
+
r.removeEventListener("pointerover", this.onAdoptCheck);
|
|
3439
|
+
r.removeEventListener("focusin", this.onAdoptCheck);
|
|
3406
3440
|
this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true);
|
|
3407
3441
|
this.listenDoc(false);
|
|
3408
3442
|
}
|
|
@@ -3900,6 +3934,12 @@ var Calendar = class {
|
|
|
3900
3934
|
ev.preventDefault();
|
|
3901
3935
|
};
|
|
3902
3936
|
onClick = (ev) => {
|
|
3937
|
+
const yearDay = ev.target.closest?.(".tnc-ym-day");
|
|
3938
|
+
if (yearDay && this.root.contains(yearDay)) {
|
|
3939
|
+
const day = parseDay(yearDay.dataset.date ?? "");
|
|
3940
|
+
if (day !== null) this.clickSlot({ kind: "day", day }, ev, true);
|
|
3941
|
+
return;
|
|
3942
|
+
}
|
|
3903
3943
|
const el = this.itemElFrom(ev.target);
|
|
3904
3944
|
if (!el || ev.target.closest(".tnc-resize, .tnc-port")) return;
|
|
3905
3945
|
const meta = this.meta.get(el);
|
|
@@ -3959,7 +3999,7 @@ var Calendar = class {
|
|
|
3959
3999
|
return;
|
|
3960
4000
|
}
|
|
3961
4001
|
const target = ev.target;
|
|
3962
|
-
if ((ev.key === "Enter" || ev.key === " ") && target.matches(".tnc-
|
|
4002
|
+
if ((ev.key === "Enter" || ev.key === " ") && target.matches(".tnc-dg-day[tabindex]")) {
|
|
3963
4003
|
const day = parseDay(target.dataset.date ?? "");
|
|
3964
4004
|
if (day !== null) {
|
|
3965
4005
|
ev.preventDefault();
|
package/dist/cjs/react.cjs
CHANGED
|
@@ -1423,8 +1423,9 @@ var TimeGridView = class {
|
|
|
1423
1423
|
const { ctx } = this;
|
|
1424
1424
|
const { doc, opts, days, today } = ctx;
|
|
1425
1425
|
this.weights = days.map((d) => d === today && opts.todayWidth > 1 && days.length > 1 ? opts.todayWidth : 1);
|
|
1426
|
-
const tpl = `var(--tnc-gutter-w) ${this.weights.map((w) => `minmax(
|
|
1426
|
+
const tpl = `var(--tnc-gutter-w) ${this.weights.map((w) => `minmax(var(--tnc-col-min), ${w}fr)`).join(" ")}`;
|
|
1427
1427
|
this.el.style.setProperty("--tnc-cols", tpl);
|
|
1428
|
+
this.el.style.setProperty("--tnc-ncols", String(days.length));
|
|
1428
1429
|
const gutterHead = h(doc, "div", "tnc-gutter-head", { role: "columnheader" });
|
|
1429
1430
|
if (opts.weekNumbers && days[0] !== void 0) gutterHead.textContent = ctx.text.weekNumber(isoWeekNumber(days[0]));
|
|
1430
1431
|
this.headRow.replaceChildren(gutterHead);
|
|
@@ -2532,13 +2533,10 @@ var Calendar = class {
|
|
|
2532
2533
|
this.bindEvents();
|
|
2533
2534
|
this.rebuild(true);
|
|
2534
2535
|
this.scheduleTick();
|
|
2535
|
-
|
|
2536
|
-
if (RO) {
|
|
2537
|
-
this.resizeObs = new RO(() => this.current?.resize?.());
|
|
2538
|
-
this.resizeObs.observe(this.root);
|
|
2539
|
-
}
|
|
2536
|
+
this.observeResize();
|
|
2540
2537
|
}
|
|
2541
2538
|
host;
|
|
2539
|
+
/** The document/window the calendar currently lives in; see `adopt()`. */
|
|
2542
2540
|
doc;
|
|
2543
2541
|
win;
|
|
2544
2542
|
root;
|
|
@@ -2571,6 +2569,37 @@ var Calendar = class {
|
|
|
2571
2569
|
destroyed = false;
|
|
2572
2570
|
pendingChange = null;
|
|
2573
2571
|
frame = null;
|
|
2572
|
+
observeResize() {
|
|
2573
|
+
this.resizeObs?.disconnect();
|
|
2574
|
+
const RO = this.win.ResizeObserver;
|
|
2575
|
+
if (RO) {
|
|
2576
|
+
this.resizeObs = new RO(() => this.current?.resize?.());
|
|
2577
|
+
this.resizeObs.observe(this.root);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
onAdoptCheck = () => {
|
|
2581
|
+
this.adopt();
|
|
2582
|
+
};
|
|
2583
|
+
/**
|
|
2584
|
+
* Hosts may move a live calendar into another window (e.g. Obsidian's
|
|
2585
|
+
* "Move to new window"). Listeners, timers and observers belong to a window,
|
|
2586
|
+
* so rebind them to the root's current document and rebuild the view there.
|
|
2587
|
+
*/
|
|
2588
|
+
adopt() {
|
|
2589
|
+
const doc = this.root.ownerDocument;
|
|
2590
|
+
if (this.destroyed || doc === this.doc || this.session) return;
|
|
2591
|
+
const old = this.win;
|
|
2592
|
+
if (this.timer !== null) old.clearTimeout(this.timer);
|
|
2593
|
+
if (this.frame !== null) old.cancelAnimationFrame(this.frame);
|
|
2594
|
+
this.timer = this.frame = null;
|
|
2595
|
+
this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true);
|
|
2596
|
+
this.doc = doc;
|
|
2597
|
+
this.win = doc.defaultView ?? old;
|
|
2598
|
+
this.doc.addEventListener("pointerdown", this.onDocPointerDown, true);
|
|
2599
|
+
this.observeResize();
|
|
2600
|
+
this.rebuild(false);
|
|
2601
|
+
this.scheduleTick();
|
|
2602
|
+
}
|
|
2574
2603
|
/* ================================================================ public */
|
|
2575
2604
|
/** Replaces all items, re-rendering only what changed. */
|
|
2576
2605
|
setItems(items) {
|
|
@@ -3135,6 +3164,7 @@ var Calendar = class {
|
|
|
3135
3164
|
applyChange(change) {
|
|
3136
3165
|
if (!change.added.length && !change.updated.length && !change.removed.length && !change.days.size && !change.spans) return;
|
|
3137
3166
|
this.conflicts = dependencyConflicts(this.store);
|
|
3167
|
+
this.adopt();
|
|
3138
3168
|
this.pendingChange = this.pendingChange ? this.merge(this.pendingChange, change) : change;
|
|
3139
3169
|
if (this.session?.active) {
|
|
3140
3170
|
this.flush();
|
|
@@ -3295,6 +3325,8 @@ var Calendar = class {
|
|
|
3295
3325
|
r.addEventListener("dragleave", this.onNativeDragLeave);
|
|
3296
3326
|
r.addEventListener("drop", this.onNativeDrop);
|
|
3297
3327
|
r.addEventListener("touchmove", this.onTouchMove, { passive: false });
|
|
3328
|
+
r.addEventListener("pointerover", this.onAdoptCheck);
|
|
3329
|
+
r.addEventListener("focusin", this.onAdoptCheck);
|
|
3298
3330
|
this.doc.addEventListener("pointerdown", this.onDocPointerDown, true);
|
|
3299
3331
|
}
|
|
3300
3332
|
unbindEvents() {
|
|
@@ -3311,6 +3343,8 @@ var Calendar = class {
|
|
|
3311
3343
|
r.removeEventListener("dragleave", this.onNativeDragLeave);
|
|
3312
3344
|
r.removeEventListener("drop", this.onNativeDrop);
|
|
3313
3345
|
r.removeEventListener("touchmove", this.onTouchMove);
|
|
3346
|
+
r.removeEventListener("pointerover", this.onAdoptCheck);
|
|
3347
|
+
r.removeEventListener("focusin", this.onAdoptCheck);
|
|
3314
3348
|
this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true);
|
|
3315
3349
|
this.listenDoc(false);
|
|
3316
3350
|
}
|
|
@@ -3808,6 +3842,12 @@ var Calendar = class {
|
|
|
3808
3842
|
ev.preventDefault();
|
|
3809
3843
|
};
|
|
3810
3844
|
onClick = (ev) => {
|
|
3845
|
+
const yearDay = ev.target.closest?.(".tnc-ym-day");
|
|
3846
|
+
if (yearDay && this.root.contains(yearDay)) {
|
|
3847
|
+
const day = parseDay(yearDay.dataset.date ?? "");
|
|
3848
|
+
if (day !== null) this.clickSlot({ kind: "day", day }, ev, true);
|
|
3849
|
+
return;
|
|
3850
|
+
}
|
|
3811
3851
|
const el = this.itemElFrom(ev.target);
|
|
3812
3852
|
if (!el || ev.target.closest(".tnc-resize, .tnc-port")) return;
|
|
3813
3853
|
const meta = this.meta.get(el);
|
|
@@ -3867,7 +3907,7 @@ var Calendar = class {
|
|
|
3867
3907
|
return;
|
|
3868
3908
|
}
|
|
3869
3909
|
const target = ev.target;
|
|
3870
|
-
if ((ev.key === "Enter" || ev.key === " ") && target.matches(".tnc-
|
|
3910
|
+
if ((ev.key === "Enter" || ev.key === " ") && target.matches(".tnc-dg-day[tabindex]")) {
|
|
3871
3911
|
const day = parseDay(target.dataset.date ?? "");
|
|
3872
3912
|
if (day !== null) {
|
|
3873
3913
|
ev.preventDefault();
|
|
@@ -817,8 +817,9 @@ var TimeGridView = class {
|
|
|
817
817
|
const { ctx } = this;
|
|
818
818
|
const { doc, opts, days, today } = ctx;
|
|
819
819
|
this.weights = days.map((d) => d === today && opts.todayWidth > 1 && days.length > 1 ? opts.todayWidth : 1);
|
|
820
|
-
const tpl = `var(--tnc-gutter-w) ${this.weights.map((w) => `minmax(
|
|
820
|
+
const tpl = `var(--tnc-gutter-w) ${this.weights.map((w) => `minmax(var(--tnc-col-min), ${w}fr)`).join(" ")}`;
|
|
821
821
|
this.el.style.setProperty("--tnc-cols", tpl);
|
|
822
|
+
this.el.style.setProperty("--tnc-ncols", String(days.length));
|
|
822
823
|
const gutterHead = h(doc, "div", "tnc-gutter-head", { role: "columnheader" });
|
|
823
824
|
if (opts.weekNumbers && days[0] !== void 0) gutterHead.textContent = ctx.text.weekNumber(isoWeekNumber(days[0]));
|
|
824
825
|
this.headRow.replaceChildren(gutterHead);
|
|
@@ -1926,13 +1927,10 @@ var Calendar = class {
|
|
|
1926
1927
|
this.bindEvents();
|
|
1927
1928
|
this.rebuild(true);
|
|
1928
1929
|
this.scheduleTick();
|
|
1929
|
-
|
|
1930
|
-
if (RO) {
|
|
1931
|
-
this.resizeObs = new RO(() => this.current?.resize?.());
|
|
1932
|
-
this.resizeObs.observe(this.root);
|
|
1933
|
-
}
|
|
1930
|
+
this.observeResize();
|
|
1934
1931
|
}
|
|
1935
1932
|
host;
|
|
1933
|
+
/** The document/window the calendar currently lives in; see `adopt()`. */
|
|
1936
1934
|
doc;
|
|
1937
1935
|
win;
|
|
1938
1936
|
root;
|
|
@@ -1965,6 +1963,37 @@ var Calendar = class {
|
|
|
1965
1963
|
destroyed = false;
|
|
1966
1964
|
pendingChange = null;
|
|
1967
1965
|
frame = null;
|
|
1966
|
+
observeResize() {
|
|
1967
|
+
this.resizeObs?.disconnect();
|
|
1968
|
+
const RO = this.win.ResizeObserver;
|
|
1969
|
+
if (RO) {
|
|
1970
|
+
this.resizeObs = new RO(() => this.current?.resize?.());
|
|
1971
|
+
this.resizeObs.observe(this.root);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
onAdoptCheck = () => {
|
|
1975
|
+
this.adopt();
|
|
1976
|
+
};
|
|
1977
|
+
/**
|
|
1978
|
+
* Hosts may move a live calendar into another window (e.g. Obsidian's
|
|
1979
|
+
* "Move to new window"). Listeners, timers and observers belong to a window,
|
|
1980
|
+
* so rebind them to the root's current document and rebuild the view there.
|
|
1981
|
+
*/
|
|
1982
|
+
adopt() {
|
|
1983
|
+
const doc = this.root.ownerDocument;
|
|
1984
|
+
if (this.destroyed || doc === this.doc || this.session) return;
|
|
1985
|
+
const old = this.win;
|
|
1986
|
+
if (this.timer !== null) old.clearTimeout(this.timer);
|
|
1987
|
+
if (this.frame !== null) old.cancelAnimationFrame(this.frame);
|
|
1988
|
+
this.timer = this.frame = null;
|
|
1989
|
+
this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true);
|
|
1990
|
+
this.doc = doc;
|
|
1991
|
+
this.win = doc.defaultView ?? old;
|
|
1992
|
+
this.doc.addEventListener("pointerdown", this.onDocPointerDown, true);
|
|
1993
|
+
this.observeResize();
|
|
1994
|
+
this.rebuild(false);
|
|
1995
|
+
this.scheduleTick();
|
|
1996
|
+
}
|
|
1968
1997
|
/* ================================================================ public */
|
|
1969
1998
|
/** Replaces all items, re-rendering only what changed. */
|
|
1970
1999
|
setItems(items) {
|
|
@@ -2529,6 +2558,7 @@ var Calendar = class {
|
|
|
2529
2558
|
applyChange(change) {
|
|
2530
2559
|
if (!change.added.length && !change.updated.length && !change.removed.length && !change.days.size && !change.spans) return;
|
|
2531
2560
|
this.conflicts = dependencyConflicts(this.store);
|
|
2561
|
+
this.adopt();
|
|
2532
2562
|
this.pendingChange = this.pendingChange ? this.merge(this.pendingChange, change) : change;
|
|
2533
2563
|
if (this.session?.active) {
|
|
2534
2564
|
this.flush();
|
|
@@ -2689,6 +2719,8 @@ var Calendar = class {
|
|
|
2689
2719
|
r.addEventListener("dragleave", this.onNativeDragLeave);
|
|
2690
2720
|
r.addEventListener("drop", this.onNativeDrop);
|
|
2691
2721
|
r.addEventListener("touchmove", this.onTouchMove, { passive: false });
|
|
2722
|
+
r.addEventListener("pointerover", this.onAdoptCheck);
|
|
2723
|
+
r.addEventListener("focusin", this.onAdoptCheck);
|
|
2692
2724
|
this.doc.addEventListener("pointerdown", this.onDocPointerDown, true);
|
|
2693
2725
|
}
|
|
2694
2726
|
unbindEvents() {
|
|
@@ -2705,6 +2737,8 @@ var Calendar = class {
|
|
|
2705
2737
|
r.removeEventListener("dragleave", this.onNativeDragLeave);
|
|
2706
2738
|
r.removeEventListener("drop", this.onNativeDrop);
|
|
2707
2739
|
r.removeEventListener("touchmove", this.onTouchMove);
|
|
2740
|
+
r.removeEventListener("pointerover", this.onAdoptCheck);
|
|
2741
|
+
r.removeEventListener("focusin", this.onAdoptCheck);
|
|
2708
2742
|
this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true);
|
|
2709
2743
|
this.listenDoc(false);
|
|
2710
2744
|
}
|
|
@@ -3202,6 +3236,12 @@ var Calendar = class {
|
|
|
3202
3236
|
ev.preventDefault();
|
|
3203
3237
|
};
|
|
3204
3238
|
onClick = (ev) => {
|
|
3239
|
+
const yearDay = ev.target.closest?.(".tnc-ym-day");
|
|
3240
|
+
if (yearDay && this.root.contains(yearDay)) {
|
|
3241
|
+
const day = parseDay(yearDay.dataset.date ?? "");
|
|
3242
|
+
if (day !== null) this.clickSlot({ kind: "day", day }, ev, true);
|
|
3243
|
+
return;
|
|
3244
|
+
}
|
|
3205
3245
|
const el = this.itemElFrom(ev.target);
|
|
3206
3246
|
if (!el || ev.target.closest(".tnc-resize, .tnc-port")) return;
|
|
3207
3247
|
const meta = this.meta.get(el);
|
|
@@ -3261,7 +3301,7 @@ var Calendar = class {
|
|
|
3261
3301
|
return;
|
|
3262
3302
|
}
|
|
3263
3303
|
const target = ev.target;
|
|
3264
|
-
if ((ev.key === "Enter" || ev.key === " ") && target.matches(".tnc-
|
|
3304
|
+
if ((ev.key === "Enter" || ev.key === " ") && target.matches(".tnc-dg-day[tabindex]")) {
|
|
3265
3305
|
const day = parseDay(target.dataset.date ?? "");
|
|
3266
3306
|
if (day !== null) {
|
|
3267
3307
|
ev.preventDefault();
|
package/dist/esm/index.js
CHANGED
package/dist/esm/react.js
CHANGED
|
@@ -12,8 +12,9 @@ import { type CalendarOptions, type CalendarText, type DayArg, type ExternalDrag
|
|
|
12
12
|
*/
|
|
13
13
|
export declare class Calendar<D = unknown> implements ViewContext<D> {
|
|
14
14
|
readonly host: HTMLElement;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
/** The document/window the calendar currently lives in; see `adopt()`. */
|
|
16
|
+
doc: Document;
|
|
17
|
+
win: Window;
|
|
17
18
|
readonly root: HTMLElement;
|
|
18
19
|
readonly store: ItemStore<D>;
|
|
19
20
|
readonly meta: WeakMap<Element, ElMeta<D>>;
|
|
@@ -54,6 +55,14 @@ export declare class Calendar<D = unknown> implements ViewContext<D> {
|
|
|
54
55
|
private pendingChange;
|
|
55
56
|
private frame;
|
|
56
57
|
constructor(host: HTMLElement, options?: Partial<CalendarOptions<D>>, items?: Iterable<CalendarItem<D>>);
|
|
58
|
+
private observeResize;
|
|
59
|
+
private readonly onAdoptCheck;
|
|
60
|
+
/**
|
|
61
|
+
* Hosts may move a live calendar into another window (e.g. Obsidian's
|
|
62
|
+
* "Move to new window"). Listeners, timers and observers belong to a window,
|
|
63
|
+
* so rebind them to the root's current document and rebuild the view there.
|
|
64
|
+
*/
|
|
65
|
+
adopt(): void;
|
|
57
66
|
/** Replaces all items, re-rendering only what changed. */
|
|
58
67
|
setItems(items: Iterable<CalendarItem<D>>): void;
|
|
59
68
|
upsertItems(items: Iterable<CalendarItem<D>>): void;
|
|
@@ -12,8 +12,9 @@ import { type CalendarOptions, type CalendarText, type DayArg, type ExternalDrag
|
|
|
12
12
|
*/
|
|
13
13
|
export declare class Calendar<D = unknown> implements ViewContext<D> {
|
|
14
14
|
readonly host: HTMLElement;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
/** The document/window the calendar currently lives in; see `adopt()`. */
|
|
16
|
+
doc: Document;
|
|
17
|
+
win: Window;
|
|
17
18
|
readonly root: HTMLElement;
|
|
18
19
|
readonly store: ItemStore<D>;
|
|
19
20
|
readonly meta: WeakMap<Element, ElMeta<D>>;
|
|
@@ -54,6 +55,14 @@ export declare class Calendar<D = unknown> implements ViewContext<D> {
|
|
|
54
55
|
private pendingChange;
|
|
55
56
|
private frame;
|
|
56
57
|
constructor(host: HTMLElement, options?: Partial<CalendarOptions<D>>, items?: Iterable<CalendarItem<D>>);
|
|
58
|
+
private observeResize;
|
|
59
|
+
private readonly onAdoptCheck;
|
|
60
|
+
/**
|
|
61
|
+
* Hosts may move a live calendar into another window (e.g. Obsidian's
|
|
62
|
+
* "Move to new window"). Listeners, timers and observers belong to a window,
|
|
63
|
+
* so rebind them to the root's current document and rebuild the view there.
|
|
64
|
+
*/
|
|
65
|
+
adopt(): void;
|
|
57
66
|
/** Replaces all items, re-rendering only what changed. */
|
|
58
67
|
setItems(items: Iterable<CalendarItem<D>>): void;
|
|
59
68
|
upsertItems(items: Iterable<CalendarItem<D>>): void;
|
package/package.json
CHANGED