Files
2026-05-27 23:29:53 +01:00

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 status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in 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.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create directory tree per proposal layout.
  • Write package.json at 0.1.0 with "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 TimelineError extending SuaveplanError; codes: TIMELINE_INVALID_EVENT, TIMELINE_LAYOUT_FAILED.
  • Define all public types: TimelineEvent<TMeta>, TimelineTrack<TMeta>, TimeScaleConfig (with optional timeZone), 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 — throws TimelineError(TIMELINE_INVALID_EVENT) when used outside provider.
  • Implement computeLayout<TMeta>(events, tracks, scale) — overlap resolution (greedy lane assignment), returns LayoutResult with 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 TimelineProvider state.
  • useVirtual — delegates to @suaveplan/react-virtual useVirtualList when 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/testing polyfill). 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, snapToGrid in src/utils/time-utils/.
  • Timezone-aware: dateToPixel and pixelToDate accept optional timeZone.
  • Write time-utils.test.ts (≤500 lines), time-utils.md.

8. Integration and E2E

  • tests/integration.test.tsx — Timeline with 50 events: layout produced, no overlapping items in same lane; Gantt renders dependency arrows.
  • e2e/timeline.spec.ts — Playwright: render Timeline, take screenshot snapshot; render Gantt with 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.