@jaeungkim/gantt-chart 0.3.1 → 1.0.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +222 -124
  3. package/dist/Gantt.d.ts +5 -0
  4. package/dist/bars/components/GanttBar.d.ts +20 -0
  5. package/dist/bars/components/GanttBarsLayer.d.ts +24 -0
  6. package/dist/bars/components/GanttDragGuides.d.ts +1 -0
  7. package/dist/bars/hooks/useGanttBarDrag.d.ts +16 -0
  8. package/dist/bars/hooks/useGanttDrawCreate.d.ts +25 -0
  9. package/dist/bars/hooks/useGanttProgressDrag.d.ts +11 -0
  10. package/dist/core/calendar.d.ts +27 -0
  11. package/dist/core/dates.d.ts +16 -0
  12. package/dist/core/index.d.ts +3 -0
  13. package/dist/core/reorder.d.ts +55 -0
  14. package/dist/core/tree.d.ts +34 -0
  15. package/dist/core/types.d.ts +43 -0
  16. package/dist/dependencies/components/GanttDependencyArrows.d.ts +13 -0
  17. package/dist/dependencies/hooks/useGanttLinkDrag.d.ts +20 -0
  18. package/dist/dependencies/utils/arrowPath.d.ts +20 -0
  19. package/dist/dependencies/utils/link.d.ts +17 -0
  20. package/dist/detail/components/GanttDetailPanel.d.ts +21 -0
  21. package/dist/detail/hooks/useGanttDetail.d.ts +42 -0
  22. package/dist/detail/utils/edit.d.ts +21 -0
  23. package/dist/gantt-chart.css +1 -1
  24. package/dist/index.cjs +1 -0
  25. package/dist/index.d.cts +11 -0
  26. package/dist/index.d.ts +11 -51
  27. package/dist/index.js +4749 -0
  28. package/dist/interaction/hooks/useGanttInteraction.d.ts +2 -0
  29. package/dist/interaction/hooks/useGanttKeyboardNav.d.ts +33 -0
  30. package/dist/interaction/hooks/useGanttSelection.d.ts +12 -0
  31. package/dist/interaction/utils/a11y.d.ts +84 -0
  32. package/dist/props.d.ts +121 -0
  33. package/dist/rows/components/GanttRowsLayer.d.ts +13 -0
  34. package/dist/rows/hooks/useGanttCollapse.d.ts +18 -0
  35. package/dist/rows/hooks/useGanttRowModel.d.ts +19 -0
  36. package/dist/rows/utils/rows.d.ts +21 -0
  37. package/dist/shared/constants.d.ts +24 -0
  38. package/dist/shared/context.d.ts +4 -0
  39. package/dist/shared/hooks/useLatestRef.d.ts +2 -0
  40. package/dist/shared/hooks/useResolvedTheme.d.ts +8 -0
  41. package/dist/shared/store.d.ts +81 -0
  42. package/dist/shared/task.d.ts +55 -0
  43. package/dist/shared/types.d.ts +115 -0
  44. package/dist/shared/utils/holidays.d.ts +12 -0
  45. package/dist/shared/utils/i18n.d.ts +5 -0
  46. package/dist/shared/utils/pointerGesture.d.ts +11 -0
  47. package/dist/shared/virtual/axis.d.ts +13 -0
  48. package/dist/shared/virtual/useVirtualWindow.d.ts +16 -0
  49. package/dist/shared/virtual/window.d.ts +30 -0
  50. package/dist/task-list/components/GanttGridSplitter.d.ts +6 -0
  51. package/dist/task-list/components/GanttTaskAddRow.d.ts +7 -0
  52. package/dist/task-list/components/GanttTaskGrid.d.ts +24 -0
  53. package/dist/task-list/hooks/useGanttRowDrag.d.ts +17 -0
  54. package/dist/task-list/hooks/useGanttTaskListPane.d.ts +11 -0
  55. package/dist/task-list/hooks/useGanttTaskMove.d.ts +16 -0
  56. package/dist/timeline/components/GanttChartHeader.d.ts +10 -0
  57. package/dist/timeline/components/GanttHolidayLabels.d.ts +6 -0
  58. package/dist/timeline/components/GanttNonWorkingLayer.d.ts +6 -0
  59. package/dist/timeline/components/GanttTodayLine.d.ts +6 -0
  60. package/dist/timeline/hooks/useGanttScrollApi.d.ts +62 -0
  61. package/dist/timeline/hooks/useGanttViewport.d.ts +47 -0
  62. package/dist/timeline/hooks/useGanttVirtualization.d.ts +28 -0
  63. package/dist/timeline/utils/geometry.d.ts +52 -0
  64. package/dist/timeline/utils/header.d.ts +8 -0
  65. package/dist/timeline/utils/transform.d.ts +4 -0
  66. package/dist/timeline/utils/viewport.d.ts +31 -0
  67. package/dist/useGanttSelectors.d.ts +11 -0
  68. package/package.json +53 -38
  69. package/dist/index.cjs.js +0 -4
  70. package/dist/index.es.js +0 -2394
  71. package/dist/readmeImg.png +0 -0
@@ -0,0 +1,11 @@
1
+ export declare const TOUCH_LONG_PRESS_MS = 400;
2
+ export declare const TOUCH_SLOP_PX = 10;
3
+ interface PointerGestureStart {
4
+ pointerType: string;
5
+ pointerId: number;
6
+ clientX: number;
7
+ clientY: number;
8
+ }
9
+ export declare function armPointerGesture(start: PointerGestureStart, onStart: (clientX: number, clientY: number) => void, target?: EventTarget): (() => void) | null;
10
+ export declare function suppressTouchScroll(): () => void;
11
+ export {};
@@ -0,0 +1,13 @@
1
+ export interface VirtualAxis {
2
+ count: number;
3
+ /** Size of the whole axis (px) */
4
+ total: number;
5
+ sizeAt: (index: number) => number;
6
+ /** Pixels before `index` starts */
7
+ offsetAt: (index: number) => number;
8
+ /** Index of the item covering `px`, clamped to the axis */
9
+ indexAt: (px: number) => number;
10
+ }
11
+ export declare function fixedAxis(count: number, size: number): VirtualAxis;
12
+ export declare function variableAxis(count: number, sizeAt: (index: number) => number): VirtualAxis;
13
+ export declare function axisOf(count: number, size: number | ArrayLike<number>, fallback?: number): VirtualAxis;
@@ -0,0 +1,16 @@
1
+ import { RefObject } from 'react';
2
+ import { VirtualAxis } from './axis';
3
+ import { VirtualWindow } from './window';
4
+ export type ScrollAlign = 'start' | 'center' | 'end' | 'auto';
5
+ interface UseVirtualWindowParams {
6
+ scrollRef: RefObject<HTMLElement | null>;
7
+ row: VirtualAxis;
8
+ col: VirtualAxis;
9
+ }
10
+ interface VirtualWindows {
11
+ row: VirtualWindow;
12
+ col: VirtualWindow;
13
+ scrollToRow: (index: number, align?: ScrollAlign) => void;
14
+ }
15
+ export declare function useVirtualWindow({ scrollRef, row, col, }: UseVirtualWindowParams): VirtualWindows;
16
+ export {};
@@ -0,0 +1,30 @@
1
+ import { VirtualAxis } from './axis';
2
+ export declare const MIN_VIRTUAL_COUNT = 24;
3
+ export interface VirtualWindow {
4
+ /** First index to render */
5
+ start: number;
6
+ /** Last index to render, inclusive - `-1` when the axis is empty */
7
+ end: number;
8
+ /** Pixels before `start` */
9
+ padStart: number;
10
+ /** Pixels after `end` */
11
+ padEnd: number;
12
+ /** False when the whole axis is being rendered */
13
+ virtualized: boolean;
14
+ }
15
+ export interface VirtualItem {
16
+ index: number;
17
+ key: number;
18
+ start: number;
19
+ end: number;
20
+ size: number;
21
+ }
22
+ export type ScrollDirection = -1 | 0 | 1;
23
+ export declare function fullWindow(count: number): VirtualWindow;
24
+ export declare function windowOf(axis: VirtualAxis, scroll: number, viewport: number, overscan?: number, direction?: ScrollDirection): VirtualWindow;
25
+ export declare function virtualItemsOf(axis: VirtualAxis, window: VirtualWindow): VirtualItem[];
26
+ export declare function windowBounds(axis: VirtualAxis, window: VirtualWindow): {
27
+ startPx: number;
28
+ endPx: number;
29
+ };
30
+ export declare function sameWindow(a: VirtualWindow, b: VirtualWindow): boolean;
@@ -0,0 +1,6 @@
1
+ interface GanttGridSplitterProps {
2
+ width: number;
3
+ onWidthChange: (width: number) => void;
4
+ }
5
+ export default function GanttGridSplitter({ width, onWidthChange, }: GanttGridSplitterProps): import("react").JSX.Element;
6
+ export {};
@@ -0,0 +1,7 @@
1
+ interface GanttTaskAddRowProps {
2
+ width: number;
3
+ /** Proposes the new task - the same thing `addTask()` on the chart ref calls */
4
+ onAdd: () => void;
5
+ }
6
+ export default function GanttTaskAddRow({ width, onAdd, }: GanttTaskAddRowProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,24 @@
1
+ import { VirtualItem } from '../../shared/virtual/window';
2
+ import { GanttTaskMoveApi } from '../hooks/useGanttTaskMove';
3
+ import { GanttInteractionConfig, TaskTransformed } from '../../shared/task';
4
+ import { GanttFocus } from '../../interaction/utils/a11y';
5
+ import { GanttRow } from '../../rows/utils/rows';
6
+ interface GanttTaskGridProps {
7
+ rows: GanttRow[];
8
+ virtualItems: VirtualItem[];
9
+ totalHeight: number;
10
+ width: number;
11
+ showRowNumbers: boolean;
12
+ hierarchy: boolean;
13
+ collapsedIds: ReadonlySet<string>;
14
+ onToggleCollapse: (rowId: string) => void;
15
+ focus: GanttFocus;
16
+ reorderEnabled: boolean;
17
+ interaction: GanttInteractionConfig;
18
+ move: GanttTaskMoveApi;
19
+ selectedTaskId?: string | null;
20
+ onRowClick?: (task: TaskTransformed, event: React.MouseEvent) => void;
21
+ onRowDoubleClick?: (task: TaskTransformed, event: React.MouseEvent) => void;
22
+ }
23
+ export default function GanttTaskGrid({ rows, virtualItems, totalHeight, width, showRowNumbers, hierarchy, collapsedIds, onToggleCollapse, focus, reorderEnabled, interaction, move, selectedTaskId, onRowClick, onRowDoubleClick, }: GanttTaskGridProps): import("react").JSX.Element;
24
+ export {};
@@ -0,0 +1,17 @@
1
+ import { VirtualItem } from '../../shared/virtual/window';
2
+ import { RefObject } from 'react';
3
+ import { GanttTaskMoveApi } from './useGanttTaskMove';
4
+ import { GanttReorderDraft } from '../../shared/store';
5
+ import { GanttRow } from '../../rows/utils/rows';
6
+ interface UseGanttRowDragParams {
7
+ rows: GanttRow[];
8
+ virtualItems: VirtualItem[];
9
+ bodyRef: RefObject<HTMLDivElement | null>;
10
+ hierarchy: boolean;
11
+ move: GanttTaskMoveApi;
12
+ }
13
+ export declare function useGanttRowDrag({ rows, virtualItems, bodyRef, hierarchy, move, }: UseGanttRowDragParams): {
14
+ onGripPointerDown: (rowIndex: number, event: React.PointerEvent) => void;
15
+ draft: GanttReorderDraft | null;
16
+ };
17
+ export {};
@@ -0,0 +1,11 @@
1
+ interface UseGanttTaskListPaneParams {
2
+ showTaskList?: boolean;
3
+ }
4
+ interface GanttTaskListPane {
5
+ width: number;
6
+ setWidth: (width: number) => void;
7
+ visible: boolean;
8
+ inset: number;
9
+ }
10
+ export declare function useGanttTaskListPane({ showTaskList, }: UseGanttTaskListPaneParams): GanttTaskListPane;
11
+ export {};
@@ -0,0 +1,16 @@
1
+ import { GanttMoveRejection, GanttTaskMove, GanttTaskMoveChange } from '../../core/reorder';
2
+ import { GanttInteractionConfig, Task } from '../../shared/task';
3
+ interface UseGanttTaskMoveParams {
4
+ hierarchy: boolean;
5
+ interaction: GanttInteractionConfig;
6
+ collapsedIds: ReadonlySet<string>;
7
+ onTasksChange?: (tasks: Task[]) => void;
8
+ onTaskMove?: (change: GanttTaskMoveChange) => boolean | void;
9
+ onExpand?: (rowId: string) => void;
10
+ }
11
+ export interface GanttTaskMoveApi {
12
+ validate: (move: GanttTaskMove) => GanttMoveRejection | null;
13
+ apply: (move: GanttTaskMove) => boolean;
14
+ }
15
+ export declare function useGanttTaskMove({ hierarchy, interaction, collapsedIds, onTasksChange, onTaskMove, onExpand, }: UseGanttTaskMoveParams): GanttTaskMoveApi;
16
+ export {};
@@ -0,0 +1,10 @@
1
+ import { GanttBottomRowCell, GanttScaleKey } from '../../shared/types';
2
+ import { GanttVirtualization } from '../hooks/useGanttVirtualization';
3
+ interface GanttChartHeaderProps {
4
+ bottomRowCells: GanttBottomRowCell[];
5
+ selectedScale: GanttScaleKey;
6
+ width: number;
7
+ virtual: GanttVirtualization;
8
+ }
9
+ declare function GanttChartHeader({ bottomRowCells, selectedScale, width, virtual, }: GanttChartHeaderProps): import("react").JSX.Element;
10
+ export default GanttChartHeader;
@@ -0,0 +1,6 @@
1
+ import { NonWorkingRange } from '../utils/geometry';
2
+ interface GanttHolidayLabelsProps {
3
+ ranges: NonWorkingRange[];
4
+ }
5
+ export default function GanttHolidayLabels({ ranges, }: GanttHolidayLabelsProps): import("react").JSX.Element | null;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ import { NonWorkingRange } from '../utils/geometry';
2
+ interface GanttNonWorkingLayerProps {
3
+ ranges: NonWorkingRange[];
4
+ }
5
+ export default function GanttNonWorkingLayer({ ranges, }: GanttNonWorkingLayerProps): import("react").JSX.Element | null;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ export declare function GanttTodayLine({ leftPx }: {
2
+ leftPx: number | null;
3
+ }): import("react").JSX.Element | null;
4
+ export declare function GanttTodayDot({ leftPx }: {
5
+ leftPx: number | null;
6
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,62 @@
1
+ import { Dayjs } from 'dayjs';
2
+ import { RefObject } from 'react';
3
+ import { GanttBottomRowCell, GanttScaleKey } from '../../shared/types';
4
+ import { TaskTransformed } from '../../shared/task';
5
+ /** Options for the scrollTo* methods */
6
+ export interface GanttScrollOptions {
7
+ /** Whether to animate the scroll (default true) */
8
+ smooth?: boolean;
9
+ /** Where the target lands inside the viewport (default 'center') */
10
+ align?: "start" | "center";
11
+ }
12
+ /** A date pinned at a fixed distance from the timeline's visible left edge */
13
+ export interface GanttZoomAnchor {
14
+ date: Dayjs;
15
+ /** px from the left edge of the timeline area (the task list pane excluded) */
16
+ viewportX: number;
17
+ }
18
+ /** Imperative scroll and zoom API */
19
+ export interface GanttScrollApi {
20
+ /** Scroll horizontally to a given date */
21
+ scrollToDate: (date: string | Date | Dayjs, options?: GanttScrollOptions) => void;
22
+ /** Scroll horizontally to today */
23
+ scrollToToday: (options?: GanttScrollOptions) => void;
24
+ /** Scroll horizontally and vertically to a given task */
25
+ scrollToTask: (taskId: string, options?: GanttScrollOptions) => void;
26
+ /** Switches the scale, keeping the centre date centred; an unknown key is ignored */
27
+ setScale: (scale: GanttScaleKey) => void;
28
+ /** Switches to the finest scale the whole project fits at and scrolls it into view (no-op with no tasks) */
29
+ zoomToFit: () => void;
30
+ /** The scroll container DOM node (null when unavailable) */
31
+ getScrollElement: () => HTMLDivElement | null;
32
+ }
33
+ /** Opening and closing the detail panel from outside the chart */
34
+ export interface GanttDetailApi {
35
+ /** Opens the detail panel on a task; unknown ids and a panel-less chart (no `renderDetail`/`showDetail`) are ignored */
36
+ openDetail: (taskId: string) => void;
37
+ /** Closes the detail panel */
38
+ closeDetail: () => void;
39
+ }
40
+ /** Proposing a new task from outside the chart */
41
+ export interface GanttTaskCreateApi {
42
+ /** Sends a one-tick draft at today to `onTaskCreate`, as the "Add task" button does; no-op without `onTaskCreate` or with `allowTaskCreate` false */
43
+ addTask: () => void;
44
+ }
45
+ /** Imperative API exposed through the ref */
46
+ export interface GanttHandle extends GanttScrollApi, GanttDetailApi, GanttTaskCreateApi {
47
+ }
48
+ interface UseGanttScrollApiParams {
49
+ scrollRef: RefObject<HTMLDivElement | null>;
50
+ bottomRowCells: GanttBottomRowCell[];
51
+ transformedTasks: TaskTransformed[];
52
+ selectedScale: GanttScaleKey;
53
+ rowHeight: number;
54
+ /** Width of the pinned task list (default 0) - centering measures against the narrowed viewport */
55
+ viewportInsetPx?: number;
56
+ /** Switches scale while keeping the anchor date where it is on screen */
57
+ zoomTo: (scale: GanttScaleKey, anchor: GanttZoomAnchor) => void;
58
+ /** Sets the scale with no anchor - the fallback when there is nothing on screen to pin */
59
+ setSelectedScale: (scale: GanttScaleKey) => void;
60
+ }
61
+ export declare function useGanttScrollApi({ scrollRef, bottomRowCells, transformedTasks, selectedScale, rowHeight, viewportInsetPx, zoomTo, setSelectedScale, }: UseGanttScrollApiParams): GanttScrollApi;
62
+ export {};
@@ -0,0 +1,47 @@
1
+ import { RefObject } from 'react';
2
+ import { GanttScrollApi, GanttZoomAnchor } from './useGanttScrollApi';
3
+ import { GanttBottomRowCell, GanttDateRange, GanttRangeExtension, GanttScaleKey, GanttVisibleRange } from '../../shared/types';
4
+ import { Task } from '../../shared/task';
5
+ interface UseGanttRangeExtensionParams {
6
+ /** Off (the default `infiniteScroll`), the timeline never grows past its tasks */
7
+ enabled: boolean;
8
+ scrollRef: RefObject<HTMLDivElement | null>;
9
+ selectedScale: GanttScaleKey;
10
+ bottomRowCells: GanttBottomRowCell[];
11
+ totalWidth: number;
12
+ /** Width of the pinned task list, which the viewport does not extend into */
13
+ viewportInsetPx: number;
14
+ /** A pinned end is where the host put it - growing past it would be undone on every recompute */
15
+ pinnedStart: boolean;
16
+ pinnedEnd: boolean;
17
+ }
18
+ export declare function useGanttRangeExtension({ enabled, scrollRef, selectedScale, bottomRowCells, totalWidth, viewportInsetPx, pinnedStart, pinnedEnd, }: UseGanttRangeExtensionParams): GanttRangeExtension;
19
+ interface UseGanttTimelineSyncParams {
20
+ rawTasks: Task[];
21
+ selectedScale: GanttScaleKey;
22
+ /** Pinned window, or undefined to fit the timeline to the tasks */
23
+ visibleRange: GanttVisibleRange | undefined;
24
+ hierarchy: boolean;
25
+ extension: GanttRangeExtension;
26
+ scrollRef: RefObject<HTMLDivElement | null>;
27
+ bottomRowCells: GanttBottomRowCell[];
28
+ }
29
+ export declare function useGanttTimelineSync({ rawTasks, selectedScale, visibleRange, hierarchy, extension, scrollRef, bottomRowCells, }: UseGanttTimelineSyncParams): (scale: GanttScaleKey, anchor: GanttZoomAnchor) => void;
30
+ interface UseGanttWheelZoomParams {
31
+ /** Off (the default `zoomOnWheel`), ctrl/cmd + wheel is left to the browser */
32
+ enabled: boolean;
33
+ scrollRef: RefObject<HTMLDivElement | null>;
34
+ selectedScale: GanttScaleKey;
35
+ bottomRowCells: GanttBottomRowCell[];
36
+ /** Width of the pinned task list, which the timeline's own left edge starts after */
37
+ viewportInsetPx: number;
38
+ zoomTo: (scale: GanttScaleKey, anchor: GanttZoomAnchor) => void;
39
+ }
40
+ /** Ctrl/Cmd + wheel steps through the scale ladder, keeping the date under the cursor */
41
+ export declare function useGanttWheelZoom({ enabled, scrollRef, selectedScale, bottomRowCells, viewportInsetPx, zoomTo, }: UseGanttWheelZoomParams): void;
42
+ export declare function useGanttScaleReport(selectedScale: GanttScaleKey, onScaleChange?: (scale: GanttScaleKey) => void): void;
43
+ /** Reports the rendered timeline range - the hook a host lazy-loads tasks from */
44
+ export declare function useGanttRangeReport(bottomRowCells: GanttBottomRowCell[], selectedScale: GanttScaleKey, onRangeChange?: (range: GanttDateRange) => void): void;
45
+ /** Scrolls to `initialScrollTo` once, when the timeline first becomes ready */
46
+ export declare function useGanttInitialScroll(initialScrollTo: "today" | string | undefined, bottomRowCells: GanttBottomRowCell[], scrollApi: GanttScrollApi): void;
47
+ export {};
@@ -0,0 +1,28 @@
1
+ import { RefObject } from 'react';
2
+ import { GanttBottomRowCell } from '../../shared/types';
3
+ import { ScrollAlign } from '../../shared/virtual/useVirtualWindow';
4
+ import { VirtualItem } from '../../shared/virtual/window';
5
+ interface UseGanttVirtualizationParams {
6
+ /** Number of rows on screen - not the task count, since a lane can share one row */
7
+ rowCount: number;
8
+ bottomRowCells: GanttBottomRowCell[];
9
+ scrollRef: RefObject<HTMLDivElement | null>;
10
+ }
11
+ export interface GanttVirtualization {
12
+ /** Rows to render, already positioned */
13
+ virtualRows: VirtualItem[];
14
+ /** Height of all rows, culled ones included - the scrollable content height */
15
+ totalHeight: number;
16
+ /** Time cells to render, already positioned */
17
+ virtualCells: VirtualItem[];
18
+ /** Width of the cells skipped before the first rendered one (px) */
19
+ leadingCellPx: number;
20
+ /** Vertical bounds of the row window (px) - what the arrows cull against */
21
+ rowStartPx: number;
22
+ rowEndPx: number;
23
+ /** Horizontal culling, shared by the header, the bars and the arrows */
24
+ isBarVisible: (barLeft: number, barWidth: number) => boolean;
25
+ scrollToRow: (index: number, align?: ScrollAlign) => void;
26
+ }
27
+ export declare function useGanttVirtualization({ rowCount, bottomRowCells, scrollRef, }: UseGanttVirtualizationParams): GanttVirtualization;
28
+ export {};
@@ -0,0 +1,52 @@
1
+ import { Dayjs } from 'dayjs';
2
+ import { GanttBottomRowCell, GanttDateRange, GanttDragBounds, GanttDragMode, GanttLocaleOptions, GanttRangeExtension, GanttScaleKey, GanttTopHeaderGroup, GanttVisibleRange } from '../../shared/types';
3
+ import { Task, TaskTransformed } from '../../shared/task';
4
+ interface TimelineData {
5
+ bottomCells: GanttBottomRowCell[];
6
+ transformedTasks: TaskTransformed[];
7
+ }
8
+ /** The identity of a day that is off with nothing else said about it - no name, no colour. */
9
+ export declare const OFF_DAY_KEY = "off";
10
+ /** What one non-working day is, as far as the shading is concerned. */
11
+ export interface NonWorkingDay {
12
+ /** Adjacent days merge only when this matches - a named holiday must not fuse with a Saturday */
13
+ key: string;
14
+ label?: string;
15
+ color?: string;
16
+ }
17
+ export interface NonWorkingRange {
18
+ left: number;
19
+ width: number;
20
+ label?: string;
21
+ color?: string;
22
+ }
23
+ export declare function originShiftPx(prevTicks: GanttBottomRowCell[], nextTicks: GanttBottomRowCell[], scaleKey: GanttScaleKey): number;
24
+ export declare function computeNonWorkingRanges(timelineTicks: GanttBottomRowCell[], scaleKey: GanttScaleKey, nonWorkingDayAt: (date: Dayjs) => NonWorkingDay | null): NonWorkingRange[];
25
+ export declare function shiftByDragSteps(date: Dayjs, steps: number, scaleKey: GanttScaleKey): Dayjs;
26
+ export declare function pxBetweenDates(from: Dayjs, to: Dayjs, scaleKey: GanttScaleKey): number;
27
+ export declare function clampDragDates(mode: GanttDragMode, startDate: Dayjs, endDate: Dayjs, bounds: GanttDragBounds, scaleKey: GanttScaleKey): {
28
+ startDate: Dayjs;
29
+ endDate: Dayjs;
30
+ };
31
+ export declare function clampMoveDelta(members: {
32
+ start: Dayjs;
33
+ end: Dayjs;
34
+ bounds: GanttDragBounds;
35
+ }[], requestedMs: number, scaleKey: GanttScaleKey): number;
36
+ export declare function calculateDateOffsets(startDate: Dayjs, endDate: Dayjs, timelineTicks: GanttBottomRowCell[], scaleKey: GanttScaleKey): {
37
+ barMarginLeftAmount: number;
38
+ barWidthSize: number;
39
+ };
40
+ export declare function calculateDateOffsetPx(date: Dayjs, timelineTicks: GanttBottomRowCell[], scaleKey: GanttScaleKey): number | null;
41
+ export declare function dateAtOffsetPx(offsetPx: number, timelineTicks: GanttBottomRowCell[], scaleKey: GanttScaleKey): Dayjs | null;
42
+ export declare function timelineRange(timelineTicks: GanttBottomRowCell[], scaleKey: GanttScaleKey): GanttDateRange | null;
43
+ interface DrawnRange {
44
+ startDate: Dayjs;
45
+ endDate: Dayjs;
46
+ leftPx: number;
47
+ widthPx: number;
48
+ }
49
+ export declare function snapDrawnRange(startPx: number, endPx: number, timelineTicks: GanttBottomRowCell[], scaleKey: GanttScaleKey): DrawnRange | null;
50
+ export declare function createTopHeaderGroups(bottomCells: GanttBottomRowCell[], selectedScale: GanttScaleKey, localeOptions?: GanttLocaleOptions): GanttTopHeaderGroup[];
51
+ export declare function computeTimelineData(rawTasks: Task[], selectedScale: GanttScaleKey, visibleRange?: GanttVisibleRange, hierarchy?: boolean, extension?: GanttRangeExtension): TimelineData;
52
+ export {};
@@ -0,0 +1,8 @@
1
+ import { GanttBottomRowCell, GanttTopHeaderGroup } from '../../shared/types';
2
+ export declare function mergeHeaderGroups(groups: GanttTopHeaderGroup[]): GanttTopHeaderGroup[];
3
+ export declare function tickBoundaries(cells: GanttBottomRowCell[]): number[];
4
+ export declare function tickCellAt(boundaries: number[], x: number): {
5
+ index: number;
6
+ left: number;
7
+ width: number;
8
+ } | null;
@@ -0,0 +1,4 @@
1
+ import { GanttBottomRowCell, GanttScaleKey } from '../../shared/types';
2
+ import { Task, TaskTransformed } from '../../shared/task';
3
+ import { TaskTree } from '../../core/tree';
4
+ export declare function transformTasks(tasks: Task[], timelineTicks: GanttBottomRowCell[], selectedScale: GanttScaleKey, tree?: TaskTree): TaskTransformed[];
@@ -0,0 +1,31 @@
1
+ import { GanttRangeExtension, GanttScaleKey } from '../../shared/types';
2
+ export declare const SCALE_LADDER: GanttScaleKey[];
3
+ export declare function pxPerMs(scale: GanttScaleKey): number;
4
+ export declare function stepScale(scale: GanttScaleKey, direction: number): GanttScaleKey;
5
+ export declare function fitScale(durationMs: number, viewportPx: number): GanttScaleKey;
6
+ interface ZoomAccumulator {
7
+ delta: number;
8
+ lastEventAt: number;
9
+ locked: boolean;
10
+ }
11
+ export declare const INITIAL_ZOOM_ACCUMULATOR: ZoomAccumulator;
12
+ export declare function accumulateZoom(state: ZoomAccumulator, deltaY: number, now: number): {
13
+ state: ZoomAccumulator;
14
+ step: number;
15
+ };
16
+ export declare function edgeScrollVelocity(clientX: number, left: number, right: number): number;
17
+ export declare const NO_RANGE_EXTENSION: GanttRangeExtension;
18
+ export declare const MAX_RANGE_EXTENSION_TICKS = 2000;
19
+ interface ExtendRangeParams {
20
+ current: GanttRangeExtension;
21
+ scrollLeft: number;
22
+ viewportPx: number;
23
+ totalPx: number;
24
+ pxPerTick: number;
25
+ canExtend?: {
26
+ before: boolean;
27
+ after: boolean;
28
+ };
29
+ }
30
+ export declare function extendRangeForScroll({ current, scrollLeft, viewportPx, totalPx, pxPerTick, canExtend, }: ExtendRangeParams): GanttRangeExtension | null;
31
+ export {};
@@ -0,0 +1,11 @@
1
+ export declare function useGanttSelectors(): {
2
+ rawTasks: import('.').Task[];
3
+ transformedTasks: import('.').TaskTransformed[];
4
+ bottomRowCells: import('./shared/types').GanttBottomRowCell[];
5
+ selectedScale: import('.').GanttScaleKey;
6
+ selectedTaskId: string | null;
7
+ syncTasksFromProps: (rawTasks: import('.').Task[]) => void;
8
+ setSelectedScale: (scale: import('.').GanttScaleKey) => void;
9
+ setLocaleOptions: (options: import('./shared/types').GanttLocaleOptions | undefined) => void;
10
+ getTotalWidth: () => number;
11
+ };
package/package.json CHANGED
@@ -1,77 +1,92 @@
1
1
  {
2
2
  "name": "@jaeungkim/gantt-chart",
3
- "version": "0.3.1",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "type": "module",
6
- "main": "dist/index.cjs.js",
7
- "module": "dist/index.es.js",
8
- "types": "dist/index.d.ts",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.es.js",
13
- "require": "./dist/index.cjs.js"
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
14
19
  },
15
- "./style.css": "./dist/gantt-chart.css"
20
+ "./style.css": "./dist/gantt-chart.css",
21
+ "./package.json": "./package.json"
16
22
  },
17
23
  "files": [
18
24
  "dist",
19
25
  "README.md",
20
26
  "LICENSE"
21
27
  ],
22
- "description": "Lightweight React Gantt Chart component",
28
+ "description": "React Gantt chart with editable bars, dependency arrows, and headless date utilities",
23
29
  "keywords": [
24
30
  "gantt",
31
+ "gantt-chart",
25
32
  "chart",
33
+ "project-management",
26
34
  "react",
27
- "timeline"
35
+ "timeline",
36
+ "virtualized"
28
37
  ],
29
38
  "author": "jaeungkim",
30
39
  "license": "MIT",
31
40
  "repository": {
32
41
  "type": "git",
33
- "url": "https://github.com/jaeungkim/gantt-chart.git"
42
+ "url": "git+https://github.com/jaeungkim/gantt-chart.git"
34
43
  },
35
- "homepage": "https://github.com/jaeungkim/gantt-chart#readme",
44
+ "homepage": "https://gantt.jaeungkim.com",
36
45
  "bugs": {
37
46
  "url": "https://github.com/jaeungkim/gantt-chart/issues"
38
47
  },
39
48
  "scripts": {
40
- "dev": "vite",
41
- "build": "vite build",
42
- "preview": "vite preview",
43
- "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
44
- "lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"",
45
- "type-check": "tsc --noEmit"
49
+ "dev": "pnpm --filter @gantt-chart/site dev",
50
+ "build": "vite build && node -e \"require('fs').copyFileSync('dist/index.d.ts','dist/index.d.cts')\"",
51
+ "lint": "eslint .",
52
+ "lint:fix": "eslint . --fix",
53
+ "type-check": "tsc --noEmit",
54
+ "test": "vitest run",
55
+ "docs:build": "pnpm build && pnpm --filter @gantt-chart/site build"
46
56
  },
47
57
  "peerDependencies": {
48
58
  "react": "^18.0.0 || ^19.0.0",
49
59
  "react-dom": "^18.0.0 || ^19.0.0"
50
60
  },
51
61
  "dependencies": {
52
- "@tanstack/react-virtual": "^3.13.6",
53
- "dayjs": "^1.11.13",
54
- "zustand": "^5.0.3"
62
+ "dayjs": "^1.11.23",
63
+ "zustand": "^5.0.15"
55
64
  },
56
65
  "devDependencies": {
57
- "@eslint/js": "^9.21.0",
58
- "@types/node": "^22.13.7",
59
- "@types/react": "^19.0.10",
60
- "@types/react-dom": "^19.0.4",
61
- "@vitejs/plugin-react": "^4.3.4",
62
- "eslint": "^9.21.0",
66
+ "@eslint/js": "^9.39.5",
67
+ "@types/node": "^22.20.1",
68
+ "@types/react": "^19.2.18",
69
+ "@vitejs/plugin-react": "^4.7.0",
70
+ "eslint": "^9.39.5",
63
71
  "eslint-plugin-react": "^7.37.5",
64
- "eslint-plugin-react-hooks": "^5.1.0",
65
- "eslint-plugin-react-refresh": "^0.4.19",
72
+ "eslint-plugin-react-hooks": "^7.1.1",
73
+ "eslint-plugin-react-refresh": "^0.5.5",
66
74
  "globals": "^15.15.0",
67
- "react": "^19.1.1",
68
- "react-dom": "^19.1.1",
69
- "typescript": "~5.7.2",
70
- "typescript-eslint": "^8.24.1",
71
- "vite": "^6.2.3",
72
- "vite-plugin-dts": "^4.5.4",
73
- "vite-plugin-svgr": "^4.3.0",
74
- "vite-tsconfig-paths": "^5.1.4"
75
+ "react": "^19.2.8",
76
+ "react-dom": "^19.2.8",
77
+ "typescript": "~5.7.3",
78
+ "typescript-eslint": "^8.69.0",
79
+ "vite": "^6.4.3",
80
+ "vite-plugin-dts": "^5.1.0",
81
+ "vite-tsconfig-paths": "^6.1.1",
82
+ "vitest": "^4.1.11"
75
83
  },
76
- "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
84
+ "packageManager": "pnpm@10.30.3",
85
+ "pnpm": {
86
+ "overrides": {
87
+ "@rushstack/node-core-library>ajv": ">=8.18.0",
88
+ "@microsoft/api-extractor>lodash": ">=4.18.0",
89
+ "@microsoft/api-extractor>minimatch": ">=10.2.3"
90
+ }
91
+ }
77
92
  }