GanttHandle

The methods the `ref` handle exposes, and the option types they take

GanttHandle is the object a ref on the chart receives. It combines GanttScrollApi, GanttDetailApi and GanttTaskCreateApi, so it carries the scroll and zoom methods, the two detail panel methods and addTask. All five types on this page are type-only exports of the package.

import type {
  GanttDetailApi,
  GanttHandle,
  GanttScrollApi,
  GanttScrollOptions,
  GanttTaskCreateApi,
} from '@jaeungkim/gantt-chart';

GanttHandle

/** Imperative API exposed through the ref */
export interface GanttHandle
  extends GanttScrollApi,
    GanttDetailApi,
    GanttTaskCreateApi {}

It declares no member of its own. Every method below is defined in one of the three interfaces it extends. The chart builds the handle by spreading the scroll API and adding the two detail methods and addTask.

Members

MemberSignatureEffect
scrollToDate(date: string | Date | Dayjs, options?: GanttScrollOptions) => voidScrolls horizontally so the date lands at the requested position. Does nothing when the date is outside the rendered timeline.
scrollToToday(options?: GanttScrollOptions) => voidscrollToDate with the current instant.
scrollToTask(taskId: string, options?: GanttScrollOptions) => voidScrolls horizontally to the task's bar, and vertically only when its row is off screen. Does nothing for an id that no row shows.
setScale(scale: GanttScaleKey) => voidSwitches the scale and keeps the centre date in place.
zoomToFit() => voidSwitches to the finest scale at which the whole project fits the timeline width and pins the earliest task date to the left edge.
getScrollElement() => HTMLDivElement | nullReturns the chart's scroll container element, or null when the chart is not mounted.
openDetail(taskId: string) => voidOpens the detail panel on that task. Does nothing for an id that names no task, or while the panel is off.
closeDetail() => voidCloses the detail panel.
addTask() => voidCalls onTaskCreate with a draft one tick long at today, snapped to the current scale. Does nothing while task creation is off.

Every method except getScrollElement returns void.

GanttScrollApi

/** Imperative scroll and zoom API */
export interface GanttScrollApi {
  /** Scroll horizontally to a given date */
  scrollToDate: (date: string | Date | Dayjs, options?: GanttScrollOptions) => void;
  /** Scroll horizontally to today */
  scrollToToday: (options?: GanttScrollOptions) => void;
  /** Scroll horizontally and vertically to a given task */
  scrollToTask: (taskId: string, options?: GanttScrollOptions) => void;
  /** Switches the scale, keeping the centre date centred; an unknown key is ignored */
  setScale: (scale: GanttScaleKey) => void;
  /** Switches to the finest scale the whole project fits at and scrolls it into view (no-op with no tasks) */
  zoomToFit: () => void;
  /** The scroll container DOM node (null when unavailable) */
  getScrollElement: () => HTMLDivElement | null;
}

Dayjs is the object type from dayjs. The package does not re-export it, so import it from dayjs. A plain string or Date is accepted and parsed as UTC. See Task data.

GanttScaleKey is the union of the five scale keys, listed in Scale and theme types. The scale table that setScale checks its argument against is internal and not exported.

GanttDetailApi

/** Opening and closing the detail panel from outside the chart */
export interface GanttDetailApi {
  /** Opens the detail panel on a task; unknown ids and a panel-less chart (no `renderDetail`/`showDetail`) are ignored */
  openDetail: (taskId: string) => void;
  /** Closes the detail panel */
  closeDetail: () => void;
}

The panel is on when showDetail is true. With showDetail omitted, it is on when renderDetail is given. Both props, and the rest of the detail surface, are in GanttProps. While the panel is off, both methods do nothing, so a toolbar button wired to openDetail needs no guard.

GanttTaskCreateApi

/** Proposing a new task from outside the chart */
export interface GanttTaskCreateApi {
  /** Sends a one-tick draft at today to `onTaskCreate`, as the "Add task" button does; no-op without `onTaskCreate` or with `allowTaskCreate` false */
  addTask: () => void;
}

addTask() is the ref counterpart of the Add task button under the task list. It sends the same draft to the same callback and does nothing while creation is off. When today is outside the rendered timeline, the draft moves to the first tick. The row appears when the tasks array your onTaskCreate builds includes it. Creating tasks describes the draft and what turns creation off.

GanttScrollOptions

/** Options for the scrollTo* methods */
export interface GanttScrollOptions {
  /** Whether to animate the scroll (default true) */
  smooth?: boolean;
  /** Where the target lands inside the viewport (default 'center') */
  align?: "start" | "center";
}
FieldTypeDefaultEffect
smoothbooleantruefalse scrolls with behavior: "auto". Any other value, undefined included, animates with behavior: "smooth".
align"start" | "center""center""start" puts the target at the left edge of the timeline area. "center" centres it in the timeline area, measured against the width that remains beside the task list pane.

Horizontal targets are clamped with Math.max(0, ...), so a target left of the timeline origin scrolls to 0.

align applies to the horizontal axis only. When scrollToTask scrolls vertically, it always centres the row.

Imperative API shows the handle attached to a toolbar.

Early calls

ref.current is null until React commits the chart, and null again after it unmounts. A read during the parent's render sees null. By the time the parent's useEffect or useLayoutEffect runs, the handle is set. Guard with ?. rather than !.

After the handle exists, the methods tolerate calls made before their data is ready. Each case below returns without throwing and without a console warning.

CallConditionResult
scrollToDatethe timeline has no ticks, or the date is before the first tick or past the end of the lastno scroll
scrollToTodaytoday is outside the rendered rangeno scroll
scrollToTaskno row shows the id, because it is unknown or hidden under a collapsed parentno scroll
setScalethe key is not one of the five scalesno scale change
setScalethe scroll container is not mounted, or the centre of the timeline area is not over a tickthe scale changes, with no anchor
zoomToFittasks is empty, or the scroll container is not mountedno scale change, no scroll
getScrollElementthe chart is not mountednull
openDetailthe id names no task in tasksno open
openDetailthe panel is off, with neither renderDetail nor showDetail turning it onno open
closeDetailthe panel is off, or already closednothing, and no onDetailChange
addTaskonTaskCreate is not given, allowTaskCreate is false, or readOnly is set without an overriding allowTaskCreateno draft, no callback
addTaskthe timeline has no ticks, because there are no tasks and no window pinned with visibleStart and visibleEndno draft, no callback

Notes

  • The handle is rebuilt whenever the scroll API, either detail method or addTask changes identity. getScrollElement reads the ref on each call, so a handle captured earlier returns the current element.
  • scrollToDate and scrollToToday never change scrollTop. Only scrollToTask scrolls vertically, and only when the target row is outside the viewport.
  • No prop sets the scale after mount. setScale sets an exact scale from code. defaultScale is read once when the store is created, so a later change to it is ignored.
  • The chart renders no scale picker. A picker in your app calls setScale. The onScaleChange prop in GanttProps reports the change back, whichever source made it.
  • zoomToFit takes no GanttScrollOptions. Its scroll is instant, with no animation.
  • zoomToFit tries the five scales in the order day, week, month, quarter, year, and falls back to year when the project fits none of them. See The timeline.
  • Row height for the vertical scrollToTask math is a fixed 38px.
  • openDetail resolves the id against every task, collapsed rows included. scrollToTask needs the row to be rendered. Collapsing a parent hides the row without closing the panel that describes it.
  • With detailTaskId given, the chart is controlled and the two detail methods change nothing on their own. They report the request through onDetailChange and wait for the prop to follow. Without it they move the panel themselves and fire onDetailChange too.
  • addTask does not scroll or change the scale. It calls onTaskCreate and the chart never writes to tasks.
  • Imperative API covers these methods in use.