@taskctrl/canvas-timeline 0.8.1 → 0.10.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.
- package/README.md +1 -1
- package/dist/canvas-timeline.cjs.js +1 -1
- package/dist/canvas-timeline.cjs.js.map +1 -1
- package/dist/canvas-timeline.es.js +1096 -1038
- package/dist/canvas-timeline.es.js.map +1 -1
- package/dist/dom/DateHeader.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/interaction/InteractionHandler.d.ts +2 -2
- package/dist/interaction/interactionInfo.d.ts +3 -2
- package/dist/interaction/snapResolve.d.ts +41 -0
- package/dist/interaction/snapUtils.d.ts +1 -1
- package/dist/types.d.ts +36 -1
- package/package.json +1 -1
package/dist/dom/DateHeader.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TimelineTheme } from '../types';
|
|
2
|
-
export type DateUnit = 'year' | 'month' | 'week' | 'day' | 'hour';
|
|
2
|
+
export type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour';
|
|
3
3
|
export interface DateHeaderProps {
|
|
4
4
|
unit: DateUnit;
|
|
5
5
|
visibleTimeStart?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Group, Item, ItemBounds, ItemState, DrawHelpers, CanvasItemRenderer, CanvasGroupItemRenderer, DayStyle, RowStyle, Dependency, TimeRangeHighlight, TimelineTheme, MarkerConfig, InteractionInfo, CanvasTimelineProps, CanvasTimelineRef, CaptureOptions, } from './types';
|
|
1
|
+
export type { Group, Item, ItemBounds, ItemState, DrawHelpers, CanvasItemRenderer, CanvasGroupItemRenderer, DayStyle, RowStyle, Dependency, TimeRangeHighlight, TimelineTheme, MarkerConfig, InteractionInfo, DragSnapFn, DragSnapResult, DragSnapAnchor, CanvasTimelineProps, CanvasTimelineRef, CaptureOptions, } from './types';
|
|
2
2
|
export { DEFAULT_THEME } from './types';
|
|
3
3
|
export { CanvasTimeline } from './CanvasTimeline';
|
|
4
4
|
export { HierarchyEngine } from './core/HierarchyEngine';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Item } from '../types';
|
|
1
|
+
import type { Item, DragSnapFn } from '../types';
|
|
2
2
|
export type InteractionMode = 'move' | 'resize-left' | 'resize-right';
|
|
3
3
|
export interface InteractionState {
|
|
4
4
|
item: Item;
|
|
@@ -15,7 +15,7 @@ export declare class InteractionHandler {
|
|
|
15
15
|
private state;
|
|
16
16
|
private dragSnap;
|
|
17
17
|
private activated;
|
|
18
|
-
constructor(dragSnap: number);
|
|
18
|
+
constructor(dragSnap: number | DragSnapFn | undefined);
|
|
19
19
|
startInteraction(item: Item, mode: InteractionMode, x: number, y: number): void;
|
|
20
20
|
update(x: number, y: number): void;
|
|
21
21
|
setCurrentGroup(groupId: string | number): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Item, InteractionInfo } from '../types';
|
|
1
|
+
import type { Item, InteractionInfo, DragSnapFn } from '../types';
|
|
2
2
|
import type { ViewState } from '../core/ViewState';
|
|
3
3
|
import type { IntervalTree } from '../core/IntervalTree';
|
|
4
4
|
import type { HierarchyEngine } from '../core/HierarchyEngine';
|
|
@@ -6,7 +6,8 @@ import type { InteractionState } from './InteractionHandler';
|
|
|
6
6
|
/** The subset of props the snap helpers need. */
|
|
7
7
|
export interface SnapDeps {
|
|
8
8
|
canvasWidth: number;
|
|
9
|
-
dragSnap
|
|
9
|
+
dragSnap?: number | DragSnapFn;
|
|
10
|
+
timezone?: string;
|
|
10
11
|
intervalTree: IntervalTree<Item>;
|
|
11
12
|
hierarchyEngine: HierarchyEngine;
|
|
12
13
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Item, DragSnapFn, DragSnapResult } from '../types';
|
|
2
|
+
/** Reset the once-per-session invalid-snap warning. Test-only. */
|
|
3
|
+
export declare function _resetSnapWarning(): void;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a `dragSnap` prop to a concrete snap spec for the given item/edge.
|
|
6
|
+
*
|
|
7
|
+
* - `undefined` → `1` (no snap).
|
|
8
|
+
* - `number` → returned as-is (preserves legacy behavior, including `0`).
|
|
9
|
+
* - `DragSnapFn` → invoked with `(item, edge)`. `edge` is `'left' | 'right'`
|
|
10
|
+
* during a resize and `undefined` during a move. It may return either a bare
|
|
11
|
+
* interval (ms) — tz-aware default anchoring (see {@link gridSnap}) — or a
|
|
12
|
+
* `{ interval, anchor }` spec to control phase explicitly. An invalid return
|
|
13
|
+
* (`interval` that is `0`, `NaN`, or negative, or a non-finite `anchor`) falls
|
|
14
|
+
* back to `1` (no snap) and warns once per session.
|
|
15
|
+
*
|
|
16
|
+
* Hot path: called on every pointer-move frame. Returns the consumer's object
|
|
17
|
+
* by reference — no allocation or copying here.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveDragSnap(dragSnap: number | DragSnapFn | undefined, item: Item, edge?: 'left' | 'right'): DragSnapResult;
|
|
20
|
+
/**
|
|
21
|
+
* Snap `time` (epoch ms) to a snap grid.
|
|
22
|
+
*
|
|
23
|
+
* When `snap` is a `{ interval, anchor }` spec, the grid is `anchor + N *
|
|
24
|
+
* interval` and the `timezone` is ignored — the consumer owns the phase (see
|
|
25
|
+
* {@link DragSnapAnchor} for the DST caveat). This branch is pure arithmetic
|
|
26
|
+
* (no dayjs), so it is the cheapest path.
|
|
27
|
+
*
|
|
28
|
+
* When `snap` is a bare `number` interval:
|
|
29
|
+
* - For day-or-larger intervals with a `timezone`, the grid is anchored to
|
|
30
|
+
* tz-local midnight rather than the UTC epoch, so the snap lands on the same
|
|
31
|
+
* day boundaries the grid/headers render (which are also tz-local). Day
|
|
32
|
+
* boundaries in a tz with a non-zero UTC offset are not multiples of
|
|
33
|
+
* 86_400_000 since the epoch, so a naive `Math.round(time / interval) *
|
|
34
|
+
* interval` drifts by the offset. The snap is computed in local-calendar-day
|
|
35
|
+
* space, so it stays correct across DST transitions (where a local day is 23
|
|
36
|
+
* or 25 hours long).
|
|
37
|
+
* - Sub-day intervals (1h, 15min, …) stay UTC-anchored: hours and quarter-hours
|
|
38
|
+
* line up between UTC and any whole- or fractional-hour offset, so no
|
|
39
|
+
* translation is needed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function gridSnap(time: number, snap: DragSnapResult, timezone?: string): number;
|
|
@@ -11,5 +11,5 @@ export declare function collectItemEdges(items: SnapItem[], excludeItemId: numbe
|
|
|
11
11
|
* Find the best snap target from a list of edge X positions.
|
|
12
12
|
* Returns the snapped X position if an edge is within threshold, or null to fall back to time-grid snap.
|
|
13
13
|
*/
|
|
14
|
-
export declare function findSnapTarget(currentX: number, edgeXPositions: number[], thresholdPx: number, _pixelsPerMs: number, _dragSnap:
|
|
14
|
+
export declare function findSnapTarget(currentX: number, edgeXPositions: number[], thresholdPx: number, _pixelsPerMs: number, _dragSnap: import('../types').DragSnapResult): number | null;
|
|
15
15
|
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -129,6 +129,38 @@ export interface InteractionInfo {
|
|
|
129
129
|
pointerX: number;
|
|
130
130
|
pointerY: number;
|
|
131
131
|
}
|
|
132
|
+
/** Anchored snap grid: snap to `anchor + N * interval`. Returning this from a
|
|
133
|
+
* {@link DragSnapFn} overrides the default tz-local-midnight anchoring — the
|
|
134
|
+
* consumer is fully in charge of phase. */
|
|
135
|
+
export interface DragSnapAnchor {
|
|
136
|
+
/** Snap interval in ms. Must be finite and `> 0`, else snapping is disabled
|
|
137
|
+
* (falls back to no snap, one `console.warn` per session). */
|
|
138
|
+
interval: number;
|
|
139
|
+
/** Absolute epoch ms. The snap grid is built as
|
|
140
|
+
* `anchor + N * interval`. Because `interval` is exact ms, the grid does
|
|
141
|
+
* NOT track wall-clock hour across DST — at the spring-forward boundary the
|
|
142
|
+
* snapped position will drift one hour from local time and stay drifted
|
|
143
|
+
* until the next anchor reset. Consumers that need wall-clock-stable
|
|
144
|
+
* snapping should re-pick an anchor on the DST side they care about.
|
|
145
|
+
* The timeline's `timezone` prop is ignored when an anchor is supplied. */
|
|
146
|
+
anchor: number;
|
|
147
|
+
}
|
|
148
|
+
/** What a {@link DragSnapFn} may return: a bare interval (ms) — tz-aware
|
|
149
|
+
* default anchoring — or an explicit `{ interval, anchor }` grid. */
|
|
150
|
+
export type DragSnapResult = number | DragSnapAnchor;
|
|
151
|
+
/**
|
|
152
|
+
* Per-drag snap resolver. Called on every pointer-move frame during a
|
|
153
|
+
* drag/resize, so keep it cheap — the library does not memoize the result.
|
|
154
|
+
*
|
|
155
|
+
* @param item The item being dragged/resized.
|
|
156
|
+
* @param edge `'left' | 'right'` during a resize; `undefined` during a move.
|
|
157
|
+
* @returns Either a snap interval in ms (varies only the *interval*; phase stays
|
|
158
|
+
* grid-aligned to multiples of it — tz-local midnight for day-or-larger
|
|
159
|
+
* intervals when `timezone` is set), or a {@link DragSnapAnchor} `{ interval,
|
|
160
|
+
* anchor }` to also control phase (tz is ignored in that case). A `0`, `NaN`,
|
|
161
|
+
* or negative `interval` (or non-finite `anchor`) falls back to no snap.
|
|
162
|
+
*/
|
|
163
|
+
export type DragSnapFn = (item: Item, edge?: 'left' | 'right') => DragSnapResult;
|
|
132
164
|
export interface CanvasTimelineProps {
|
|
133
165
|
groups: Group[];
|
|
134
166
|
items: Item[];
|
|
@@ -144,7 +176,10 @@ export interface CanvasTimelineProps {
|
|
|
144
176
|
canMove: boolean;
|
|
145
177
|
canResize: false | 'left' | 'right' | 'both';
|
|
146
178
|
canChangeGroup: boolean;
|
|
147
|
-
|
|
179
|
+
/** Snap interval for drag/resize, in ms. A `number` snaps everything to that
|
|
180
|
+
* interval; a {@link DragSnapFn} resolves the interval per item/edge. When
|
|
181
|
+
* omitted, no snapping is applied. */
|
|
182
|
+
dragSnap?: number | DragSnapFn;
|
|
148
183
|
minZoom: number;
|
|
149
184
|
maxZoom: number;
|
|
150
185
|
theme?: Partial<TimelineTheme>;
|