npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@haro/react-gantt

v0.2.6

Published

High-performance React Gantt chart library

Readme

@haro/react-gantt

npm version npm downloads bundle size license

High-performance React Gantt chart library optimized for 10,000+ tasks.

A feature-rich, virtualized Gantt chart component for React with TypeScript support. Handles massive datasets smoothly while providing an intuitive drag-and-drop interface.

日本語ドキュメント | Live Demo

Why @haro/react-gantt?

  • Built for scale - Virtual scrolling handles 10,000+ tasks smoothly
  • Resource view - Display tasks by person/equipment, not just by task
  • Full dependency types - FS, SS, FF, SF with visual arrows
  • Minimal footprint - Only 1 runtime dependency (@tanstack/react-virtual)
  • TypeScript-first - Complete type definitions included
  • Modern React - Supports React 18 and 19

Features

  • 🚀 High Performance - Virtual scrolling handles 10,000+ tasks at 60fps
  • 📊 Dual View Modes - Task view and Resource view (who's doing what)
  • 🔗 Dependencies - FS, SS, FF, SF with visual arrows
  • 🎯 Drag & Drop - Move, resize, and reorder tasks
  • 📅 Zoom Levels - Hour, Day, Week, Month
  • 🎨 Customizable - CSS variables, custom renderers, column definitions
  • 📦 Lightweight - Only 1 dependency (@tanstack/react-virtual)
  • 💪 TypeScript - Full type definitions included
  • ⚛️ Modern React - Supports React 18 and 19

Installation

npm install @haro/react-gantt
# or
yarn add @haro/react-gantt
# or
pnpm add @haro/react-gantt

Quick Start

import { Gantt, type Task } from '@haro/react-gantt';
import '@haro/react-gantt/styles.css';

const tasks: Task[] = [
  {
    id: '1',
    title: 'Planning',
    start: Date.now(),
    end: Date.now() + 7 * 24 * 60 * 60 * 1000,
    progress: 0.5,
  },
  {
    id: '2',
    title: 'Development',
    start: Date.now() + 7 * 24 * 60 * 60 * 1000,
    end: Date.now() + 21 * 24 * 60 * 60 * 1000,
    progress: 0,
  },
  {
    id: '3',
    title: 'Release',
    start: Date.now() + 21 * 24 * 60 * 60 * 1000,
    end: Date.now() + 21 * 24 * 60 * 60 * 1000,
    type: 'milestone',
  },
];

function App() {
  const [taskList, setTaskList] = useState(tasks);

  return (
    <div style={{ height: '500px' }}>
      <Gantt
        tasks={taskList}
        view={{ zoom: 'day' }}
        editable
        onTaskChange={(patch) => {
          setTaskList(prev =>
            prev.map(t => t.id === patch.id ? { ...t, ...patch.changes } : t)
          );
        }}
      />
    </div>
  );
}

Core Concepts

Task Types

interface Task {
  id: string;                              // Unique identifier
  title: string;                           // Display name
  start: number | Date;                    // Start timestamp
  end: number | Date;                      // End timestamp
  type?: 'task' | 'milestone' | 'group';   // Task type
  progress?: number;                       // 0 to 1
  parentId?: string;                       // For hierarchy (WBS)
  resourceId?: string;                     // For resource view
  collapsed?: boolean;                     // Collapse children
  deadline?: number;                       // Deadline marker
  segments?: TaskSegment[];                // Composite task bar
  style?: {
    color?: string;
    progressColor?: string;
    barClass?: string;
  };
}

Zoom Levels

| Level | Display | Best for | |-------|---------|----------| | hour | Hours | Daily schedules | | day | Days | Weekly planning | | week | Weeks | Monthly overview | | month | Months | Quarterly/yearly view |

Resource View

Display tasks grouped by resource (person, equipment, etc.):

const resources = [
  { id: 'r1', name: 'Alice', group: 'Dev Team' },
  { id: 'r2', name: 'Bob', group: 'Dev Team' },
];

const tasks = [
  { id: '1', title: 'Task A', resourceId: 'r1', ... },
  { id: '2', title: 'Task B', resourceId: 'r1', ... },  // Same resource
  { id: '3', title: 'Task C', resourceId: 'r2', ... },
];

<Gantt
  tasks={tasks}
  resources={resources}
  resourceMode={true}
  resourceGroupBy="group"
/>

Dependencies

const dependencies = [
  { id: 'd1', fromTaskId: '1', toTaskId: '2', type: 'FS' },  // Finish-to-Start
  { id: 'd2', fromTaskId: '2', toTaskId: '3', type: 'SS' },  // Start-to-Start
];

<Gantt
  tasks={tasks}
  dependencies={dependencies}
  showDependencies={true}
  highlightDependencies={true}
/>

Markers & Non-Working Time

<Gantt
  tasks={tasks}
  markers={[
    { id: 'm1', timestamp: releaseDate, label: 'Release', color: '#f44336' }
  ]}
  showTaskDeadlines={true}
  nonWorkingPeriods={[
    { id: 'h1', start: holidayStart, end: holidayEnd, type: 'holiday' }
  ]}
  workingHours={{ start: '09:00', end: '18:00', daysOfWeek: [1,2,3,4,5] }}
  highlightWeekends={true}
/>

Props Reference

| Prop | Type | Default | Description | |------|------|---------|-------------| | tasks | Task[] | required | Task data | | columns | ColumnDef[] | default cols | Grid column definitions | | view | ViewConfig | - | Zoom level and date range | | editable | boolean | true | Enable drag/resize | | rowHeight | number | 36 | Row height in pixels | | gridWidth | number | 300 | Grid panel width | | showGrid | boolean | true | Show left grid panel | | fitToContainer | boolean | false | Auto-fit to container width | | syncParentDates | boolean | false | Sync parent dates with children | | locale | string | 'ja-JP' | Date format locale | | resources | Resource[] | - | Resource definitions | | resourceMode | boolean | false | Enable resource view | | dependencies | Dependency[] | - | Task dependencies | | markers | Marker[] | - | Global timeline markers | | onTaskChange | function | - | Task change callback | | onSelectionChange | function | - | Selection change callback | | onTaskClick | function | - | Task click callback |

Styling

Customize with CSS variables:

.my-gantt {
  --gantt-bg: #ffffff;
  --gantt-text: #333333;
  --gantt-border: #e0e0e0;
  --gantt-task-bg: #42a5f5;
  --gantt-task-progress: #1976d2;
  --gantt-milestone-bg: #ff9800;
  --gantt-today-line: #f44336;
  --gantt-row-height: 36px;
}

/* Dark mode */
[data-theme="dark"] .my-gantt {
  --gantt-bg: #1a1a2e;
  --gantt-text: #e0e0e0;
  --gantt-border: #333;
}

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Contributing

Contributions are welcome! Please read our Contributing Guide first.

# Clone the repo
git clone https://github.com/Haronoya/react-gantt.git
cd react-gantt

# Install dependencies
npm install

# Start dev server
npm run dev

# Run tests
npm test

# Build
npm run build

License

MIT © Haro


日本語ドキュメント

高性能なReact用ガントチャートライブラリ。10,000タスクでもスムーズに動作します。

特徴

  • 高性能: 仮想スクロールによる大規模データ対応(10,000タスク以上でも60fps)
  • 柔軟なズーム: 時間/日/週/月の4段階
  • ドラッグ操作: タスクの移動・リサイズ
  • 依存関係線: タスク間の依存関係を矢印で表示(FS/SS/FF/SF)
  • リソースビュー: リソース単位でタスクを表示
  • 複合タスクバー: セグメント分割表示
  • マーカー: 期限やイベントの縦線表示
  • 非稼働時間: 休日・休憩時間のグレーアウト
  • カスタマイズ: タスクの色、列定義、レンダラー
  • TypeScript: 完全な型定義
  • 軽量: 依存は@tanstack/react-virtualのみ

インストール

npm install @haro/react-gantt

クイックスタート

import { Gantt, type Task } from '@haro/react-gantt';
import '@haro/react-gantt/styles.css';

const tasks: Task[] = [
  {
    id: '1',
    title: 'プロジェクト計画',
    start: Date.now(),
    end: Date.now() + 7 * 24 * 60 * 60 * 1000, // 1週間後
    type: 'task',
    progress: 0.5,
  },
  {
    id: '2',
    title: 'マイルストーン',
    start: Date.now() + 7 * 24 * 60 * 60 * 1000,
    end: Date.now() + 7 * 24 * 60 * 60 * 1000,
    type: 'milestone',
  },
];

function App() {
  return (
    <div style={{ height: '500px' }}>
      <Gantt
        tasks={tasks}
        view={{ zoom: 'day' }}
        onTaskChange={(patch, context) => {
          console.log('Task changed:', patch, context);
        }}
      />
    </div>
  );
}

基本的な使い方

タスクの定義

interface Task {
  id: string;                    // 一意のID
  title: string;                 // タスク名
  start: number | Date;          // 開始日時
  end: number | Date;            // 終了日時
  type?: 'task' | 'milestone' | 'group';  // タスクタイプ
  progress?: number;             // 進捗(0-1)
  parentId?: string;             // 親タスクID(階層構造用)
  collapsed?: boolean;           // 折りたたみ状態
  resourceId?: string;           // リソースID(リソースビュー用)
  deadline?: number;             // 期限(マーカー表示)
  segments?: TaskSegment[];      // セグメント(複合タスクバー)
  style?: {
    color?: string;              // バーの色
    progressColor?: string;      // 進捗部分の色
    barClass?: string;           // カスタムCSSクラス
  };
}

ズームレベル

| レベル | 表示単位 | 用途 | |--------|----------|------| | hour | 時間 | 1日以内のスケジュール | | day | 日 | 週単位の計画(デフォルト) | | week | 週 | 月単位の計画 | | month | 月 | 四半期〜年単位の計画 |

列のカスタマイズ

import { Gantt, type ColumnDef } from '@haro/react-gantt';

const columns: ColumnDef[] = [
  {
    id: 'title',
    title: 'タスク名',
    width: 200,
    accessor: 'title',
  },
  {
    id: 'start',
    title: '開始日',
    width: 100,
    accessor: (task) => new Date(task.start).toLocaleDateString(),
  },
  {
    id: 'progress',
    title: '進捗',
    width: 80,
    accessor: (task) => `${Math.round((task.progress ?? 0) * 100)}%`,
    align: 'right',
  },
];

<Gantt tasks={tasks} columns={columns} />

イベントハンドリング

<Gantt
  tasks={tasks}
  editable={true}
  onTaskChange={(patch, context) => {
    // patch: { id, changes, previousValues }
    // context: { type: 'drag' | 'resize' | 'collapse' }
    setTasks(prev => prev.map(t =>
      t.id === patch.id ? { ...t, ...patch.changes } : t
    ));
  }}
  onSelectionChange={(selection) => {
    // selection: { ids: string[], anchor?: string }
    console.log('Selected tasks:', selection.ids);
  }}
  onTaskClick={(task, event) => {
    console.log('Clicked:', task.title);
  }}
  onTaskDoubleClick={(task, event) => {
    openEditDialog(task);
  }}
/>

親子タスクの連動

親タスクの期間を子タスク全体に自動で合わせる場合:

<Gantt
  tasks={tasks}
  syncParentDates={true}  // 親タスクの日付を子タスクと連動
/>

表示期間の制御

const [viewStart, setViewStart] = useState(Date.now());
const [viewEnd, setViewEnd] = useState(Date.now() + 30 * 24 * 60 * 60 * 1000);

<Gantt
  tasks={tasks}
  view={{
    zoom: 'day',
    start: viewStart,
    end: viewEnd,
  }}
/>

コンテナ幅に自動フィット

<Gantt
  tasks={tasks}
  fitToContainer={true}  // 表示期間をコンテナ幅に自動調整
/>

拡張機能

依存関係線

タスク間の依存関係を矢印で表示します。

import { Gantt, type Dependency } from '@haro/react-gantt';

const dependencies: Dependency[] = [
  {
    id: 'd1',
    fromTaskId: '1',
    toTaskId: '2',
    type: 'FS',  // Finish-to-Start
  },
  {
    id: 'd2',
    fromTaskId: '2',
    toTaskId: '3',
    type: 'SS',  // Start-to-Start
    color: '#ff5722',
    style: 'dashed',
  },
];

<Gantt
  tasks={tasks}
  dependencies={dependencies}
  showDependencies={true}
  highlightDependencies={true}
  onDependencyClick={(dep, event) => console.log('Clicked:', dep)}
/>

依存関係タイプ:

  • FS: Finish-to-Start(前タスク完了後に開始)
  • SS: Start-to-Start(同時開始)
  • FF: Finish-to-Finish(同時終了)
  • SF: Start-to-Finish

マーカー

期限やイベントを縦線で表示します。

import { Gantt, type Marker } from '@haro/react-gantt';

const markers: Marker[] = [
  {
    id: 'm1',
    timestamp: Date.now() + 14 * 24 * 60 * 60 * 1000,
    label: 'リリース日',
    color: '#f44336',
    style: 'solid',
  },
];

<Gantt
  tasks={tasks}
  markers={markers}
  showTaskDeadlines={true}  // タスクのdeadlineフィールドもマーカー表示
  onMarkerClick={(marker, event) => console.log('Clicked:', marker)}
/>

複合タスクバー(セグメント)

タスクバーを複数のセグメントで構成します。

const tasks: Task[] = [
  {
    id: '1',
    title: '開発作業',
    start: Date.now(),
    end: Date.now() + 5 * 24 * 60 * 60 * 1000,
    segments: [
      { id: 's1', duration: 1 * 24 * 60 * 60 * 1000, color: '#ffeb3b', label: '準備' },
      { id: 's2', duration: 3 * 24 * 60 * 60 * 1000, color: '#4caf50', label: '実装' },
      { id: 's3', duration: 1 * 24 * 60 * 60 * 1000, color: '#2196f3', label: 'レビュー' },
    ],
  },
];

非稼働時間

休日や休憩時間をグレーアウト表示します。

import { Gantt, type NonWorkingPeriod, type WorkingHours } from '@haro/react-gantt';

// 稼働時間設定(自動で営業時間外をグレーアウト)
const workingHours: WorkingHours = {
  start: '09:00',
  end: '18:00',
  daysOfWeek: [1, 2, 3, 4, 5],  // 月〜金
};

// 明示的な非稼働期間
const nonWorkingPeriods: NonWorkingPeriod[] = [
  {
    id: 'holiday1',
    start: Date.parse('2024-01-01'),
    end: Date.parse('2024-01-03'),
    type: 'holiday',
    label: '年末年始',
  },
];

<Gantt
  tasks={tasks}
  workingHours={workingHours}
  nonWorkingPeriods={nonWorkingPeriods}
  showNonWorkingTime={true}
  highlightWeekends={true}
/>

リソースビュー

リソース(人、設備等)単位でタスクを表示します。タスクビューとの違いは以下の通りです:

| | タスクビュー | リソースビュー | |---|---|---| | 行の単位 | 1行 = 1タスク | 1行 = 1リソース | | 同じ行のタスク数 | 1つ | 複数可 | | 用途 | プロジェクト全体の進捗確認 | 誰が何をしているか確認 |

タスクビュー:
行1: タスクA ████████████
行2: タスクB     ██████████
行3: タスクC         ████████

リソースビュー:
行1: 田中さん  ████タスクA████  ██タスクD██
行2: 鈴木さん      ████タスクB████
行3: 佐藤さん          ████タスクC████
import { Gantt, type Resource, type Task } from '@haro/react-gantt';

const resources: Resource[] = [
  { id: 'r1', name: '田中太郎', group: '開発チーム' },
  { id: 'r2', name: '鈴木花子', group: '開発チーム' },
  { id: 'r3', name: '佐藤次郎', group: 'デザインチーム' },
];

const tasks: Task[] = [
  // 同じリソースに複数のタスクを割り当て可能
  { id: '1', title: 'タスク1', start: Date.now(), end: Date.now() + 86400000, resourceId: 'r1' },
  { id: '2', title: 'タスク2', start: Date.now() + 86400000, end: Date.now() + 172800000, resourceId: 'r1' },
  { id: '3', title: 'タスク3', start: Date.now(), end: Date.now() + 172800000, resourceId: 'r2' },
];

<Gantt
  tasks={tasks}
  resources={resources}
  resourceMode={true}           // リソースビューを有効化
  resourceGroupBy="group"       // グループ化するフィールド
  showEmptyResources={true}     // タスクがないリソースも表示
/>

リソースビューでは、同じリソースに割り当てられた複数のタスクが同じ行に並んで表示されます。これにより、各リソースの稼働状況やスケジュールの競合を一目で確認できます。

関連タスクのハイライト

選択タスクに関連するタスクをハイライト表示します。

const tasks: Task[] = [
  { id: '1', title: 'タスク1', groupId: 'project-a', ... },
  { id: '2', title: 'タスク2', groupId: 'project-a', ... },
  { id: '3', title: 'タスク3', relatedTaskIds: ['1', '2'], ... },
];

<Gantt
  tasks={tasks}
  highlightRelatedTasks={true}
  highlightDependencies={true}
/>

Props一覧

| Prop | 型 | デフォルト | 説明 | |------|-----|----------|------| | tasks | Task[] | 必須 | タスクデータ | | columns | ColumnDef[] | デフォルト列 | グリッド列定義 | | view | ViewConfig | - | ズーム・表示期間 | | selection | SelectionState | - | 選択状態(制御モード) | | editable | boolean | true | 編集可否 | | rowHeight | number | 36 | 行の高さ(px) | | gridWidth | number | 300 | グリッド幅(px) | | showGrid | boolean | true | グリッド表示 | | fitToContainer | boolean | false | コンテナ幅自動フィット | | syncParentDates | boolean | false | 親子タスク日付連動 | | locale | string | 'ja-JP' | 日付フォーマットのロケール | | dependencies | Dependency[] | - | 依存関係 | | showDependencies | boolean | true | 依存関係線表示 | | highlightDependencies | boolean | true | 選択時の依存関係ハイライト | | markers | Marker[] | - | グローバルマーカー | | showTaskDeadlines | boolean | true | タスク期限マーカー表示 | | nonWorkingPeriods | NonWorkingPeriod[] | - | 非稼働期間 | | workingHours | WorkingHours | - | 稼働時間設定 | | showNonWorkingTime | boolean | true | 非稼働時間表示 | | highlightWeekends | boolean | true | 週末ハイライト | | resources | Resource[] | - | リソース一覧 | | resourceMode | boolean | false | リソースビュー有効化 | | resourceGroupBy | string | - | リソースグルーピングキー | | highlightRelatedTasks | boolean | false | 関連タスクハイライト | | onTaskChange | function | - | タスク変更時コールバック | | onSelectionChange | function | - | 選択変更時コールバック | | onTaskClick | function | - | タスククリック時 | | onTaskDoubleClick | function | - | タスクダブルクリック時 | | onDependencyClick | function | - | 依存関係クリック時 | | onMarkerClick | function | - | マーカークリック時 | | onResourceClick | function | - | リソースクリック時 | | onColumnResize | function | - | 列リサイズ時 |

CSS変数

スタイルはCSS変数でカスタマイズできます:

.my-gantt {
  /* 基本色 */
  --gantt-bg: #ffffff;
  --gantt-text: #333333;
  --gantt-border: #e0e0e0;

  /* タスクバー */
  --gantt-task-bg: #42a5f5;
  --gantt-task-progress: #1976d2;
  --gantt-milestone-bg: #ff9800;
  --gantt-group-bg: #78909c;

  /* 依存関係線 */
  --gantt-dependency-color: #607d8b;
  --gantt-dependency-highlight: #1976d2;

  /* マーカー */
  --gantt-marker-color: #9c27b0;
  --gantt-deadline-color: #ff9800;

  /* 非稼働時間 */
  --gantt-nonworking-default: rgba(0, 0, 0, 0.05);
  --gantt-nonworking-holiday: rgba(0, 0, 0, 0.08);

  /* キャパシティ */
  --gantt-capacity-normal: #4caf50;
  --gantt-capacity-warning: #ff9800;
  --gantt-capacity-critical: #f44336;

  /* その他 */
  --gantt-today-line: #f44336;
  --gantt-row-height: 36px;
  --gantt-header-height: 40px;
}

開発

# 依存インストール
npm install

# 開発サーバー起動
npm run dev

# ビルド
npm run build

# テスト
npm run test

# 型チェック
npm run typecheck

ライセンス

MIT License

作者

Haro