@ganttloom/gantt-react 0.2.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Santhoshkumar Hariharan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,183 @@
1
+ # @ganttloom/gantt-react
2
+
3
+ React component wrapping [`@ganttloom/gantt-core`](../gantt-core). A thin
4
+ wrapper: it owns no scheduling logic of its own, just React lifecycle,
5
+ props-as-events, and an imperative handle for the escape hatches (undo/redo,
6
+ zoom, export) that don't fit the declarative-props model.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @ganttloom/gantt-react
12
+ # react/react-dom >=18 are peer dependencies
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```tsx
18
+ import { GanttChart } from "@ganttloom/gantt-react";
19
+
20
+ const tasks = [
21
+ { id: "1", name: "Design", start: new Date("2026-01-05"), end: new Date("2026-01-09"), progress: 60 },
22
+ { id: "2", name: "Build", start: new Date("2026-01-09"), end: new Date("2026-01-16"), progress: 10 },
23
+ ];
24
+ const dependencies = [{ fromId: "1", toId: "2", type: "FS" as const }];
25
+
26
+ function App() {
27
+ return (
28
+ <GanttChart
29
+ tasks={tasks}
30
+ dependencies={dependencies}
31
+ viewMode="day"
32
+ showCriticalPath
33
+ enableHistory
34
+ onDateChange={(task, start, end) => console.log(task.name, start, end)}
35
+ />
36
+ );
37
+ }
38
+ ```
39
+
40
+ `<GanttChart />` bundles `@ganttloom/gantt-core`'s default stylesheet
41
+ automatically. `tasks`/`dependencies`/every option prop mirror
42
+ `@ganttloom/gantt-core`'s `GanttOptions` one-to-one — see that package's
43
+ README for what each one does. Pass new array/object references to trigger a
44
+ sync (`setTasks`/`setDependencies`/`setOptions` underneath); mutating in
45
+ place won't re-render.
46
+
47
+ ## Imperative handle
48
+
49
+ Props cover the declarative surface (tasks, dependencies, view options,
50
+ `onXxx` event callbacks). For everything else, attach a ref:
51
+
52
+ ```tsx
53
+ import { useRef } from "react";
54
+ import { GanttChart, type GanttChartHandle } from "@ganttloom/gantt-react";
55
+
56
+ function App() {
57
+ const chartRef = useRef<GanttChartHandle>(null);
58
+
59
+ return (
60
+ <>
61
+ <button onClick={() => chartRef.current?.undo()}>Undo</button>
62
+ <button onClick={() => chartRef.current?.zoomIn()}>Zoom in</button>
63
+ <GanttChart ref={chartRef} tasks={tasks} enableHistory />
64
+ </>
65
+ );
66
+ }
67
+ ```
68
+
69
+ `GanttChartHandle` exposes: `undo`/`redo`/`canUndo`/`canRedo`,
70
+ `expandAll`/`collapseAll`/`toggleGroup`, `removeDependency`,
71
+ `updateDependency`, `updateTask`, `setViewMode`,
72
+ `zoomIn`/`zoomOut`/`getZoomLevel`, `fitToViewport`, `scrollToToday`,
73
+ `getPageCount`/`setPage`, `getResourceHistogram`,
74
+ `selectTask`/`clearSelection`/`getSelectedTaskIds`/`bulkShiftDates`/`bulkDelete`,
75
+ `toSVGString`/`toPNGDataURL`, `getRenderModel`, and `getInstance()` for direct
76
+ access to the underlying `@ganttloom/gantt-core` `GanttChart` when you need
77
+ something not on this list.
78
+
79
+ ## Multi-select and bulk actions
80
+
81
+ ```tsx
82
+ <GanttChart
83
+ tasks={tasks}
84
+ selectable
85
+ onSelectionChange={(taskIds) => setSelectedCount(taskIds.length)}
86
+ />
87
+ ```
88
+
89
+ Click selects one bar, ctrl/cmd-click toggles it into the selection,
90
+ shift-click selects a range. Then drive it from the handle:
91
+ `chartRef.current?.bulkShiftDates(dayMs)`, `chartRef.current?.bulkDelete()`.
92
+
93
+ ## Row reorder and dependency editing
94
+
95
+ ```tsx
96
+ <GanttChart
97
+ tasks={tasks}
98
+ onTaskReorder={(draggedId, targetId, position) => { /* position: before | after | inside */ }}
99
+ onDependencyDblClick={(dep) => {
100
+ // show your own "edit link" UI, then:
101
+ chartRef.current?.updateDependency(dep.fromId, dep.toId, { type: "SS" });
102
+ }}
103
+ />
104
+ ```
105
+
106
+ Both off by default (same construction-time-only wiring caveat as
107
+ `onTaskCreate` — pass the prop from the first render).
108
+
109
+ ## Drag-to-create
110
+
111
+ Off by default; supply `onTaskCreate` to turn it on (the core only wires the
112
+ drag listener when a creation handler is present, so existing consumers see
113
+ no behavior change):
114
+
115
+ ```tsx
116
+ <GanttChart tasks={tasks} onTaskCreate={(task) => console.log("created", task)} />
117
+ ```
118
+
119
+ > The core only checks for `onTaskCreate` **at mount** (same caveat as
120
+ > `onContextMenu`) — pass a function from the first render if you want
121
+ > drag-to-create enabled; toggling it on after mount won't retroactively wire it.
122
+
123
+ ## Timeline markers, column resize/reorder, and search
124
+
125
+ ```tsx
126
+ import { filterTasks } from "@ganttloom/gantt-react";
127
+
128
+ <GanttChart
129
+ tasks={filterTasks(tasks, (t) => t.name.includes(query)).tasks}
130
+ markers={[{ date: releaseDate, label: "Release" }]}
131
+ onColumnResize={(id, width) => setColumnWidths((w) => ({ ...w, [id]: width }))}
132
+ onColumnReorder={(order) => setColumnOrder(order)}
133
+ />
134
+ ```
135
+
136
+ See `@ganttloom/gantt-core`'s README for the full behavior of each — the
137
+ props here are 1:1 mirrors of its `GanttOptions` fields, and `filterTasks`
138
+ is a pure re-export.
139
+
140
+ ## Resource leveling and multi-page PNG export
141
+
142
+ ```tsx
143
+ const { tasks: leveled, shifted } = chartRef.current!.getLeveledTasks();
144
+ if (shifted.length) setTasks(leveled); // if you're holding tasks in your own state
145
+
146
+ const pages = await chartRef.current!.toPNGDataURLs({ pageWidthPx: 1600, pageHeightPx: 1200 });
147
+ ```
148
+
149
+ ## Resource histogram
150
+
151
+ ```tsx
152
+ import { renderResourceHistogramSVG } from "@ganttloom/gantt-react";
153
+
154
+ const buckets = chartRef.current?.getResourceHistogram() ?? [];
155
+ const svg = renderResourceHistogramSVG(buckets);
156
+ // e.g. <div dangerouslySetInnerHTML={{ __html: svg }} />
157
+ ```
158
+
159
+ ## `useGanttChart` (lower-level hook)
160
+
161
+ If you want to own the container element/DOM tree yourself instead of using
162
+ `<GanttChart />`:
163
+
164
+ ```tsx
165
+ import { useRef } from "react";
166
+ import { useGanttChart } from "@ganttloom/gantt-react";
167
+
168
+ function CustomGantt({ tasks }) {
169
+ const containerRef = useRef<HTMLDivElement>(null);
170
+ const { chart, canUndo, canRedo } = useGanttChart(containerRef, tasks);
171
+ return <div ref={containerRef} />;
172
+ }
173
+ ```
174
+
175
+ ## Re-exported types & helpers
176
+
177
+ For convenience, this package re-exports every `@ganttloom/gantt-core` type
178
+ (`GanttTask`, `GanttDependency`, `GanttColumn`, `GanttTheme`, `ViewMode`,
179
+ `WorkingCalendar`, `ConstraintType`, `ResourceLoadBucket`, etc.) and the
180
+ standalone helper functions (`computeWBSCodes`, `applyConstraint`,
181
+ `isWorkingDay`, `nextWorkingDay`, `computeResourceHistogram`,
182
+ `renderResourceHistogramSVG`, ...) so you never need
183
+ `@ganttloom/gantt-core` as a direct dependency just to reference them.
package/dist/index.cjs ADDED
@@ -0,0 +1,363 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_PALETTE: () => import_gantt_core2.DEFAULT_PALETTE,
24
+ DENSITY_PRESETS: () => import_gantt_core2.DENSITY_PRESETS,
25
+ GanttChart: () => GanttChart,
26
+ applyColorByField: () => import_gantt_core2.applyColorByField,
27
+ applyConstraint: () => import_gantt_core2.applyConstraint,
28
+ colorByField: () => import_gantt_core2.colorByField,
29
+ computeResourceHistogram: () => import_gantt_core2.computeResourceHistogram,
30
+ computeWBSCodes: () => import_gantt_core2.computeWBSCodes,
31
+ default: () => GanttChart_default,
32
+ filterTasks: () => import_gantt_core2.filterTasks,
33
+ isHoliday: () => import_gantt_core2.isHoliday,
34
+ isWithinWorkingHours: () => import_gantt_core2.isWithinWorkingHours,
35
+ isWorkingDay: () => import_gantt_core2.isWorkingDay,
36
+ isWorkingTime: () => import_gantt_core2.isWorkingTime,
37
+ levelResources: () => import_gantt_core2.levelResources,
38
+ nextWorkingDay: () => import_gantt_core2.nextWorkingDay,
39
+ previousWorkingDay: () => import_gantt_core2.previousWorkingDay,
40
+ renderResourceHistogramSVG: () => import_gantt_core2.renderResourceHistogramSVG,
41
+ shiftToWorkingDay: () => import_gantt_core2.shiftToWorkingDay,
42
+ shiftToWorkingTime: () => import_gantt_core2.shiftToWorkingTime,
43
+ useGanttChart: () => useGanttChart
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/GanttChart.tsx
48
+ var import_styles = require("@ganttloom/gantt-core/styles.css");
49
+ var import_react2 = require("react");
50
+
51
+ // src/useGanttChart.ts
52
+ var import_react = require("react");
53
+ var import_gantt_core = require("@ganttloom/gantt-core");
54
+ var EMPTY_DEPENDENCIES = [];
55
+ var EMPTY_OPTIONS = {};
56
+ function useGanttChart(containerRef, tasks, dependencies = EMPTY_DEPENDENCIES, options = EMPTY_OPTIONS) {
57
+ const [chart, setChart] = (0, import_react.useState)(null);
58
+ const [canUndo, setCanUndo] = (0, import_react.useState)(false);
59
+ const [canRedo, setCanRedo] = (0, import_react.useState)(false);
60
+ const chartRef = (0, import_react.useRef)(null);
61
+ const initialTasksRef = (0, import_react.useRef)(tasks);
62
+ initialTasksRef.current = tasks;
63
+ const initialDepsRef = (0, import_react.useRef)(dependencies);
64
+ initialDepsRef.current = dependencies;
65
+ const initialOptionsRef = (0, import_react.useRef)(options);
66
+ initialOptionsRef.current = options;
67
+ (0, import_react.useEffect)(() => {
68
+ if (typeof window === "undefined") return void 0;
69
+ const container = containerRef.current;
70
+ if (!container) return void 0;
71
+ const instance = new import_gantt_core.GanttChart(
72
+ container,
73
+ initialTasksRef.current,
74
+ initialDepsRef.current,
75
+ initialOptionsRef.current
76
+ );
77
+ chartRef.current = instance;
78
+ setChart(instance);
79
+ setCanUndo(instance.canUndo);
80
+ setCanRedo(instance.canRedo);
81
+ const onHistoryChange = (state) => {
82
+ setCanUndo(state.canUndo);
83
+ setCanRedo(state.canRedo);
84
+ };
85
+ instance.on("history-change", onHistoryChange);
86
+ return () => {
87
+ instance.off("history-change", onHistoryChange);
88
+ instance.destroy();
89
+ chartRef.current = null;
90
+ setChart(null);
91
+ setCanUndo(false);
92
+ setCanRedo(false);
93
+ };
94
+ }, [containerRef]);
95
+ const isFirstTasksSync = (0, import_react.useRef)(true);
96
+ (0, import_react.useEffect)(() => {
97
+ if (isFirstTasksSync.current) {
98
+ isFirstTasksSync.current = false;
99
+ return;
100
+ }
101
+ chartRef.current?.setTasks(tasks);
102
+ }, [tasks]);
103
+ const isFirstDepsSync = (0, import_react.useRef)(true);
104
+ (0, import_react.useEffect)(() => {
105
+ if (isFirstDepsSync.current) {
106
+ isFirstDepsSync.current = false;
107
+ return;
108
+ }
109
+ chartRef.current?.setDependencies(dependencies);
110
+ }, [dependencies]);
111
+ const isFirstOptionsSync = (0, import_react.useRef)(true);
112
+ (0, import_react.useEffect)(() => {
113
+ if (isFirstOptionsSync.current) {
114
+ isFirstOptionsSync.current = false;
115
+ return;
116
+ }
117
+ chartRef.current?.setOptions(options);
118
+ }, [options]);
119
+ return { chart, canUndo, canRedo };
120
+ }
121
+
122
+ // src/GanttChart.tsx
123
+ var import_jsx_runtime = require("react/jsx-runtime");
124
+ var EMPTY_DEPENDENCIES2 = [];
125
+ var EMPTY_RENDER_MODEL = {
126
+ width: 0,
127
+ height: 0,
128
+ rowHeight: 0,
129
+ headerHeight: 0,
130
+ rows: [],
131
+ bars: [],
132
+ links: [],
133
+ ticks: [],
134
+ columns: [],
135
+ theme: {},
136
+ markers: [],
137
+ rangeStart: /* @__PURE__ */ new Date(0)
138
+ };
139
+ function GanttChartInner(props, ref) {
140
+ const {
141
+ tasks,
142
+ dependencies = EMPTY_DEPENDENCIES2,
143
+ className,
144
+ style,
145
+ onDateChange,
146
+ onProgressChange,
147
+ onDependencyCreate,
148
+ onDependencyRemove,
149
+ onDependencyDblClick,
150
+ onTaskClick,
151
+ onGroupToggle,
152
+ onContextMenu,
153
+ onTaskCreate,
154
+ onColumnResize,
155
+ onColumnReorder,
156
+ onTaskReorder,
157
+ onSelectionChange,
158
+ ...rest
159
+ } = props;
160
+ const containerRef = (0, import_react2.useRef)(null);
161
+ const enableContextMenuWiring = (0, import_react2.useRef)(() => {
162
+ });
163
+ const enableCreateWiring = (0, import_react2.useRef)(() => {
164
+ });
165
+ const enableColumnResizeWiring = (0, import_react2.useRef)((_columnId, _width) => {
166
+ });
167
+ const enableColumnReorderWiring = (0, import_react2.useRef)((_order) => {
168
+ });
169
+ const enableTaskReorderWiring = (0, import_react2.useRef)(
170
+ (_draggedTaskId, _targetTaskId, _position) => {
171
+ }
172
+ );
173
+ const enableDependencyDblClickWiring = (0, import_react2.useRef)((_dep) => {
174
+ });
175
+ const options = (0, import_react2.useMemo)(
176
+ () => ({
177
+ ...rest,
178
+ onContextMenu: enableContextMenuWiring.current,
179
+ onTaskCreate: onTaskCreate ? enableCreateWiring.current : void 0,
180
+ onColumnResize: onColumnResize ? enableColumnResizeWiring.current : void 0,
181
+ onColumnReorder: onColumnReorder ? enableColumnReorderWiring.current : void 0,
182
+ onTaskReorder: onTaskReorder ? enableTaskReorderWiring.current : void 0,
183
+ onDependencyDblClick: onDependencyDblClick ? enableDependencyDblClickWiring.current : void 0,
184
+ onSelectionChange
185
+ }),
186
+ [
187
+ rest.viewMode,
188
+ rest.columns,
189
+ rest.theme,
190
+ rest.colorScheme,
191
+ rest.columnWidth,
192
+ rest.readonly,
193
+ rest.showProgress,
194
+ rest.showDependencies,
195
+ rest.gridPanelWidth,
196
+ rest.showCriticalPath,
197
+ rest.showBaseline,
198
+ rest.showDeadlines,
199
+ rest.showAssigneeAvatars,
200
+ rest.enableHistory,
201
+ rest.keyboardAccessible,
202
+ rest.virtualScroll,
203
+ rest.autoSchedule,
204
+ rest.pagination,
205
+ rest.snapToUnit,
206
+ rest.calendar,
207
+ rest.markers,
208
+ rest.autoRollupProgress,
209
+ rest.selectable,
210
+ Boolean(onTaskCreate),
211
+ Boolean(onColumnResize),
212
+ Boolean(onColumnReorder),
213
+ Boolean(onTaskReorder),
214
+ Boolean(onDependencyDblClick),
215
+ onSelectionChange
216
+ ]
217
+ );
218
+ const { chart } = useGanttChart(containerRef, tasks, dependencies, options);
219
+ const callbacksRef = (0, import_react2.useRef)({
220
+ onDateChange,
221
+ onProgressChange,
222
+ onDependencyCreate,
223
+ onDependencyRemove,
224
+ onDependencyDblClick,
225
+ onTaskClick,
226
+ onGroupToggle,
227
+ onContextMenu,
228
+ onTaskCreate,
229
+ onColumnResize,
230
+ onColumnReorder,
231
+ onTaskReorder,
232
+ onSelectionChange
233
+ });
234
+ callbacksRef.current = {
235
+ onDateChange,
236
+ onProgressChange,
237
+ onDependencyCreate,
238
+ onDependencyRemove,
239
+ onDependencyDblClick,
240
+ onTaskClick,
241
+ onGroupToggle,
242
+ onContextMenu,
243
+ onTaskCreate,
244
+ onColumnResize,
245
+ onColumnReorder,
246
+ onTaskReorder,
247
+ onSelectionChange
248
+ };
249
+ (0, import_react2.useEffect)(() => {
250
+ if (!chart) return void 0;
251
+ const handleDateChange = (p) => callbacksRef.current.onDateChange?.(p.task, p.start, p.end);
252
+ const handleProgressChange = (p) => callbacksRef.current.onProgressChange?.(p.task, p.progress);
253
+ const handleDependencyCreate = (dep) => callbacksRef.current.onDependencyCreate?.(dep);
254
+ const handleDependencyRemove = (dep) => callbacksRef.current.onDependencyRemove?.(dep);
255
+ const handleTaskClick = (p) => callbacksRef.current.onTaskClick?.(p.task);
256
+ const handleGroupToggle = (p) => callbacksRef.current.onGroupToggle?.(p.task, p.collapsed);
257
+ const handleContextMenu = (p) => callbacksRef.current.onContextMenu?.(p.task, p.evt);
258
+ const handleTaskCreate = (p) => callbacksRef.current.onTaskCreate?.(p.task);
259
+ const handleColumnResize = (p) => callbacksRef.current.onColumnResize?.(p.columnId, p.width);
260
+ const handleColumnReorder = (p) => callbacksRef.current.onColumnReorder?.(p.order);
261
+ const handleDependencyDblClick = (dep) => callbacksRef.current.onDependencyDblClick?.(dep);
262
+ const handleTaskReorder = (p) => callbacksRef.current.onTaskReorder?.(p.draggedTaskId, p.targetTaskId, p.position);
263
+ const handleSelectionChange = (p) => callbacksRef.current.onSelectionChange?.(p.taskIds);
264
+ chart.on("date-change", handleDateChange);
265
+ chart.on("progress-change", handleProgressChange);
266
+ chart.on("dependency-create", handleDependencyCreate);
267
+ chart.on("dependency-remove", handleDependencyRemove);
268
+ chart.on("dependency-dblclick", handleDependencyDblClick);
269
+ chart.on("task-click", handleTaskClick);
270
+ chart.on("group-toggle", handleGroupToggle);
271
+ chart.on("context-menu", handleContextMenu);
272
+ chart.on("task-create", handleTaskCreate);
273
+ chart.on("column-resize", handleColumnResize);
274
+ chart.on("column-reorder", handleColumnReorder);
275
+ chart.on("task-reorder", handleTaskReorder);
276
+ chart.on("selection-change", handleSelectionChange);
277
+ return () => {
278
+ chart.off("date-change", handleDateChange);
279
+ chart.off("progress-change", handleProgressChange);
280
+ chart.off("dependency-create", handleDependencyCreate);
281
+ chart.off("dependency-remove", handleDependencyRemove);
282
+ chart.off("dependency-dblclick", handleDependencyDblClick);
283
+ chart.off("task-click", handleTaskClick);
284
+ chart.off("group-toggle", handleGroupToggle);
285
+ chart.off("context-menu", handleContextMenu);
286
+ chart.off("task-create", handleTaskCreate);
287
+ chart.off("column-resize", handleColumnResize);
288
+ chart.off("column-reorder", handleColumnReorder);
289
+ chart.off("task-reorder", handleTaskReorder);
290
+ chart.off("selection-change", handleSelectionChange);
291
+ };
292
+ }, [chart]);
293
+ (0, import_react2.useImperativeHandle)(
294
+ ref,
295
+ () => ({
296
+ undo: () => chart?.undo(),
297
+ redo: () => chart?.redo(),
298
+ canUndo: () => chart?.canUndo ?? false,
299
+ canRedo: () => chart?.canRedo ?? false,
300
+ expandAll: () => chart?.expandAll(),
301
+ collapseAll: () => chart?.collapseAll(),
302
+ toggleGroup: (taskId) => chart?.toggleGroup(taskId),
303
+ removeDependency: (fromId, toId) => chart?.removeDependency(fromId, toId),
304
+ updateDependency: (fromId, toId, partial) => chart?.updateDependency(fromId, toId, partial),
305
+ updateTask: (id, partial) => chart?.updateTask(id, partial),
306
+ setViewMode: (mode) => chart?.setViewMode(mode),
307
+ fitToViewport: (containerWidthPx) => chart?.fitToViewport(containerWidthPx),
308
+ scrollToToday: () => chart?.scrollToToday(),
309
+ scrollToRangeStart: () => chart?.scrollToRangeStart(),
310
+ scrollToRangeEnd: () => chart?.scrollToRangeEnd(),
311
+ getPageCount: () => chart?.getPageCount() ?? 1,
312
+ setPage: (page) => chart?.setPage(page),
313
+ zoomIn: (factor) => chart?.zoomIn(factor),
314
+ zoomOut: (factor) => chart?.zoomOut(factor),
315
+ getZoomLevel: () => chart?.getZoomLevel() ?? 0,
316
+ getResourceHistogram: (options2) => chart?.getResourceHistogram(options2) ?? [],
317
+ getLeveledTasks: (options2) => chart?.getLeveledTasks(options2) ?? { tasks: [], shifted: [] },
318
+ selectTask: (id, options2) => chart?.selectTask(id, options2),
319
+ selectAllVisible: () => chart?.selectAllVisible(),
320
+ clearSelection: () => chart?.clearSelection(),
321
+ getSelectedTaskIds: () => chart?.getSelectedTaskIds() ?? [],
322
+ bulkShiftDates: (deltaMs) => chart?.bulkShiftDates(deltaMs),
323
+ bulkDelete: () => chart?.bulkDelete(),
324
+ toSVGString: () => chart?.toSVGString() ?? "",
325
+ toPNGDataURL: () => chart?.toPNGDataURL() ?? Promise.resolve(""),
326
+ toPNGDataURLs: (options2) => chart?.toPNGDataURLs(options2) ?? Promise.resolve([]),
327
+ getRenderModel: () => chart?.getRenderModel() ?? EMPTY_RENDER_MODEL,
328
+ getInstance: () => chart
329
+ }),
330
+ [chart]
331
+ );
332
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: containerRef, className, style });
333
+ }
334
+ var GanttChart = (0, import_react2.forwardRef)(GanttChartInner);
335
+ GanttChart.displayName = "GanttChart";
336
+ var GanttChart_default = GanttChart;
337
+
338
+ // src/index.ts
339
+ var import_gantt_core2 = require("@ganttloom/gantt-core");
340
+ // Annotate the CommonJS export names for ESM import in node:
341
+ 0 && (module.exports = {
342
+ DEFAULT_PALETTE,
343
+ DENSITY_PRESETS,
344
+ GanttChart,
345
+ applyColorByField,
346
+ applyConstraint,
347
+ colorByField,
348
+ computeResourceHistogram,
349
+ computeWBSCodes,
350
+ filterTasks,
351
+ isHoliday,
352
+ isWithinWorkingHours,
353
+ isWorkingDay,
354
+ isWorkingTime,
355
+ levelResources,
356
+ nextWorkingDay,
357
+ previousWorkingDay,
358
+ renderResourceHistogramSVG,
359
+ shiftToWorkingDay,
360
+ shiftToWorkingTime,
361
+ useGanttChart
362
+ });
363
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/GanttChart.tsx","../src/useGanttChart.ts"],"sourcesContent":["export { GanttChart, default } from \"./GanttChart\";\nexport type { GanttChartProps, GanttChartHandle } from \"./GanttChart\";\n\nexport { useGanttChart } from \"./useGanttChart\";\nexport type { UseGanttChartResult } from \"./useGanttChart\";\n\n// Re-exported so consumers never need to add @ganttloom/gantt-core as a direct\n// dependency just to reference its types.\nexport type {\n ViewMode,\n DependencyType,\n GanttDependency,\n GanttAssignee,\n GanttTask,\n GanttColumn,\n GanttTheme,\n GanttRenderRow,\n GanttRenderBar,\n GanttRenderLink,\n GanttRenderTick,\n GanttRenderModel,\n GanttOptions,\n GanttEventMap,\n WorkingCalendar,\n ConstraintType,\n ResourceHistogramOptions,\n ResourceLoadBucket,\n GanttMarker,\n GanttRenderMarker,\n FilterTasksOptions,\n FilterTasksResult,\n Density,\n ResourceLevelingOptions,\n ResourceLevelingResult,\n} from \"@ganttloom/gantt-core\";\n\nexport {\n computeWBSCodes,\n applyConstraint,\n isWorkingDay,\n isHoliday,\n isWithinWorkingHours,\n isWorkingTime,\n nextWorkingDay,\n previousWorkingDay,\n shiftToWorkingDay,\n shiftToWorkingTime,\n computeResourceHistogram,\n renderResourceHistogramSVG,\n filterTasks,\n colorByField,\n applyColorByField,\n DEFAULT_PALETTE,\n DENSITY_PRESETS,\n levelResources,\n} from \"@ganttloom/gantt-core\";\n","// Pulls in the core's default styles so consumers get a working chart out of the box.\n// This resolves through gantt-core's package.json \"exports\" map (\"./styles.css\" -> \"./dist/styles.css\").\n// If your bundler can't resolve CSS imports from a dependency's export map, import it yourself instead:\n// import \"@ganttloom/gantt-core/styles.css\";\nimport \"@ganttloom/gantt-core/styles.css\";\n\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n type CSSProperties,\n type Ref,\n} from \"react\";\nimport type {\n GanttChart as GanttCore,\n GanttColumn,\n GanttDependency,\n GanttMarker,\n GanttOptions,\n GanttRenderModel,\n GanttTask,\n GanttTheme,\n ResourceHistogramOptions,\n ResourceLoadBucket,\n ResourceLevelingOptions,\n ResourceLevelingResult,\n ViewMode,\n WorkingCalendar,\n} from \"@ganttloom/gantt-core\";\nimport { useGanttChart } from \"./useGanttChart\";\n\nexport interface GanttChartProps {\n tasks: GanttTask[];\n dependencies?: GanttDependency[];\n\n // Mirrors of GanttOptions' non-callback fields.\n viewMode?: ViewMode;\n columns?: GanttColumn[];\n theme?: Partial<GanttTheme>;\n colorScheme?: \"light\" | \"dark\" | \"auto\";\n columnWidth?: number;\n readonly?: boolean;\n showProgress?: boolean;\n showDependencies?: boolean;\n gridPanelWidth?: number;\n showCriticalPath?: boolean;\n showBaseline?: boolean;\n showDeadlines?: boolean;\n showAssigneeAvatars?: boolean;\n enableHistory?: boolean;\n keyboardAccessible?: boolean;\n virtualScroll?: boolean;\n autoSchedule?: boolean;\n pagination?: { pageSize: number; page: number };\n snapToUnit?: \"hour\" | \"day\" | \"week\" | false;\n /** working-day/holiday definition used to shade non-working time and (with autoSchedule) skip it when cascading */\n calendar?: WorkingCalendar;\n /** arbitrary labeled vertical lines on the timeline, independent of any task */\n markers?: GanttMarker[];\n /** a group task with no explicit `progress` gets a duration-weighted average of its children's progress instead of 0 */\n autoRollupProgress?: boolean;\n /** enables click/ctrl-click/shift-click multi-selection of task bars, and the handle's bulkShiftDates()/bulkDelete() */\n selectable?: boolean;\n\n // Mirrors of GanttOptions' callback fields, as normal React event props.\n onDateChange?: (task: GanttTask, start: Date, end: Date) => void;\n onProgressChange?: (task: GanttTask, progress: number) => void;\n onDependencyCreate?: (dep: GanttDependency) => void;\n onDependencyRemove?: (dep: GanttDependency) => void;\n /** called on double-click of a dependency link, for building your own \"edit this link\" UI (see the handle's updateDependency) */\n onDependencyDblClick?: (dep: GanttDependency) => void;\n onTaskClick?: (task: GanttTask) => void;\n onGroupToggle?: (task: GanttTask, collapsed: boolean) => void;\n onContextMenu?: (task: GanttTask, evt: PointerEvent) => void;\n /** called when a task is created via drag-to-create on an empty timeline row */\n onTaskCreate?: (task: GanttTask) => void;\n /** called when a grid column is resized by dragging its header's edge */\n onColumnResize?: (columnId: string, width: number) => void;\n /** called when grid columns are reordered by dragging a header; `order` is the new full list of column ids */\n onColumnReorder?: (order: string[]) => void;\n /** called when a grid row is dragged onto another; \"inside\" reparents the dragged task under the target */\n onTaskReorder?: (draggedTaskId: string, targetTaskId: string, position: \"before\" | \"after\" | \"inside\") => void;\n onSelectionChange?: (taskIds: string[]) => void;\n\n /** Applied to the wrapping container div. */\n className?: string;\n style?: CSSProperties;\n}\n\n/** Imperative escape hatches that don't need to be reactive props. */\nexport interface GanttChartHandle {\n undo(): void;\n redo(): void;\n canUndo(): boolean;\n canRedo(): boolean;\n expandAll(): void;\n collapseAll(): void;\n toggleGroup(taskId: string): void;\n removeDependency(fromId: string, toId: string): void;\n updateDependency(fromId: string, toId: string, partial: Partial<GanttDependency>): void;\n updateTask(id: string, partial: Partial<GanttTask>): void;\n setViewMode(mode: ViewMode): void;\n fitToViewport(containerWidthPx: number): void;\n scrollToToday(): void;\n scrollToRangeStart(): void;\n scrollToRangeEnd(): void;\n getPageCount(): number;\n setPage(page: number): void;\n zoomIn(factor?: number): void;\n zoomOut(factor?: number): void;\n getZoomLevel(): number;\n getResourceHistogram(options?: ResourceHistogramOptions): ResourceLoadBucket[];\n getLeveledTasks(options?: ResourceLevelingOptions): ResourceLevelingResult;\n selectTask(id: string, options?: { additive?: boolean }): void;\n selectAllVisible(): void;\n clearSelection(): void;\n getSelectedTaskIds(): string[];\n bulkShiftDates(deltaMs: number): void;\n bulkDelete(): void;\n toSVGString(): string;\n toPNGDataURL(): Promise<string>;\n toPNGDataURLs(options?: { pageWidthPx?: number; pageHeightPx?: number }): Promise<string[]>;\n getRenderModel(): GanttRenderModel | null;\n /** Direct access to the underlying framework-agnostic core instance (null before mount). */\n getInstance(): GanttCore | null;\n}\n\nconst EMPTY_DEPENDENCIES: GanttDependency[] = [];\n\nconst EMPTY_RENDER_MODEL: GanttRenderModel = {\n width: 0,\n height: 0,\n rowHeight: 0,\n headerHeight: 0,\n rows: [],\n bars: [],\n links: [],\n ticks: [],\n columns: [],\n theme: {} as GanttTheme,\n markers: [],\n rangeStart: new Date(0),\n};\n\nfunction GanttChartInner(props: GanttChartProps, ref: Ref<GanttChartHandle>) {\n const {\n tasks,\n dependencies = EMPTY_DEPENDENCIES,\n className,\n style,\n onDateChange,\n onProgressChange,\n onDependencyCreate,\n onDependencyRemove,\n onDependencyDblClick,\n onTaskClick,\n onGroupToggle,\n onContextMenu,\n onTaskCreate,\n onColumnResize,\n onColumnReorder,\n onTaskReorder,\n onSelectionChange,\n ...rest\n } = props;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // The core only wires up its internal contextmenu DOM listener (and therefore only\n // ever emits the \"context-menu\" event) when options.onContextMenu is truthy AT\n // CONSTRUCTION TIME (see GanttChart#setupDom in gantt-core). We pass a stable no-op\n // here purely to force that wiring on regardless of whether the consumer supplied\n // onContextMenu, and dispatch the actual prop via the \"context-menu\" event\n // subscription below (so it stays reactive to prop changes and is never double-fired).\n const enableContextMenuWiring = useRef(() => {});\n\n // Same construction-time-only caveat as onContextMenu above: drag-to-create is only\n // wired into the core's InteractionController when options.onTaskCreate is truthy at\n // construction. A stable no-op forces it on whenever this component was given an\n // onTaskCreate prop at all; the real dispatch goes through the \"task-create\" event.\n const enableCreateWiring = useRef(() => {});\n\n // Same construction-time-only caveat: column resize/reorder DOM listeners are only\n // built into the grid header when these options are truthy at construction.\n const enableColumnResizeWiring = useRef((_columnId: string, _width: number) => {});\n const enableColumnReorderWiring = useRef((_order: string[]) => {});\n const enableTaskReorderWiring = useRef(\n (_draggedTaskId: string, _targetTaskId: string, _position: \"before\" | \"after\" | \"inside\") => {}\n );\n const enableDependencyDblClickWiring = useRef((_dep: GanttDependency) => {});\n\n const options = useMemo<GanttOptions>(\n () => ({\n ...rest,\n onContextMenu: enableContextMenuWiring.current,\n onTaskCreate: onTaskCreate ? enableCreateWiring.current : undefined,\n onColumnResize: onColumnResize ? enableColumnResizeWiring.current : undefined,\n onColumnReorder: onColumnReorder ? enableColumnReorderWiring.current : undefined,\n onTaskReorder: onTaskReorder ? enableTaskReorderWiring.current : undefined,\n onDependencyDblClick: onDependencyDblClick ? enableDependencyDblClickWiring.current : undefined,\n onSelectionChange,\n }),\n [\n rest.viewMode,\n rest.columns,\n rest.theme,\n rest.colorScheme,\n rest.columnWidth,\n rest.readonly,\n rest.showProgress,\n rest.showDependencies,\n rest.gridPanelWidth,\n rest.showCriticalPath,\n rest.showBaseline,\n rest.showDeadlines,\n rest.showAssigneeAvatars,\n rest.enableHistory,\n rest.keyboardAccessible,\n rest.virtualScroll,\n rest.autoSchedule,\n rest.pagination,\n rest.snapToUnit,\n rest.calendar,\n rest.markers,\n rest.autoRollupProgress,\n rest.selectable,\n Boolean(onTaskCreate),\n Boolean(onColumnResize),\n Boolean(onColumnReorder),\n Boolean(onTaskReorder),\n Boolean(onDependencyDblClick),\n onSelectionChange,\n ]\n );\n\n const { chart } = useGanttChart(containerRef, tasks, dependencies, options);\n\n // Keep the latest callback props in a ref so the event-subscription effect below\n // doesn't need to re-subscribe (tearing down/rebuilding listeners) on every render.\n const callbacksRef = useRef({\n onDateChange,\n onProgressChange,\n onDependencyCreate,\n onDependencyRemove,\n onDependencyDblClick,\n onTaskClick,\n onGroupToggle,\n onContextMenu,\n onTaskCreate,\n onColumnResize,\n onColumnReorder,\n onTaskReorder,\n onSelectionChange,\n });\n callbacksRef.current = {\n onDateChange,\n onProgressChange,\n onDependencyCreate,\n onDependencyRemove,\n onDependencyDblClick,\n onTaskClick,\n onGroupToggle,\n onContextMenu,\n onTaskCreate,\n onColumnResize,\n onColumnReorder,\n onTaskReorder,\n onSelectionChange,\n };\n\n useEffect(() => {\n if (!chart) return undefined;\n\n const handleDateChange = (p: { task: GanttTask; start: Date; end: Date }) =>\n callbacksRef.current.onDateChange?.(p.task, p.start, p.end);\n const handleProgressChange = (p: { task: GanttTask; progress: number }) =>\n callbacksRef.current.onProgressChange?.(p.task, p.progress);\n const handleDependencyCreate = (dep: GanttDependency) =>\n callbacksRef.current.onDependencyCreate?.(dep);\n const handleDependencyRemove = (dep: GanttDependency) =>\n callbacksRef.current.onDependencyRemove?.(dep);\n const handleTaskClick = (p: { task: GanttTask }) =>\n callbacksRef.current.onTaskClick?.(p.task);\n const handleGroupToggle = (p: { task: GanttTask; collapsed: boolean }) =>\n callbacksRef.current.onGroupToggle?.(p.task, p.collapsed);\n const handleContextMenu = (p: { task: GanttTask; evt: PointerEvent }) =>\n callbacksRef.current.onContextMenu?.(p.task, p.evt);\n const handleTaskCreate = (p: { task: GanttTask }) => callbacksRef.current.onTaskCreate?.(p.task);\n const handleColumnResize = (p: { columnId: string; width: number }) =>\n callbacksRef.current.onColumnResize?.(p.columnId, p.width);\n const handleColumnReorder = (p: { order: string[] }) =>\n callbacksRef.current.onColumnReorder?.(p.order);\n const handleDependencyDblClick = (dep: GanttDependency) =>\n callbacksRef.current.onDependencyDblClick?.(dep);\n const handleTaskReorder = (p: {\n draggedTaskId: string;\n targetTaskId: string;\n position: \"before\" | \"after\" | \"inside\";\n }) => callbacksRef.current.onTaskReorder?.(p.draggedTaskId, p.targetTaskId, p.position);\n const handleSelectionChange = (p: { taskIds: string[] }) =>\n callbacksRef.current.onSelectionChange?.(p.taskIds);\n\n chart.on(\"date-change\", handleDateChange);\n chart.on(\"progress-change\", handleProgressChange);\n chart.on(\"dependency-create\", handleDependencyCreate);\n chart.on(\"dependency-remove\", handleDependencyRemove);\n chart.on(\"dependency-dblclick\", handleDependencyDblClick);\n chart.on(\"task-click\", handleTaskClick);\n chart.on(\"group-toggle\", handleGroupToggle);\n chart.on(\"context-menu\", handleContextMenu);\n chart.on(\"task-create\", handleTaskCreate);\n chart.on(\"column-resize\", handleColumnResize);\n chart.on(\"column-reorder\", handleColumnReorder);\n chart.on(\"task-reorder\", handleTaskReorder);\n chart.on(\"selection-change\", handleSelectionChange);\n\n return () => {\n chart.off(\"date-change\", handleDateChange);\n chart.off(\"progress-change\", handleProgressChange);\n chart.off(\"dependency-create\", handleDependencyCreate);\n chart.off(\"dependency-remove\", handleDependencyRemove);\n chart.off(\"dependency-dblclick\", handleDependencyDblClick);\n chart.off(\"task-click\", handleTaskClick);\n chart.off(\"group-toggle\", handleGroupToggle);\n chart.off(\"context-menu\", handleContextMenu);\n chart.off(\"task-create\", handleTaskCreate);\n chart.off(\"column-resize\", handleColumnResize);\n chart.off(\"column-reorder\", handleColumnReorder);\n chart.off(\"task-reorder\", handleTaskReorder);\n chart.off(\"selection-change\", handleSelectionChange);\n };\n }, [chart]);\n\n useImperativeHandle(\n ref,\n (): GanttChartHandle => ({\n undo: () => chart?.undo(),\n redo: () => chart?.redo(),\n canUndo: () => chart?.canUndo ?? false,\n canRedo: () => chart?.canRedo ?? false,\n expandAll: () => chart?.expandAll(),\n collapseAll: () => chart?.collapseAll(),\n toggleGroup: (taskId: string) => chart?.toggleGroup(taskId),\n removeDependency: (fromId: string, toId: string) => chart?.removeDependency(fromId, toId),\n updateDependency: (fromId: string, toId: string, partial: Partial<GanttDependency>) =>\n chart?.updateDependency(fromId, toId, partial),\n updateTask: (id: string, partial: Partial<GanttTask>) => chart?.updateTask(id, partial),\n setViewMode: (mode: ViewMode) => chart?.setViewMode(mode),\n fitToViewport: (containerWidthPx: number) => chart?.fitToViewport(containerWidthPx),\n scrollToToday: () => chart?.scrollToToday(),\n scrollToRangeStart: () => chart?.scrollToRangeStart(),\n scrollToRangeEnd: () => chart?.scrollToRangeEnd(),\n getPageCount: () => chart?.getPageCount() ?? 1,\n setPage: (page: number) => chart?.setPage(page),\n zoomIn: (factor?: number) => chart?.zoomIn(factor),\n zoomOut: (factor?: number) => chart?.zoomOut(factor),\n getZoomLevel: () => chart?.getZoomLevel() ?? 0,\n getResourceHistogram: (options?: ResourceHistogramOptions) =>\n chart?.getResourceHistogram(options) ?? [],\n getLeveledTasks: (options?: ResourceLevelingOptions) =>\n chart?.getLeveledTasks(options) ?? { tasks: [], shifted: [] },\n selectTask: (id: string, options?: { additive?: boolean }) => chart?.selectTask(id, options),\n selectAllVisible: () => chart?.selectAllVisible(),\n clearSelection: () => chart?.clearSelection(),\n getSelectedTaskIds: () => chart?.getSelectedTaskIds() ?? [],\n bulkShiftDates: (deltaMs: number) => chart?.bulkShiftDates(deltaMs),\n bulkDelete: () => chart?.bulkDelete(),\n toSVGString: () => chart?.toSVGString() ?? \"\",\n toPNGDataURL: () => chart?.toPNGDataURL() ?? Promise.resolve(\"\"),\n toPNGDataURLs: (options?: { pageWidthPx?: number; pageHeightPx?: number }) =>\n chart?.toPNGDataURLs(options) ?? Promise.resolve([]),\n getRenderModel: () => chart?.getRenderModel() ?? EMPTY_RENDER_MODEL,\n getInstance: () => chart,\n }),\n [chart]\n );\n\n return <div ref={containerRef} className={className} style={style} />;\n}\n\nexport const GanttChart = forwardRef(GanttChartInner);\nGanttChart.displayName = \"GanttChart\";\n\nexport default GanttChart;\n","import { useEffect, useRef, useState, type RefObject } from \"react\";\nimport { GanttChart as GanttCore } from \"@ganttloom/gantt-core\";\nimport type { GanttDependency, GanttOptions, GanttTask } from \"@ganttloom/gantt-core\";\n\nexport interface UseGanttChartResult {\n /** The underlying framework-agnostic GanttChart instance, or null before the DOM mount effect runs (or on the server). */\n chart: GanttCore | null;\n /** Reactive, subscribed to the core's \"history-change\" event. Only meaningful when `enableHistory` is set in options. */\n canUndo: boolean;\n /** Reactive, subscribed to the core's \"history-change\" event. Only meaningful when `enableHistory` is set in options. */\n canRedo: boolean;\n}\n\nconst EMPTY_DEPENDENCIES: GanttDependency[] = [];\nconst EMPTY_OPTIONS: GanttOptions = {};\n\n/**\n * Lower-level escape hatch for consumers who want to own their own container element\n * and DOM tree instead of using the <GanttChart /> component. Constructs a\n * @ganttloom/gantt-core GanttChart instance against `containerRef.current` on mount,\n * keeps it in sync with `tasks` / `dependencies` / `options` via setTasks / setDependencies /\n * setOptions (reference-equality checks only — pass new arrays/objects to trigger a sync),\n * and destroys it on unmount.\n */\nexport function useGanttChart(\n containerRef: RefObject<HTMLElement | null>,\n tasks: GanttTask[],\n dependencies: GanttDependency[] = EMPTY_DEPENDENCIES,\n options: GanttOptions = EMPTY_OPTIONS\n): UseGanttChartResult {\n const [chart, setChart] = useState<GanttCore | null>(null);\n const [canUndo, setCanUndo] = useState(false);\n const [canRedo, setCanRedo] = useState(false);\n\n const chartRef = useRef<GanttCore | null>(null);\n\n // Latest props, read from the mount effect so it doesn't need to depend on them\n // (which would otherwise tear down and recreate the whole chart on every change).\n const initialTasksRef = useRef(tasks);\n initialTasksRef.current = tasks;\n const initialDepsRef = useRef(dependencies);\n initialDepsRef.current = dependencies;\n const initialOptionsRef = useRef(options);\n initialOptionsRef.current = options;\n\n useEffect(() => {\n if (typeof window === \"undefined\") return undefined;\n const container = containerRef.current;\n if (!container) return undefined;\n\n const instance = new GanttCore(\n container,\n initialTasksRef.current,\n initialDepsRef.current,\n initialOptionsRef.current\n );\n chartRef.current = instance;\n setChart(instance);\n setCanUndo(instance.canUndo);\n setCanRedo(instance.canRedo);\n\n const onHistoryChange = (state: { canUndo: boolean; canRedo: boolean }) => {\n setCanUndo(state.canUndo);\n setCanRedo(state.canRedo);\n };\n instance.on(\"history-change\", onHistoryChange);\n\n return () => {\n instance.off(\"history-change\", onHistoryChange);\n instance.destroy();\n chartRef.current = null;\n setChart(null);\n setCanUndo(false);\n setCanRedo(false);\n };\n // Intentionally mount/unmount only — the container element identity is what matters.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [containerRef]);\n\n const isFirstTasksSync = useRef(true);\n useEffect(() => {\n if (isFirstTasksSync.current) {\n isFirstTasksSync.current = false;\n return;\n }\n chartRef.current?.setTasks(tasks);\n }, [tasks]);\n\n const isFirstDepsSync = useRef(true);\n useEffect(() => {\n if (isFirstDepsSync.current) {\n isFirstDepsSync.current = false;\n return;\n }\n chartRef.current?.setDependencies(dependencies);\n }, [dependencies]);\n\n const isFirstOptionsSync = useRef(true);\n useEffect(() => {\n if (isFirstOptionsSync.current) {\n isFirstOptionsSync.current = false;\n return;\n }\n chartRef.current?.setOptions(options);\n }, [options]);\n\n return { chart, canUndo, canRedo };\n}\n"],"mappings":"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","names":["import_react","GanttCore","EMPTY_DEPENDENCIES","options","import_gantt_core"]}