@tasknotes/calendar 0.1.8 → 0.1.11
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 +23 -1
- package/README.md +1 -0
- package/dist/calendar.css +62 -2
- package/dist/cjs/core.cjs +20 -26
- package/dist/cjs/index.cjs +225 -53
- package/dist/cjs/react.cjs +221 -53
- package/dist/esm/{chunk-66A6EMCU.js → chunk-JWORVABV.js} +20 -26
- package/dist/esm/{chunk-EXKFHPW2.js → chunk-TTM45UAN.js} +202 -28
- package/dist/esm/core.js +1 -1
- package/dist/esm/index.js +6 -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/dist/types/dom/calendar.d.cts +8 -0
- package/dist/types/dom/calendar.d.ts +8 -0
- package/dist/types/dom/format.d.cts +2 -1
- package/dist/types/dom/format.d.ts +2 -1
- package/dist/types/dom/options.d.cts +6 -0
- package/dist/types/dom/options.d.ts +6 -0
- package/dist/types/dom/views/daygrid.d.cts +2 -0
- package/dist/types/dom/views/daygrid.d.ts +2 -0
- package/dist/types/dom/views/list.d.cts +1 -0
- package/dist/types/dom/views/list.d.ts +1 -0
- package/dist/types/dom/views/strip.d.cts +3 -1
- package/dist/types/dom/views/strip.d.ts +3 -1
- package/dist/types/dom/views/timegrid.d.cts +4 -1
- package/dist/types/dom/views/timegrid.d.ts +4 -1
- package/dist/types/tasknotes/bases.d.cts +2 -0
- package/dist/types/tasknotes/bases.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.1.11
|
|
4
|
+
|
|
5
|
+
- Hour-long timed items keep their time in narrow columns. Only single-row short items drop the time label when narrow; in the stacked layout the title is clamped to the lines left above the time (callumalpass/tasknotes#2528).
|
|
6
|
+
- Back-to-back timed items no longer count as overlapping: an item starting exactly where a short item ends stays in the same column instead of going side by side or into a collision stack, and the short item is drawn at its real height (callumalpass/tasknotes#2529).
|
|
7
|
+
|
|
8
|
+
## 0.1.10
|
|
9
|
+
|
|
10
|
+
- Freeze Month source layout during a move and draw an inert target placeholder; preserve timed drag width across collision layouts.
|
|
11
|
+
- Contain date-strip touch gestures, reveal the complete target month in Year view, and allow dense collision stacks independently of the overlap preference.
|
|
12
|
+
- Require a short pause at a drag edge before scrolling, so passing through the edge does not shift the grid. Cancellation still restores the original scroll position.
|
|
13
|
+
- Keep the whole requested hour label visible below the sticky day and all-day headers when scrolling to a time.
|
|
14
|
+
- Agenda strip paging moves the list to the focused day; scrollbar and keyboard scrolling update the date highlight after a day is picked. Activity dots show up to three appointments in their configured colours.
|
|
15
|
+
- Hosts can supply one wall-clock `formatTime` callback for event, stack, selection, accessibility and slot labels.
|
|
16
|
+
- Hosts can set `overlapStackThreshold` to group dense overlapping appointments into the existing collision stack even in wide columns. Explicit side-by-side layouts remain unchanged.
|
|
17
|
+
|
|
18
|
+
## 0.1.9
|
|
19
|
+
|
|
20
|
+
Not published to npm (the release check failed); these changes ship in 0.1.10.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- Pinching a time grid on touch rescales its slots around the time under the fingers. `onSlotHeightChange` reports the settled height for hosts to store, and `pinchZoom: false` turns the gesture off.
|
|
25
|
+
- `basesLayoutOptions` reads `slotHeight` and `pinchZoom` from Bases calendar settings.
|
|
4
26
|
|
|
5
27
|
## 0.1.8
|
|
6
28
|
|
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ The host persists changes; the calendar supplies optimistic updates and a
|
|
|
46
46
|
- **Changes** (`onItemDrop`, `onItemResize`, `onSelect`, `onExternalDrop`) report TaskNotes storage strings (`startStr`/`endStr`), `revert()`, and `source: "pointer" | "keyboard"`. Returning a rejected promise reverts.
|
|
47
47
|
- **Clicks**: `onDateClick` reports `minute` (the slot's wall-clock minute, snapped to `slotDuration`; null for day cells and the all-day row), `allDay` and `startStr` (`"YYYY-MM-DD"` or `"YYYY-MM-DDTHH:mm"`), so a tap on a slot can prefill a time.
|
|
48
48
|
- **Input**: mouse drag after 4px, touch long press (`longPressDelay`), keyboard (Enter/Space, Shift+F10, Alt+Arrow to move, Alt+Shift+Arrow to resize), external drags via `beginExternalDrag` or native HTML5 drops.
|
|
49
|
+
- **Pinch**: two fingers on a time grid rescale `slotHeight` between 16 and 96px, keeping the time under the fingers in place. `onSlotHeightChange` reports the settled height for the host to store; `pinchZoom: false` leaves the gesture to the browser.
|
|
49
50
|
- **Popouts**: all listeners, timers and observers use the host element's `ownerDocument`; bare `window`/`document` are lint errors in `src`.
|
|
50
51
|
|
|
51
52
|
### Views and options
|
package/dist/calendar.css
CHANGED
|
@@ -293,8 +293,42 @@
|
|
|
293
293
|
.tnc-item--timed.is-short .tnc-item-time {
|
|
294
294
|
flex: none;
|
|
295
295
|
}
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
/* Stacked layout: the time keeps its line and the title gets the lines left over
|
|
297
|
+
(11px text: n title lines need 13.75 * (n + 1) + 1px). Single-row short items drop the time when narrow. */
|
|
298
|
+
.tnc-item--timed:not(.is-short) .tnc-item-title {
|
|
299
|
+
flex: 0 1 auto;
|
|
300
|
+
min-height: 0;
|
|
301
|
+
}
|
|
302
|
+
.tnc-item--timed:not(.is-short) .tnc-item-time {
|
|
303
|
+
flex: none;
|
|
304
|
+
}
|
|
305
|
+
@container (max-height: 97.2px) {
|
|
306
|
+
.tnc-item--timed:not(.is-short) .tnc-item-title {
|
|
307
|
+
-webkit-line-clamp: 5;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
@container (max-height: 83.4px) {
|
|
311
|
+
.tnc-item--timed:not(.is-short) .tnc-item-title {
|
|
312
|
+
-webkit-line-clamp: 4;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
@container (max-height: 69.7px) {
|
|
316
|
+
.tnc-item--timed:not(.is-short) .tnc-item-title {
|
|
317
|
+
-webkit-line-clamp: 3;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
@container (max-height: 55.9px) {
|
|
321
|
+
.tnc-item--timed:not(.is-short) .tnc-item-title {
|
|
322
|
+
-webkit-line-clamp: 2;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
@container (max-height: 42.2px) {
|
|
326
|
+
.tnc-item--timed:not(.is-short) .tnc-item-title {
|
|
327
|
+
-webkit-line-clamp: 1;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
@container (max-width: 239px) {
|
|
331
|
+
.tnc-item--timed.is-short .tnc-item-time {
|
|
298
332
|
display: none;
|
|
299
333
|
}
|
|
300
334
|
}
|
|
@@ -707,6 +741,10 @@
|
|
|
707
741
|
.tnc-tg-body {
|
|
708
742
|
position: relative;
|
|
709
743
|
}
|
|
744
|
+
.tnc-tg--pinch .tnc-tg-body {
|
|
745
|
+
/* Pinches rescale the grid rather than zoom the page. */
|
|
746
|
+
touch-action: pan-x pan-y;
|
|
747
|
+
}
|
|
710
748
|
.tnc-gutter {
|
|
711
749
|
border-right: 1px solid var(--tnc-line);
|
|
712
750
|
}
|
|
@@ -1196,6 +1234,12 @@
|
|
|
1196
1234
|
font-weight: 650;
|
|
1197
1235
|
line-height: 1;
|
|
1198
1236
|
}
|
|
1237
|
+
.tnc-strip-dots {
|
|
1238
|
+
display: flex;
|
|
1239
|
+
justify-content: center;
|
|
1240
|
+
gap: 2px;
|
|
1241
|
+
min-height: 5px;
|
|
1242
|
+
}
|
|
1199
1243
|
.tnc-strip-dot {
|
|
1200
1244
|
width: 5px;
|
|
1201
1245
|
height: 5px;
|
|
@@ -1906,6 +1950,22 @@
|
|
|
1906
1950
|
outline: 1px solid var(--tnc-focus);
|
|
1907
1951
|
outline-offset: -1px;
|
|
1908
1952
|
}
|
|
1953
|
+
.tnc .tnc-item--timed.is-dragging {
|
|
1954
|
+
min-width: var(--tnc-drag-width);
|
|
1955
|
+
max-width: var(--tnc-drag-width);
|
|
1956
|
+
}
|
|
1957
|
+
.tnc .tnc-dg .tnc-item.is-dragging:not(.is-mirror) {
|
|
1958
|
+
opacity: var(--tnc-drag-opacity);
|
|
1959
|
+
box-shadow: none;
|
|
1960
|
+
outline: none;
|
|
1961
|
+
}
|
|
1962
|
+
.tnc .tnc-month-preview {
|
|
1963
|
+
position: absolute;
|
|
1964
|
+
pointer-events: none;
|
|
1965
|
+
outline: 2px dashed var(--tnc-accent);
|
|
1966
|
+
outline-offset: -2px;
|
|
1967
|
+
z-index: 10;
|
|
1968
|
+
}
|
|
1909
1969
|
.tnc .tnc-item--list.is-dragging:not(.tnc-drag-preview) {
|
|
1910
1970
|
opacity: var(--tnc-drag-opacity);
|
|
1911
1971
|
box-shadow: none;
|
package/dist/cjs/core.cjs
CHANGED
|
@@ -490,43 +490,44 @@ function segmentInWindow(n, day, minMinute, maxMinute, zone) {
|
|
|
490
490
|
};
|
|
491
491
|
}
|
|
492
492
|
var defaultOrder = (a, b) => a.startMs - b.startMs || b.endMs - b.startMs - (a.endMs - a.startMs) || Number(b.allDay) - Number(a.allDay) || a.item.title.localeCompare(b.item.title);
|
|
493
|
+
function collides(a, b, minMinutes) {
|
|
494
|
+
if (b.startMin < a.endMin) return true;
|
|
495
|
+
if (b.startMin === a.endMin && a.endMin > a.startMin) return false;
|
|
496
|
+
return b.startMin < a.startMin + minMinutes;
|
|
497
|
+
}
|
|
498
|
+
function overlaps(a, b, minMinutes) {
|
|
499
|
+
return a.startMin <= b.startMin ? collides(a, b, minMinutes) : collides(b, a, minMinutes);
|
|
500
|
+
}
|
|
493
501
|
function packTimed(segs, minMinutes, order = defaultOrder) {
|
|
494
|
-
const sorted = segs.
|
|
502
|
+
const sorted = [...segs].sort((a, b) => a.startMin - b.startMin || Math.max(b.endMin, b.startMin + minMinutes) - Math.max(a.endMin, a.startMin + minMinutes) || order(a.item, b.item));
|
|
495
503
|
const out = [];
|
|
496
504
|
let cluster = [];
|
|
497
|
-
let
|
|
498
|
-
let clusterEnd = -Infinity;
|
|
505
|
+
let colLast = [];
|
|
499
506
|
let clusterIndex = 0;
|
|
500
507
|
const flush = () => {
|
|
501
508
|
if (cluster.length) clusterIndex++;
|
|
502
|
-
const cols =
|
|
509
|
+
const cols = colLast.length;
|
|
503
510
|
for (const p of cluster) {
|
|
504
511
|
p.cols = cols;
|
|
505
512
|
let span = 1;
|
|
506
|
-
while (p.col + span < cols && !cluster.some((o) => o.col === p.col + span && o
|
|
513
|
+
while (p.col + span < cols && !cluster.some((o) => o.col === p.col + span && overlaps(o, p, minMinutes))) span++;
|
|
507
514
|
p.span = span;
|
|
508
515
|
}
|
|
509
516
|
cluster = [];
|
|
510
|
-
|
|
517
|
+
colLast = [];
|
|
511
518
|
};
|
|
512
519
|
for (const s of sorted) {
|
|
513
|
-
if (
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
}
|
|
517
|
-
let col = colEnds.findIndex((end) => end <= s.startMin);
|
|
518
|
-
if (col < 0) {
|
|
519
|
-
col = colEnds.length;
|
|
520
|
-
colEnds.push(0);
|
|
521
|
-
}
|
|
522
|
-
colEnds[col] = s.end;
|
|
520
|
+
if (!cluster.some((o) => collides(o, s, minMinutes))) flush();
|
|
521
|
+
let col = colLast.findIndex((last) => !collides(last, s, minMinutes));
|
|
522
|
+
if (col < 0) col = colLast.length;
|
|
523
523
|
const p = { ...s, col, cols: 1, span: 1, cluster: clusterIndex, split: false };
|
|
524
|
+
colLast[col] = p;
|
|
524
525
|
cluster.push(p);
|
|
525
526
|
out.push(p);
|
|
526
|
-
clusterEnd = Math.max(clusterEnd, s.end);
|
|
527
527
|
}
|
|
528
528
|
flush();
|
|
529
|
-
|
|
529
|
+
const starts = new Set(out.map((p) => p.startMin));
|
|
530
|
+
for (const p of out) if (p.endMin > p.startMin && p.startMin + minMinutes > p.endMin && starts.has(p.endMin)) p.abutted = true;
|
|
530
531
|
return out;
|
|
531
532
|
}
|
|
532
533
|
function layoutTimedDay(items, day, zone, minMinutes, order, window = [0, MINUTES_PER_DAY]) {
|
|
@@ -548,15 +549,8 @@ function layoutTimedDay(items, day, zone, minMinutes, order, window = [0, MINUTE
|
|
|
548
549
|
}
|
|
549
550
|
function markSplit(lane, other, minMinutes) {
|
|
550
551
|
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
552
|
const split = /* @__PURE__ */ new Set();
|
|
559
|
-
for (const
|
|
553
|
+
for (const p of lane) if (!split.has(p.cluster) && other.some((o) => overlaps(p, o, minMinutes))) split.add(p.cluster);
|
|
560
554
|
for (const p of lane) p.split = split.has(p.cluster);
|
|
561
555
|
}
|
|
562
556
|
function layoutRow(items, days, order = defaultOrder) {
|