4.4 KiB
4.4 KiB
Tasks: enterprise-react-timeline
Change ID: enterprise-react-timeline
Package: @suaveplan/react-timeline
Target path: react/ui/react-timeline
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/react-translate, @suaveplan/react-virtual
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory tree per proposal layout.
- Write
package.jsonat0.1.0with"sideEffects": ["**/*.css"], exports map. - Dependencies:
@suaveplan/error workspace:^,@suaveplan/types workspace:^,@suaveplan/react-translate workspace:^,@suaveplan/react-virtual workspace:^,clsx catalog:ui,tailwind-merge catalog:ui,zod catalog:forms,@opentelemetry/api catalog:observability,tslib catalog:build. - Write
tsconfig.json,vitest.config.ts, scripts.
2. Types and errors
- Define
TimelineErrorextendingSuaveplanError; codes:TIMELINE_INVALID_EVENT,TIMELINE_LAYOUT_FAILED. - Define all public types:
TimelineEvent<TMeta>,TimelineTrack<TMeta>,TimeScaleConfig(with optionaltimeZone),LayoutResult,DragState,SelectionState,DependencyEdge. - Write Zod
TimeScaleConfigSchema.
3. Core context and engine
- Implement
TimelineProvider— context value with scale, view, viewport, event store, dispatch. - Implement
useTimelineContext— throwsTimelineError(TIMELINE_INVALID_EVENT)when used outside provider. - Implement
computeLayout<TMeta>(events, tracks, scale)— overlap resolution (greedy lane assignment), returnsLayoutResultwith per-event pixel bounds and lane index. - Write tests + md for context and engine.
{ timeout: 5000 }.
4. Hooks (7)
For each hook:
- Implement with full types, using
TimelineProviderstate. useVirtual— delegates to@suaveplan/react-virtualuseVirtualListwhen event count > 500; falls back to full render below.- Write
<hook>.test.ts(≤500 lines) +<hook>.md+<hook>.stories.tsx(playground variant).
5. Canvas renderers
src/renderers/canvas-renderer/—drawGridLines(ctx, scale, viewport),drawTrackLines(ctx, tracks, scale),setupCanvas(canvas, dpr).src/renderers/event-renderer/—drawEvents(ctx, items, scale),drawDependencyArrows(ctx, edges, scale).- Write tests using
OffscreenCanvas(available in Node via@suaveplan/testingpolyfill). Write md.
6. Components
For each component (Timeline, Gantt, Calendar, primitives):
- Implement component referencing context + engine + renderers.
Timeline+Gantt+Calendar— each has stories:default,large-dataset(1000 events),gantt-dependencies,calendar-month,playground.- All primitive components — stories:
default,playground. - Write test + md for every component.
7. Time utilities
- Implement
addTime,clampDate,dateToPixel,diffMs,generateTicks,pixelToDate,snapToGridinsrc/utils/time-utils/. - Timezone-aware:
dateToPixelandpixelToDateaccept optionaltimeZone. - Write
time-utils.test.ts(≤500 lines),time-utils.md.
8. Integration and E2E
tests/integration.test.tsx—Timelinewith 50 events: layout produced, no overlapping items in same lane;Ganttrenders dependency arrows.e2e/timeline.spec.ts— Playwright: renderTimeline, take screenshot snapshot; renderGanttwith overlapping events, verify lane separation visually.
9. Verify and publish
bunx turbo lint typecheck test --filter=@suaveplan/react-timeline— green.bunx turbo test:coverage --filter=@suaveplan/react-timeline— 100%.bun scripts/publish.ts --package @suaveplan/react-timeline.- Archive change folder.