@tasknotes/calendar 0.1.5 → 0.1.6
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 +8 -0
- package/dist/calendar.css +21 -19
- package/dist/cjs/core.cjs +19 -2
- package/dist/cjs/index.cjs +46 -12
- package/dist/cjs/react.cjs +46 -12
- package/dist/esm/{chunk-DVMZ5OXN.js → chunk-66A6EMCU.js} +19 -2
- package/dist/esm/{chunk-25TY2UVR.js → chunk-URE7QLU3.js} +28 -11
- package/dist/esm/core.js +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/react.js +2 -2
- package/dist/types/core/layout.d.cts +5 -0
- package/dist/types/core/layout.d.ts +5 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.6
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Time grids give tracked (`lane: "actual"`) items their narrow strip only where they overlap planned items. Elsewhere, planned and tracked items use the full column width, as before the side lane existed. The strip's width is the `--tnc-actual-w` custom property (default 22%).
|
|
8
|
+
- Reported by @RumiaKitinari in [TaskNotes issue 2494](https://github.com/callumalpass/tasknotes/issues/2494) and @mgreen3 in [TaskNotes issue 2498](https://github.com/callumalpass/tasknotes/issues/2498).
|
|
9
|
+
- The toolbar's previous and next buttons draw their chevrons as icons, which are larger and clearer than the ‹ › glyphs.
|
|
10
|
+
|
|
3
11
|
## 0.1.5
|
|
4
12
|
|
|
5
13
|
### Added
|
package/dist/calendar.css
CHANGED
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
--tnc-off: color-mix(in srgb, var(--tnc-text) 3.5%, transparent);
|
|
24
24
|
--tnc-shadow: 0 8px 24px rgb(0 0 0 / 0.16);
|
|
25
25
|
--tnc-radius: 6px;
|
|
26
|
+
/* Time-grid share for tracked ("actual") items where they overlap planned ones. */
|
|
27
|
+
--tnc-actual-w: 22%;
|
|
26
28
|
--tnc-font-size: 12px;
|
|
27
29
|
--tnc-small: 11px;
|
|
28
30
|
--tnc-bar-h: 20px;
|
|
@@ -131,9 +133,21 @@
|
|
|
131
133
|
}
|
|
132
134
|
.tnc-btn-prev,
|
|
133
135
|
.tnc-btn-next {
|
|
136
|
+
display: inline-flex;
|
|
137
|
+
align-items: center;
|
|
138
|
+
justify-content: center;
|
|
134
139
|
min-width: 28px;
|
|
135
140
|
padding: 3px 6px;
|
|
136
|
-
|
|
141
|
+
}
|
|
142
|
+
.tnc-btn-prev svg,
|
|
143
|
+
.tnc-btn-next svg {
|
|
144
|
+
width: 16px;
|
|
145
|
+
height: 16px;
|
|
146
|
+
fill: none;
|
|
147
|
+
stroke: currentColor;
|
|
148
|
+
stroke-width: 2;
|
|
149
|
+
stroke-linecap: round;
|
|
150
|
+
stroke-linejoin: round;
|
|
137
151
|
}
|
|
138
152
|
.tnc-btn:focus-visible,
|
|
139
153
|
.tnc-navlink:focus-visible,
|
|
@@ -612,31 +626,19 @@
|
|
|
612
626
|
.tnc-col.is-today {
|
|
613
627
|
background-color: color-mix(in srgb, var(--tnc-accent) 5%, transparent);
|
|
614
628
|
}
|
|
629
|
+
/* Items position themselves within the column; see inLane in timegrid.ts. */
|
|
615
630
|
.tnc-col-plan,
|
|
616
631
|
.tnc-col-bg,
|
|
617
632
|
.tnc-col-actual {
|
|
618
633
|
position: absolute;
|
|
619
|
-
|
|
620
|
-
bottom: 0;
|
|
621
|
-
}
|
|
622
|
-
.tnc-col-bg {
|
|
623
|
-
left: 0;
|
|
624
|
-
right: 0;
|
|
625
|
-
}
|
|
626
|
-
.tnc-col-plan {
|
|
627
|
-
left: 1px;
|
|
628
|
-
right: 8px;
|
|
634
|
+
inset: 0;
|
|
629
635
|
}
|
|
636
|
+
/* Above the plan layer, so it must not swallow clicks meant for plan items. */
|
|
630
637
|
.tnc-col-actual {
|
|
631
|
-
|
|
632
|
-
right: 2px;
|
|
633
|
-
width: 22%;
|
|
634
|
-
}
|
|
635
|
-
.tnc-col.has-actual .tnc-col-plan {
|
|
636
|
-
right: calc(22% + 4px);
|
|
638
|
+
pointer-events: none;
|
|
637
639
|
}
|
|
638
|
-
.tnc-col
|
|
639
|
-
|
|
640
|
+
.tnc-col-actual > * {
|
|
641
|
+
pointer-events: auto;
|
|
640
642
|
}
|
|
641
643
|
.tnc-now {
|
|
642
644
|
position: absolute;
|
package/dist/cjs/core.cjs
CHANGED
|
@@ -520,7 +520,7 @@ function packTimed(segs, minMinutes, order = defaultOrder) {
|
|
|
520
520
|
colEnds.push(0);
|
|
521
521
|
}
|
|
522
522
|
colEnds[col] = s.end;
|
|
523
|
-
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex };
|
|
523
|
+
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex, split: false };
|
|
524
524
|
cluster.push(p);
|
|
525
525
|
out.push(p);
|
|
526
526
|
clusterEnd = Math.max(clusterEnd, s.end);
|
|
@@ -540,7 +540,24 @@ function layoutTimedDay(items, day, zone, minMinutes, order, window = [0, MINUTE
|
|
|
540
540
|
else if (n.item.lane === "actual") actual.push(seg);
|
|
541
541
|
else plan.push(seg);
|
|
542
542
|
}
|
|
543
|
-
|
|
543
|
+
const planPlaced = packTimed(plan, minMinutes, order);
|
|
544
|
+
const actualPlaced = packTimed(actual, minMinutes, order);
|
|
545
|
+
markSplit(planPlaced, actualPlaced, minMinutes);
|
|
546
|
+
markSplit(actualPlaced, planPlaced, minMinutes);
|
|
547
|
+
return { day, plan: planPlaced, actual: actualPlaced, background };
|
|
548
|
+
}
|
|
549
|
+
function markSplit(lane, other, minMinutes) {
|
|
550
|
+
if (!lane.length || !other.length) return;
|
|
551
|
+
const end = (p) => Math.max(p.endMin, p.startMin + minMinutes);
|
|
552
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
553
|
+
for (const p of lane) {
|
|
554
|
+
const r = ranges.get(p.cluster);
|
|
555
|
+
if (r) r[1] = Math.max(r[1], end(p));
|
|
556
|
+
else ranges.set(p.cluster, [p.startMin, end(p)]);
|
|
557
|
+
}
|
|
558
|
+
const split = /* @__PURE__ */ new Set();
|
|
559
|
+
for (const [cluster, [s, e]] of ranges) if (other.some((o) => o.startMin < e && s < end(o))) split.add(cluster);
|
|
560
|
+
for (const p of lane) p.split = split.has(p.cluster);
|
|
544
561
|
}
|
|
545
562
|
function layoutRow(items, days, order = defaultOrder) {
|
|
546
563
|
const first = days[0];
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -532,7 +532,7 @@ function packTimed(segs, minMinutes, order = defaultOrder) {
|
|
|
532
532
|
colEnds.push(0);
|
|
533
533
|
}
|
|
534
534
|
colEnds[col] = s.end;
|
|
535
|
-
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex };
|
|
535
|
+
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex, split: false };
|
|
536
536
|
cluster.push(p);
|
|
537
537
|
out.push(p);
|
|
538
538
|
clusterEnd = Math.max(clusterEnd, s.end);
|
|
@@ -552,7 +552,24 @@ function layoutTimedDay(items, day, zone, minMinutes, order, window = [0, MINUTE
|
|
|
552
552
|
else if (n.item.lane === "actual") actual.push(seg);
|
|
553
553
|
else plan.push(seg);
|
|
554
554
|
}
|
|
555
|
-
|
|
555
|
+
const planPlaced = packTimed(plan, minMinutes, order);
|
|
556
|
+
const actualPlaced = packTimed(actual, minMinutes, order);
|
|
557
|
+
markSplit(planPlaced, actualPlaced, minMinutes);
|
|
558
|
+
markSplit(actualPlaced, planPlaced, minMinutes);
|
|
559
|
+
return { day, plan: planPlaced, actual: actualPlaced, background };
|
|
560
|
+
}
|
|
561
|
+
function markSplit(lane, other, minMinutes) {
|
|
562
|
+
if (!lane.length || !other.length) return;
|
|
563
|
+
const end = (p) => Math.max(p.endMin, p.startMin + minMinutes);
|
|
564
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
565
|
+
for (const p of lane) {
|
|
566
|
+
const r = ranges.get(p.cluster);
|
|
567
|
+
if (r) r[1] = Math.max(r[1], end(p));
|
|
568
|
+
else ranges.set(p.cluster, [p.startMin, end(p)]);
|
|
569
|
+
}
|
|
570
|
+
const split = /* @__PURE__ */ new Set();
|
|
571
|
+
for (const [cluster, [s, e]] of ranges) if (other.some((o) => o.startMin < e && s < end(o))) split.add(cluster);
|
|
572
|
+
for (const p of lane) p.split = split.has(p.cluster);
|
|
556
573
|
}
|
|
557
574
|
function layoutRow(items, days, order = defaultOrder) {
|
|
558
575
|
const first = days[0];
|
|
@@ -1794,6 +1811,11 @@ var DateStrip = class {
|
|
|
1794
1811
|
|
|
1795
1812
|
// src/dom/views/timegrid.ts
|
|
1796
1813
|
var BAR_GAP2 = 2;
|
|
1814
|
+
function inLane(lane, split, left, width) {
|
|
1815
|
+
const [x, w] = !split ? ["1px", "100% - 9px"] : lane === "plan" ? ["1px", "100% - var(--tnc-actual-w) - 5px"] : ["100% - var(--tnc-actual-w) - 2px", "var(--tnc-actual-w)"];
|
|
1816
|
+
const f = (n) => Math.round(n * 1e4) / 1e4;
|
|
1817
|
+
return { left: `calc(${x} + (${w}) * ${f(left)})`, width: `calc((${w}) * ${f(width)} - 1px)` };
|
|
1818
|
+
}
|
|
1797
1819
|
var TimeGridView = class {
|
|
1798
1820
|
constructor(ctx) {
|
|
1799
1821
|
this.ctx = ctx;
|
|
@@ -2103,19 +2125,20 @@ var TimeGridView = class {
|
|
|
2103
2125
|
c.bg.end();
|
|
2104
2126
|
const hasActual = layout.actual.length > 0;
|
|
2105
2127
|
c.col.classList.toggle("has-actual", hasActual);
|
|
2106
|
-
this.placeLane(c.plan, layout.plan, c, top, height,
|
|
2107
|
-
this.placeLane(c.actual, layout.actual, c, top, height,
|
|
2128
|
+
this.placeLane(c.plan, layout.plan, c, top, height, "plan");
|
|
2129
|
+
this.placeLane(c.actual, layout.actual, c, top, height, "actual");
|
|
2108
2130
|
}
|
|
2109
|
-
placeLane(pool, placements, c, top, height,
|
|
2131
|
+
placeLane(pool, placements, c, top, height, lane) {
|
|
2110
2132
|
const { ctx } = this;
|
|
2111
2133
|
const { opts } = ctx;
|
|
2134
|
+
const withMore = lane === "plan";
|
|
2112
2135
|
const maxStack = opts.eventMaxStack;
|
|
2113
2136
|
const hiddenByCluster = /* @__PURE__ */ new Map();
|
|
2114
2137
|
pool.begin();
|
|
2115
2138
|
for (const p of placements) {
|
|
2116
2139
|
const preview = p.item.item.preview || p.item.id === ctx.draggingId;
|
|
2117
2140
|
if (!preview && withMore && maxStack > 0 && p.cols > maxStack && p.col >= maxStack - 1) {
|
|
2118
|
-
const rec = hiddenByCluster.get(p.cluster) ?? { count: 0, start: p.startMin, end: p.endMin, items: [] };
|
|
2141
|
+
const rec = hiddenByCluster.get(p.cluster) ?? { count: 0, start: p.startMin, end: p.endMin, split: p.split, items: [] };
|
|
2119
2142
|
rec.count++;
|
|
2120
2143
|
rec.start = Math.min(rec.start, p.startMin);
|
|
2121
2144
|
rec.end = Math.max(rec.end, p.endMin);
|
|
@@ -2134,8 +2157,7 @@ var TimeGridView = class {
|
|
|
2134
2157
|
setStyle(el, {
|
|
2135
2158
|
top: top(p.startMin),
|
|
2136
2159
|
height: `max(${height(p)}, ${opts.eventMinHeight}px)`,
|
|
2137
|
-
left
|
|
2138
|
-
width: `calc(${pct(width)} - 1px)`,
|
|
2160
|
+
...inLane(lane, p.split, left, width),
|
|
2139
2161
|
"z-index": String(p.col + 1)
|
|
2140
2162
|
});
|
|
2141
2163
|
}
|
|
@@ -2147,8 +2169,7 @@ var TimeGridView = class {
|
|
|
2147
2169
|
const cols = maxStack;
|
|
2148
2170
|
setStyle(link, {
|
|
2149
2171
|
top: top(rec.start),
|
|
2150
|
-
|
|
2151
|
-
width: `calc(${pct(1 / cols)} - 1px)`
|
|
2172
|
+
...inLane(lane, rec.split, (cols - 1) / cols, 1 / cols)
|
|
2152
2173
|
});
|
|
2153
2174
|
link.addEventListener("click", (ev) => ctx.openMore(c.day, link, ev));
|
|
2154
2175
|
c.more.append(link);
|
|
@@ -2934,6 +2955,7 @@ ${this.ctx.text.more(items.length - 8)}` : ""}` : label;
|
|
|
2934
2955
|
|
|
2935
2956
|
// src/dom/calendar.ts
|
|
2936
2957
|
var EXTERNAL_ID = "__tnc_external__";
|
|
2958
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2937
2959
|
var MAX_AGENDA_DAYS = 366;
|
|
2938
2960
|
function sameOption(a, b, depth = 0) {
|
|
2939
2961
|
if (a === b) return true;
|
|
@@ -3702,14 +3724,26 @@ var Calendar = class {
|
|
|
3702
3724
|
if (e.icon) b.replaceChildren(e.icon());
|
|
3703
3725
|
return b;
|
|
3704
3726
|
});
|
|
3727
|
+
const chevron = (d) => {
|
|
3728
|
+
const svg = this.doc.createElementNS(SVG_NS, "svg");
|
|
3729
|
+
setAttrs(svg, { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" });
|
|
3730
|
+
const path = this.doc.createElementNS(SVG_NS, "path");
|
|
3731
|
+
path.setAttribute("d", d);
|
|
3732
|
+
svg.append(path);
|
|
3733
|
+
return svg;
|
|
3734
|
+
};
|
|
3735
|
+
const prev = btn("", this.text.prev, "tnc-btn-prev", () => this.prev());
|
|
3736
|
+
prev.append(chevron("m15 18-6-6 6-6"));
|
|
3737
|
+
const next = btn("", this.text.next, "tnc-btn-next", () => this.next());
|
|
3738
|
+
next.append(chevron("m9 18 6-6-6-6"));
|
|
3705
3739
|
const nav = h(
|
|
3706
3740
|
this.doc,
|
|
3707
3741
|
"div",
|
|
3708
3742
|
"tnc-toolbar-group tnc-toolbar-nav",
|
|
3709
3743
|
null,
|
|
3710
|
-
|
|
3744
|
+
prev,
|
|
3711
3745
|
btn(this.text.today, this.text.today, "tnc-btn-today", () => this.goToday()),
|
|
3712
|
-
|
|
3746
|
+
next
|
|
3713
3747
|
);
|
|
3714
3748
|
const title = h(this.doc, "h2", "tnc-title", { "aria-live": "polite" }, this.view.title);
|
|
3715
3749
|
const viewGroup = h(this.doc, "div", "tnc-toolbar-group tnc-toolbar-views", { role: "group" });
|
package/dist/cjs/react.cjs
CHANGED
|
@@ -859,7 +859,7 @@ function packTimed(segs, minMinutes, order = defaultOrder) {
|
|
|
859
859
|
colEnds.push(0);
|
|
860
860
|
}
|
|
861
861
|
colEnds[col] = s.end;
|
|
862
|
-
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex };
|
|
862
|
+
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex, split: false };
|
|
863
863
|
cluster.push(p);
|
|
864
864
|
out.push(p);
|
|
865
865
|
clusterEnd = Math.max(clusterEnd, s.end);
|
|
@@ -879,7 +879,24 @@ function layoutTimedDay(items, day, zone, minMinutes, order, window = [0, MINUTE
|
|
|
879
879
|
else if (n.item.lane === "actual") actual.push(seg);
|
|
880
880
|
else plan.push(seg);
|
|
881
881
|
}
|
|
882
|
-
|
|
882
|
+
const planPlaced = packTimed(plan, minMinutes, order);
|
|
883
|
+
const actualPlaced = packTimed(actual, minMinutes, order);
|
|
884
|
+
markSplit(planPlaced, actualPlaced, minMinutes);
|
|
885
|
+
markSplit(actualPlaced, planPlaced, minMinutes);
|
|
886
|
+
return { day, plan: planPlaced, actual: actualPlaced, background };
|
|
887
|
+
}
|
|
888
|
+
function markSplit(lane, other, minMinutes) {
|
|
889
|
+
if (!lane.length || !other.length) return;
|
|
890
|
+
const end = (p) => Math.max(p.endMin, p.startMin + minMinutes);
|
|
891
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
892
|
+
for (const p of lane) {
|
|
893
|
+
const r = ranges.get(p.cluster);
|
|
894
|
+
if (r) r[1] = Math.max(r[1], end(p));
|
|
895
|
+
else ranges.set(p.cluster, [p.startMin, end(p)]);
|
|
896
|
+
}
|
|
897
|
+
const split = /* @__PURE__ */ new Set();
|
|
898
|
+
for (const [cluster, [s, e]] of ranges) if (other.some((o) => o.startMin < e && s < end(o))) split.add(cluster);
|
|
899
|
+
for (const p of lane) p.split = split.has(p.cluster);
|
|
883
900
|
}
|
|
884
901
|
function layoutRow(items, days, order = defaultOrder) {
|
|
885
902
|
const first = days[0];
|
|
@@ -1702,6 +1719,11 @@ var DateStrip = class {
|
|
|
1702
1719
|
|
|
1703
1720
|
// src/dom/views/timegrid.ts
|
|
1704
1721
|
var BAR_GAP2 = 2;
|
|
1722
|
+
function inLane(lane, split, left, width) {
|
|
1723
|
+
const [x, w] = !split ? ["1px", "100% - 9px"] : lane === "plan" ? ["1px", "100% - var(--tnc-actual-w) - 5px"] : ["100% - var(--tnc-actual-w) - 2px", "var(--tnc-actual-w)"];
|
|
1724
|
+
const f = (n) => Math.round(n * 1e4) / 1e4;
|
|
1725
|
+
return { left: `calc(${x} + (${w}) * ${f(left)})`, width: `calc((${w}) * ${f(width)} - 1px)` };
|
|
1726
|
+
}
|
|
1705
1727
|
var TimeGridView = class {
|
|
1706
1728
|
constructor(ctx) {
|
|
1707
1729
|
this.ctx = ctx;
|
|
@@ -2011,19 +2033,20 @@ var TimeGridView = class {
|
|
|
2011
2033
|
c.bg.end();
|
|
2012
2034
|
const hasActual = layout.actual.length > 0;
|
|
2013
2035
|
c.col.classList.toggle("has-actual", hasActual);
|
|
2014
|
-
this.placeLane(c.plan, layout.plan, c, top, height,
|
|
2015
|
-
this.placeLane(c.actual, layout.actual, c, top, height,
|
|
2036
|
+
this.placeLane(c.plan, layout.plan, c, top, height, "plan");
|
|
2037
|
+
this.placeLane(c.actual, layout.actual, c, top, height, "actual");
|
|
2016
2038
|
}
|
|
2017
|
-
placeLane(pool, placements, c, top, height,
|
|
2039
|
+
placeLane(pool, placements, c, top, height, lane) {
|
|
2018
2040
|
const { ctx } = this;
|
|
2019
2041
|
const { opts } = ctx;
|
|
2042
|
+
const withMore = lane === "plan";
|
|
2020
2043
|
const maxStack = opts.eventMaxStack;
|
|
2021
2044
|
const hiddenByCluster = /* @__PURE__ */ new Map();
|
|
2022
2045
|
pool.begin();
|
|
2023
2046
|
for (const p of placements) {
|
|
2024
2047
|
const preview = p.item.item.preview || p.item.id === ctx.draggingId;
|
|
2025
2048
|
if (!preview && withMore && maxStack > 0 && p.cols > maxStack && p.col >= maxStack - 1) {
|
|
2026
|
-
const rec = hiddenByCluster.get(p.cluster) ?? { count: 0, start: p.startMin, end: p.endMin, items: [] };
|
|
2049
|
+
const rec = hiddenByCluster.get(p.cluster) ?? { count: 0, start: p.startMin, end: p.endMin, split: p.split, items: [] };
|
|
2027
2050
|
rec.count++;
|
|
2028
2051
|
rec.start = Math.min(rec.start, p.startMin);
|
|
2029
2052
|
rec.end = Math.max(rec.end, p.endMin);
|
|
@@ -2042,8 +2065,7 @@ var TimeGridView = class {
|
|
|
2042
2065
|
setStyle(el, {
|
|
2043
2066
|
top: top(p.startMin),
|
|
2044
2067
|
height: `max(${height(p)}, ${opts.eventMinHeight}px)`,
|
|
2045
|
-
left
|
|
2046
|
-
width: `calc(${pct(width)} - 1px)`,
|
|
2068
|
+
...inLane(lane, p.split, left, width),
|
|
2047
2069
|
"z-index": String(p.col + 1)
|
|
2048
2070
|
});
|
|
2049
2071
|
}
|
|
@@ -2055,8 +2077,7 @@ var TimeGridView = class {
|
|
|
2055
2077
|
const cols = maxStack;
|
|
2056
2078
|
setStyle(link, {
|
|
2057
2079
|
top: top(rec.start),
|
|
2058
|
-
|
|
2059
|
-
width: `calc(${pct(1 / cols)} - 1px)`
|
|
2080
|
+
...inLane(lane, rec.split, (cols - 1) / cols, 1 / cols)
|
|
2060
2081
|
});
|
|
2061
2082
|
link.addEventListener("click", (ev) => ctx.openMore(c.day, link, ev));
|
|
2062
2083
|
c.more.append(link);
|
|
@@ -2842,6 +2863,7 @@ ${this.ctx.text.more(items.length - 8)}` : ""}` : label;
|
|
|
2842
2863
|
|
|
2843
2864
|
// src/dom/calendar.ts
|
|
2844
2865
|
var EXTERNAL_ID = "__tnc_external__";
|
|
2866
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2845
2867
|
var MAX_AGENDA_DAYS = 366;
|
|
2846
2868
|
function sameOption(a, b, depth = 0) {
|
|
2847
2869
|
if (a === b) return true;
|
|
@@ -3610,14 +3632,26 @@ var Calendar = class {
|
|
|
3610
3632
|
if (e.icon) b.replaceChildren(e.icon());
|
|
3611
3633
|
return b;
|
|
3612
3634
|
});
|
|
3635
|
+
const chevron = (d) => {
|
|
3636
|
+
const svg = this.doc.createElementNS(SVG_NS, "svg");
|
|
3637
|
+
setAttrs(svg, { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" });
|
|
3638
|
+
const path = this.doc.createElementNS(SVG_NS, "path");
|
|
3639
|
+
path.setAttribute("d", d);
|
|
3640
|
+
svg.append(path);
|
|
3641
|
+
return svg;
|
|
3642
|
+
};
|
|
3643
|
+
const prev = btn("", this.text.prev, "tnc-btn-prev", () => this.prev());
|
|
3644
|
+
prev.append(chevron("m15 18-6-6 6-6"));
|
|
3645
|
+
const next = btn("", this.text.next, "tnc-btn-next", () => this.next());
|
|
3646
|
+
next.append(chevron("m9 18 6-6-6-6"));
|
|
3613
3647
|
const nav = h(
|
|
3614
3648
|
this.doc,
|
|
3615
3649
|
"div",
|
|
3616
3650
|
"tnc-toolbar-group tnc-toolbar-nav",
|
|
3617
3651
|
null,
|
|
3618
|
-
|
|
3652
|
+
prev,
|
|
3619
3653
|
btn(this.text.today, this.text.today, "tnc-btn-today", () => this.goToday()),
|
|
3620
|
-
|
|
3654
|
+
next
|
|
3621
3655
|
);
|
|
3622
3656
|
const title = h(this.doc, "h2", "tnc-title", { "aria-live": "polite" }, this.view.title);
|
|
3623
3657
|
const viewGroup = h(this.doc, "div", "tnc-toolbar-group tnc-toolbar-views", { role: "group" });
|
|
@@ -455,7 +455,7 @@ function packTimed(segs, minMinutes, order = defaultOrder) {
|
|
|
455
455
|
colEnds.push(0);
|
|
456
456
|
}
|
|
457
457
|
colEnds[col] = s.end;
|
|
458
|
-
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex };
|
|
458
|
+
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex, split: false };
|
|
459
459
|
cluster.push(p);
|
|
460
460
|
out.push(p);
|
|
461
461
|
clusterEnd = Math.max(clusterEnd, s.end);
|
|
@@ -475,7 +475,24 @@ function layoutTimedDay(items, day, zone, minMinutes, order, window = [0, MINUTE
|
|
|
475
475
|
else if (n.item.lane === "actual") actual.push(seg);
|
|
476
476
|
else plan.push(seg);
|
|
477
477
|
}
|
|
478
|
-
|
|
478
|
+
const planPlaced = packTimed(plan, minMinutes, order);
|
|
479
|
+
const actualPlaced = packTimed(actual, minMinutes, order);
|
|
480
|
+
markSplit(planPlaced, actualPlaced, minMinutes);
|
|
481
|
+
markSplit(actualPlaced, planPlaced, minMinutes);
|
|
482
|
+
return { day, plan: planPlaced, actual: actualPlaced, background };
|
|
483
|
+
}
|
|
484
|
+
function markSplit(lane, other, minMinutes) {
|
|
485
|
+
if (!lane.length || !other.length) return;
|
|
486
|
+
const end = (p) => Math.max(p.endMin, p.startMin + minMinutes);
|
|
487
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
488
|
+
for (const p of lane) {
|
|
489
|
+
const r = ranges.get(p.cluster);
|
|
490
|
+
if (r) r[1] = Math.max(r[1], end(p));
|
|
491
|
+
else ranges.set(p.cluster, [p.startMin, end(p)]);
|
|
492
|
+
}
|
|
493
|
+
const split = /* @__PURE__ */ new Set();
|
|
494
|
+
for (const [cluster, [s, e]] of ranges) if (other.some((o) => o.startMin < e && s < end(o))) split.add(cluster);
|
|
495
|
+
for (const p of lane) p.split = split.has(p.cluster);
|
|
479
496
|
}
|
|
480
497
|
function layoutRow(items, days, order = defaultOrder) {
|
|
481
498
|
const first = days[0];
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
wallTime,
|
|
28
28
|
weekdayOf,
|
|
29
29
|
ymdOfDay
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-66A6EMCU.js";
|
|
31
31
|
|
|
32
32
|
// src/dom/format.ts
|
|
33
33
|
var Formatter = class {
|
|
@@ -1096,6 +1096,11 @@ var DateStrip = class {
|
|
|
1096
1096
|
|
|
1097
1097
|
// src/dom/views/timegrid.ts
|
|
1098
1098
|
var BAR_GAP2 = 2;
|
|
1099
|
+
function inLane(lane, split, left, width) {
|
|
1100
|
+
const [x, w] = !split ? ["1px", "100% - 9px"] : lane === "plan" ? ["1px", "100% - var(--tnc-actual-w) - 5px"] : ["100% - var(--tnc-actual-w) - 2px", "var(--tnc-actual-w)"];
|
|
1101
|
+
const f = (n) => Math.round(n * 1e4) / 1e4;
|
|
1102
|
+
return { left: `calc(${x} + (${w}) * ${f(left)})`, width: `calc((${w}) * ${f(width)} - 1px)` };
|
|
1103
|
+
}
|
|
1099
1104
|
var TimeGridView = class {
|
|
1100
1105
|
constructor(ctx) {
|
|
1101
1106
|
this.ctx = ctx;
|
|
@@ -1405,19 +1410,20 @@ var TimeGridView = class {
|
|
|
1405
1410
|
c.bg.end();
|
|
1406
1411
|
const hasActual = layout.actual.length > 0;
|
|
1407
1412
|
c.col.classList.toggle("has-actual", hasActual);
|
|
1408
|
-
this.placeLane(c.plan, layout.plan, c, top, height,
|
|
1409
|
-
this.placeLane(c.actual, layout.actual, c, top, height,
|
|
1413
|
+
this.placeLane(c.plan, layout.plan, c, top, height, "plan");
|
|
1414
|
+
this.placeLane(c.actual, layout.actual, c, top, height, "actual");
|
|
1410
1415
|
}
|
|
1411
|
-
placeLane(pool, placements, c, top, height,
|
|
1416
|
+
placeLane(pool, placements, c, top, height, lane) {
|
|
1412
1417
|
const { ctx } = this;
|
|
1413
1418
|
const { opts } = ctx;
|
|
1419
|
+
const withMore = lane === "plan";
|
|
1414
1420
|
const maxStack = opts.eventMaxStack;
|
|
1415
1421
|
const hiddenByCluster = /* @__PURE__ */ new Map();
|
|
1416
1422
|
pool.begin();
|
|
1417
1423
|
for (const p of placements) {
|
|
1418
1424
|
const preview = p.item.item.preview || p.item.id === ctx.draggingId;
|
|
1419
1425
|
if (!preview && withMore && maxStack > 0 && p.cols > maxStack && p.col >= maxStack - 1) {
|
|
1420
|
-
const rec = hiddenByCluster.get(p.cluster) ?? { count: 0, start: p.startMin, end: p.endMin, items: [] };
|
|
1426
|
+
const rec = hiddenByCluster.get(p.cluster) ?? { count: 0, start: p.startMin, end: p.endMin, split: p.split, items: [] };
|
|
1421
1427
|
rec.count++;
|
|
1422
1428
|
rec.start = Math.min(rec.start, p.startMin);
|
|
1423
1429
|
rec.end = Math.max(rec.end, p.endMin);
|
|
@@ -1436,8 +1442,7 @@ var TimeGridView = class {
|
|
|
1436
1442
|
setStyle(el, {
|
|
1437
1443
|
top: top(p.startMin),
|
|
1438
1444
|
height: `max(${height(p)}, ${opts.eventMinHeight}px)`,
|
|
1439
|
-
left
|
|
1440
|
-
width: `calc(${pct(width)} - 1px)`,
|
|
1445
|
+
...inLane(lane, p.split, left, width),
|
|
1441
1446
|
"z-index": String(p.col + 1)
|
|
1442
1447
|
});
|
|
1443
1448
|
}
|
|
@@ -1449,8 +1454,7 @@ var TimeGridView = class {
|
|
|
1449
1454
|
const cols = maxStack;
|
|
1450
1455
|
setStyle(link, {
|
|
1451
1456
|
top: top(rec.start),
|
|
1452
|
-
|
|
1453
|
-
width: `calc(${pct(1 / cols)} - 1px)`
|
|
1457
|
+
...inLane(lane, rec.split, (cols - 1) / cols, 1 / cols)
|
|
1454
1458
|
});
|
|
1455
1459
|
link.addEventListener("click", (ev) => ctx.openMore(c.day, link, ev));
|
|
1456
1460
|
c.more.append(link);
|
|
@@ -2236,6 +2240,7 @@ ${this.ctx.text.more(items.length - 8)}` : ""}` : label;
|
|
|
2236
2240
|
|
|
2237
2241
|
// src/dom/calendar.ts
|
|
2238
2242
|
var EXTERNAL_ID = "__tnc_external__";
|
|
2243
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2239
2244
|
var MAX_AGENDA_DAYS = 366;
|
|
2240
2245
|
function sameOption(a, b, depth = 0) {
|
|
2241
2246
|
if (a === b) return true;
|
|
@@ -3004,14 +3009,26 @@ var Calendar = class {
|
|
|
3004
3009
|
if (e.icon) b.replaceChildren(e.icon());
|
|
3005
3010
|
return b;
|
|
3006
3011
|
});
|
|
3012
|
+
const chevron = (d) => {
|
|
3013
|
+
const svg = this.doc.createElementNS(SVG_NS, "svg");
|
|
3014
|
+
setAttrs(svg, { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" });
|
|
3015
|
+
const path = this.doc.createElementNS(SVG_NS, "path");
|
|
3016
|
+
path.setAttribute("d", d);
|
|
3017
|
+
svg.append(path);
|
|
3018
|
+
return svg;
|
|
3019
|
+
};
|
|
3020
|
+
const prev = btn("", this.text.prev, "tnc-btn-prev", () => this.prev());
|
|
3021
|
+
prev.append(chevron("m15 18-6-6 6-6"));
|
|
3022
|
+
const next = btn("", this.text.next, "tnc-btn-next", () => this.next());
|
|
3023
|
+
next.append(chevron("m9 18 6-6-6-6"));
|
|
3007
3024
|
const nav = h(
|
|
3008
3025
|
this.doc,
|
|
3009
3026
|
"div",
|
|
3010
3027
|
"tnc-toolbar-group tnc-toolbar-nav",
|
|
3011
3028
|
null,
|
|
3012
|
-
|
|
3029
|
+
prev,
|
|
3013
3030
|
btn(this.text.today, this.text.today, "tnc-btn-today", () => this.goToday()),
|
|
3014
|
-
|
|
3031
|
+
next
|
|
3015
3032
|
);
|
|
3016
3033
|
const title = h(this.doc, "h2", "tnc-title", { "aria-live": "polite" }, this.view.title);
|
|
3017
3034
|
const viewGroup = h(this.doc, "div", "tnc-toolbar-group tnc-toolbar-views", { role: "group" });
|
package/dist/esm/core.js
CHANGED
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-
|
|
10
|
+
} from "./chunk-URE7QLU3.js";
|
|
11
11
|
import {
|
|
12
12
|
DAY_MS,
|
|
13
13
|
ItemStore,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
wallTime,
|
|
50
50
|
weekdayOf,
|
|
51
51
|
ymdOfDay
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-66A6EMCU.js";
|
|
53
53
|
|
|
54
54
|
// src/tasknotes/bases.ts
|
|
55
55
|
var FROM_BASES = {
|
package/dist/esm/react.js
CHANGED
|
@@ -19,6 +19,11 @@ export interface TimedPlacement<D = unknown> extends TimedSegment<D> {
|
|
|
19
19
|
span: number;
|
|
20
20
|
/** Index of the overlap cluster within the day. */
|
|
21
21
|
cluster: number;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the cluster overlaps an item in the other lane (plan vs actual).
|
|
24
|
+
* Only then does the item keep to its lane's share of the column.
|
|
25
|
+
*/
|
|
26
|
+
split: boolean;
|
|
22
27
|
}
|
|
23
28
|
export interface TimedDayLayout<D = unknown> {
|
|
24
29
|
day: Day;
|
|
@@ -19,6 +19,11 @@ export interface TimedPlacement<D = unknown> extends TimedSegment<D> {
|
|
|
19
19
|
span: number;
|
|
20
20
|
/** Index of the overlap cluster within the day. */
|
|
21
21
|
cluster: number;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the cluster overlaps an item in the other lane (plan vs actual).
|
|
24
|
+
* Only then does the item keep to its lane's share of the column.
|
|
25
|
+
*/
|
|
26
|
+
split: boolean;
|
|
22
27
|
}
|
|
23
28
|
export interface TimedDayLayout<D = unknown> {
|
|
24
29
|
day: Day;
|
package/package.json
CHANGED