@xpyjs/gantt-react 0.0.1-alpha.1
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 +21 -0
- package/README.md +219 -0
- package/dist/index.cjs +161 -0
- package/dist/index.d.ts +303 -0
- package/dist/index.js +153 -0
- package/dist/style.css +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jeremy Jone
|
|
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,219 @@
|
|
|
1
|
+
# @xpyjs/gantt-react
|
|
2
|
+
|
|
3
|
+
基于 [@xpyjs/gantt-core](../core/README.md) 的 React 甘特图组件。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @xpyjs/gantt-react
|
|
9
|
+
# 或
|
|
10
|
+
yarn add @xpyjs/gantt-react
|
|
11
|
+
# 或
|
|
12
|
+
pnpm add @xpyjs/gantt-react
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 基本使用
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React, { useRef } from 'react';
|
|
19
|
+
import { XGanttReact } from '@xpyjs/gantt-react';
|
|
20
|
+
import type { XGanttReactRef } from '@xpyjs/gantt-react';
|
|
21
|
+
|
|
22
|
+
function App() {
|
|
23
|
+
const ganttRef = useRef<XGanttReactRef>(null);
|
|
24
|
+
|
|
25
|
+
const data = [
|
|
26
|
+
{
|
|
27
|
+
id: '1',
|
|
28
|
+
name: '任务1',
|
|
29
|
+
startTime: '2024-01-01',
|
|
30
|
+
endTime: '2024-01-10',
|
|
31
|
+
progress: 50
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: '2',
|
|
35
|
+
name: '任务2',
|
|
36
|
+
startTime: '2024-01-05',
|
|
37
|
+
endTime: '2024-01-15',
|
|
38
|
+
progress: 30
|
|
39
|
+
}
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const handleTaskSelect = (data: any[], checked: boolean, all: any[]) => {
|
|
43
|
+
console.log('选择的任务:', data);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const jumpToToday = () => {
|
|
47
|
+
ganttRef.current?.jumpTo();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div>
|
|
52
|
+
<button onClick={jumpToToday}>跳转到今天</button>
|
|
53
|
+
<XGanttReact
|
|
54
|
+
ref={ganttRef}
|
|
55
|
+
style={{ height: '500px', width: '100%' }}
|
|
56
|
+
options={{
|
|
57
|
+
data,
|
|
58
|
+
table: {
|
|
59
|
+
width: 300,
|
|
60
|
+
columns: [
|
|
61
|
+
{ field: 'name', label: '任务名称', width: 200 },
|
|
62
|
+
{ field: 'progress', label: '进度', width: 100 }
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}}
|
|
66
|
+
onSelect={handleTaskSelect}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default App;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 使用 Hooks
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import React from 'react';
|
|
79
|
+
import { XGanttReact, useXGantt, useGanttEvents } from '@xpyjs/gantt-react';
|
|
80
|
+
|
|
81
|
+
function MyGantt() {
|
|
82
|
+
const { ganttRef, jumpToToday, updateGanttOptions } = useXGantt();
|
|
83
|
+
const { onSelect, onClickRow, selectedTasks } = useGanttEvents();
|
|
84
|
+
|
|
85
|
+
const handleChangeUnit = () => {
|
|
86
|
+
updateGanttOptions({ unit: 'week' });
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div>
|
|
91
|
+
<div>
|
|
92
|
+
<button onClick={jumpToToday}>跳转到今天</button>
|
|
93
|
+
<button onClick={handleChangeUnit}>切换到周视图</button>
|
|
94
|
+
<span>已选择 {selectedTasks.length} 个任务</span>
|
|
95
|
+
</div>
|
|
96
|
+
<XGanttReact
|
|
97
|
+
ref={ganttRef}
|
|
98
|
+
style={{ height: '500px' }}
|
|
99
|
+
options={{ data: [] }}
|
|
100
|
+
onSelect={onSelect}
|
|
101
|
+
onClickRow={onClickRow}
|
|
102
|
+
/>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## API
|
|
109
|
+
|
|
110
|
+
### XGanttReact Props
|
|
111
|
+
|
|
112
|
+
| 属性 | 类型 | 必填 | 说明 |
|
|
113
|
+
|------|------|------|------|
|
|
114
|
+
| options | `IOptions` | ✓ | 甘特图配置选项,变化时自动更新甘特图 |
|
|
115
|
+
| className | `string` | - | 容器类名 |
|
|
116
|
+
| style | `React.CSSProperties` | - | 容器样式 |
|
|
117
|
+
| onError | `EventMap['error']` | - | 错误事件回调 |
|
|
118
|
+
| onUpdateLink | `EventMap['update:link']` | - | 关联线更新事件回调 |
|
|
119
|
+
| onCreateLink | `EventMap['create:link']` | - | 关联线创建事件回调 |
|
|
120
|
+
| onSelectLink | `EventMap['select:link']` | - | 关联线选择事件回调 |
|
|
121
|
+
| onSelect | `EventMap['select']` | - | 任务选择事件回调 |
|
|
122
|
+
| onClickRow | `EventMap['click:row']` | - | 行点击事件回调 |
|
|
123
|
+
| onDoubleClickRow | `EventMap['dblclick:row']` | - | 行双击事件回调 |
|
|
124
|
+
| onContextMenuRow | `EventMap['contextmenu:row']` | - | 行右键菜单事件回调 |
|
|
125
|
+
| onClickSlider | `EventMap['click:slider']` | - | 任务条点击事件回调 |
|
|
126
|
+
| onDoubleClickSlider | `EventMap['dblclick:slider']` | - | 任务条双击事件回调 |
|
|
127
|
+
| onContextMenuSlider | `EventMap['contextmenu:slider']` | - | 任务条右键菜单事件回调 |
|
|
128
|
+
| onMove | `EventMap['move']` | - | 任务移动事件回调 |
|
|
129
|
+
|
|
130
|
+
### XGanttReactRef 方法
|
|
131
|
+
|
|
132
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
133
|
+
|------|------|--------|------|
|
|
134
|
+
| getInstance | - | `XGantt \| null` | 获取甘特图核心实例,通过实例可调用所有核心方法 |
|
|
135
|
+
| jumpTo | `date?: any` | `boolean` | 跳转到指定日期(不传参数跳转到今天) |
|
|
136
|
+
|
|
137
|
+
> **注意**:为了简化API,`updateOptions` 和 `render` 方法已移除。options变化时会自动更新,其他操作请通过 `getInstance()` 获取核心实例进行操作。
|
|
138
|
+
|
|
139
|
+
### Hooks
|
|
140
|
+
|
|
141
|
+
#### useXGantt()
|
|
142
|
+
|
|
143
|
+
提供甘特图操作的便捷方法:
|
|
144
|
+
|
|
145
|
+
- `ganttRef`: 甘特图组件引用
|
|
146
|
+
- `getInstance()`: 获取核心实例
|
|
147
|
+
- `jumpToToday()`: 跳转到今天
|
|
148
|
+
- `jumpTo(date)`: 跳转到指定日期
|
|
149
|
+
|
|
150
|
+
> **变更说明**:已移除 `updateGanttOptions()` 和 `renderGantt()` 方法,请通过 `getInstance()` 获取核心实例进行操作。
|
|
151
|
+
|
|
152
|
+
#### useGanttEvents()
|
|
153
|
+
|
|
154
|
+
提供事件处理的便捷方法:
|
|
155
|
+
|
|
156
|
+
- `onSelect`: 选择事件处理器
|
|
157
|
+
- `onClickRow`: 行点击事件处理器
|
|
158
|
+
- `onMove`: 移动事件处理器
|
|
159
|
+
- `selectedTasks`: 已选择的任务
|
|
160
|
+
- `lastClickedRow`: 最后点击的行
|
|
161
|
+
- `movedTasks`: 移动的任务
|
|
162
|
+
|
|
163
|
+
## 使用核心实例进行高级操作
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import React, { useRef } from 'react';
|
|
167
|
+
import { XGanttReact, useXGantt } from '@xpyjs/gantt-react';
|
|
168
|
+
|
|
169
|
+
function AdvancedGantt() {
|
|
170
|
+
const { ganttRef, getInstance } = useXGantt();
|
|
171
|
+
|
|
172
|
+
const handleAdvancedOperation = () => {
|
|
173
|
+
const instance = getInstance();
|
|
174
|
+
if (instance) {
|
|
175
|
+
// 更新配置
|
|
176
|
+
instance.updateOptions({
|
|
177
|
+
unit: 'week',
|
|
178
|
+
primaryColor: '#007acc'
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// 手动渲染
|
|
182
|
+
instance.render();
|
|
183
|
+
|
|
184
|
+
// 其他核心方法
|
|
185
|
+
instance.jumpTo('2024-06-01');
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<div>
|
|
191
|
+
<button onClick={handleAdvancedOperation}>高级操作</button>
|
|
192
|
+
<XGanttReact ref={ganttRef} options={{ data: [] }} />
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## 类型定义
|
|
199
|
+
|
|
200
|
+
所有核心库的类型都可以从 `@xpyjs/gantt-react` 直接导入:
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import type {
|
|
204
|
+
IOptions,
|
|
205
|
+
ILink,
|
|
206
|
+
ErrorType,
|
|
207
|
+
EventMap,
|
|
208
|
+
XGanttReactProps,
|
|
209
|
+
XGanttReactRef
|
|
210
|
+
} from '@xpyjs/gantt-react';
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## 样式
|
|
214
|
+
|
|
215
|
+
组件已自动导入样式,无需手动引入。如需自定义样式,可以通过 CSS 变量或覆盖样式类来实现。
|
|
216
|
+
|
|
217
|
+
## 许可证
|
|
218
|
+
|
|
219
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const react = require("react");
|
|
5
|
+
const ganttCore = require("@xpyjs/gantt-core");
|
|
6
|
+
const XGanttReact = react.forwardRef(
|
|
7
|
+
(props, ref) => {
|
|
8
|
+
const {
|
|
9
|
+
options,
|
|
10
|
+
className,
|
|
11
|
+
style,
|
|
12
|
+
onError,
|
|
13
|
+
onUpdateLink,
|
|
14
|
+
onCreateLink,
|
|
15
|
+
onSelectLink,
|
|
16
|
+
onSelect,
|
|
17
|
+
onClickRow,
|
|
18
|
+
onDoubleClickRow,
|
|
19
|
+
onContextMenuRow,
|
|
20
|
+
onClickSlider,
|
|
21
|
+
onDoubleClickSlider,
|
|
22
|
+
onContextMenuSlider,
|
|
23
|
+
onMove,
|
|
24
|
+
...restProps
|
|
25
|
+
} = props;
|
|
26
|
+
const containerRef = react.useRef(null);
|
|
27
|
+
const ganttInstanceRef = react.useRef(null);
|
|
28
|
+
const registerEventListeners = react.useCallback(() => {
|
|
29
|
+
const instance = ganttInstanceRef.current;
|
|
30
|
+
if (!instance) return;
|
|
31
|
+
if (onError) {
|
|
32
|
+
instance.on("error", onError);
|
|
33
|
+
}
|
|
34
|
+
if (onUpdateLink) {
|
|
35
|
+
instance.on("update:link", onUpdateLink);
|
|
36
|
+
}
|
|
37
|
+
if (onCreateLink) {
|
|
38
|
+
instance.on("create:link", onCreateLink);
|
|
39
|
+
}
|
|
40
|
+
if (onSelectLink) {
|
|
41
|
+
instance.on("select:link", onSelectLink);
|
|
42
|
+
}
|
|
43
|
+
if (onSelect) {
|
|
44
|
+
instance.on("select", onSelect);
|
|
45
|
+
}
|
|
46
|
+
if (onClickRow) {
|
|
47
|
+
instance.on("click:row", onClickRow);
|
|
48
|
+
}
|
|
49
|
+
if (onDoubleClickRow) {
|
|
50
|
+
instance.on("dblclick:row", onDoubleClickRow);
|
|
51
|
+
}
|
|
52
|
+
if (onContextMenuRow) {
|
|
53
|
+
instance.on("contextmenu:row", onContextMenuRow);
|
|
54
|
+
}
|
|
55
|
+
if (onClickSlider) {
|
|
56
|
+
instance.on("click:slider", onClickSlider);
|
|
57
|
+
}
|
|
58
|
+
if (onDoubleClickSlider) {
|
|
59
|
+
instance.on("dblclick:slider", onDoubleClickSlider);
|
|
60
|
+
}
|
|
61
|
+
if (onContextMenuSlider) {
|
|
62
|
+
instance.on("contextmenu:slider", onContextMenuSlider);
|
|
63
|
+
}
|
|
64
|
+
if (onMove) {
|
|
65
|
+
instance.on("move", onMove);
|
|
66
|
+
}
|
|
67
|
+
}, [
|
|
68
|
+
onError,
|
|
69
|
+
onUpdateLink,
|
|
70
|
+
onCreateLink,
|
|
71
|
+
onSelectLink,
|
|
72
|
+
onSelect,
|
|
73
|
+
onClickRow,
|
|
74
|
+
onDoubleClickRow,
|
|
75
|
+
onContextMenuRow,
|
|
76
|
+
onClickSlider,
|
|
77
|
+
onDoubleClickSlider,
|
|
78
|
+
onContextMenuSlider,
|
|
79
|
+
onMove
|
|
80
|
+
]);
|
|
81
|
+
const initGantt = react.useCallback(() => {
|
|
82
|
+
if (!containerRef.current) return;
|
|
83
|
+
ganttInstanceRef.current = new ganttCore.XGantt(containerRef.current, options);
|
|
84
|
+
registerEventListeners();
|
|
85
|
+
}, [options, registerEventListeners]);
|
|
86
|
+
const jumpTo = react.useCallback((date) => {
|
|
87
|
+
if (ganttInstanceRef.current) {
|
|
88
|
+
return ganttInstanceRef.current.jumpTo(date);
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}, []);
|
|
92
|
+
const destroyGantt = react.useCallback(() => {
|
|
93
|
+
if (ganttInstanceRef.current) {
|
|
94
|
+
ganttInstanceRef.current.destroy();
|
|
95
|
+
ganttInstanceRef.current = null;
|
|
96
|
+
}
|
|
97
|
+
}, []);
|
|
98
|
+
react.useImperativeHandle(ref, () => ({
|
|
99
|
+
getInstance: () => ganttInstanceRef.current,
|
|
100
|
+
jumpTo
|
|
101
|
+
}), [jumpTo]);
|
|
102
|
+
react.useEffect(() => {
|
|
103
|
+
initGantt();
|
|
104
|
+
return () => {
|
|
105
|
+
destroyGantt();
|
|
106
|
+
};
|
|
107
|
+
}, []);
|
|
108
|
+
react.useEffect(() => {
|
|
109
|
+
if (ganttInstanceRef.current) {
|
|
110
|
+
ganttInstanceRef.current.updateOptions(options);
|
|
111
|
+
}
|
|
112
|
+
}, [options]);
|
|
113
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
114
|
+
"div",
|
|
115
|
+
{
|
|
116
|
+
ref: containerRef,
|
|
117
|
+
"data-testid": "x-gantt-container",
|
|
118
|
+
className: `x-gantt-container ${className || ""}`,
|
|
119
|
+
style: {
|
|
120
|
+
position: "relative",
|
|
121
|
+
width: "100%",
|
|
122
|
+
height: "100%",
|
|
123
|
+
...style
|
|
124
|
+
},
|
|
125
|
+
...restProps
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
XGanttReact.displayName = "XGanttReact";
|
|
131
|
+
function useXGantt() {
|
|
132
|
+
const ganttRef = react.useRef(null);
|
|
133
|
+
const getInstance = react.useCallback(() => {
|
|
134
|
+
var _a;
|
|
135
|
+
return ((_a = ganttRef.current) == null ? void 0 : _a.getInstance()) || null;
|
|
136
|
+
}, []);
|
|
137
|
+
const jumpTo = react.useCallback((date) => {
|
|
138
|
+
var _a;
|
|
139
|
+
return ((_a = ganttRef.current) == null ? void 0 : _a.jumpTo(date)) || false;
|
|
140
|
+
}, []);
|
|
141
|
+
return {
|
|
142
|
+
ganttRef,
|
|
143
|
+
getInstance,
|
|
144
|
+
jumpTo
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
Object.defineProperty(exports, "colorjs", {
|
|
148
|
+
enumerable: true,
|
|
149
|
+
get: () => ganttCore.colorjs
|
|
150
|
+
});
|
|
151
|
+
Object.defineProperty(exports, "dayjs", {
|
|
152
|
+
enumerable: true,
|
|
153
|
+
get: () => ganttCore.dayjs
|
|
154
|
+
});
|
|
155
|
+
Object.defineProperty(exports, "generateId", {
|
|
156
|
+
enumerable: true,
|
|
157
|
+
get: () => ganttCore.generateId
|
|
158
|
+
});
|
|
159
|
+
exports.XGanttReact = XGanttReact;
|
|
160
|
+
exports.default = XGanttReact;
|
|
161
|
+
exports.useXGantt = useXGantt;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { Colorjs } from '@xpyjs/gantt-core';
|
|
2
|
+
import { colorjs } from '@xpyjs/gantt-core';
|
|
3
|
+
import { Dayjs } from '@xpyjs/gantt-core';
|
|
4
|
+
import { dayjs } from '@xpyjs/gantt-core';
|
|
5
|
+
import { default as default_2 } from 'react';
|
|
6
|
+
import { EmitData } from '@xpyjs/gantt-core';
|
|
7
|
+
import { ErrorType } from '@xpyjs/gantt-core';
|
|
8
|
+
import { EventMap } from '@xpyjs/gantt-core';
|
|
9
|
+
import { generateId } from '@xpyjs/gantt-core';
|
|
10
|
+
import { ILink } from '@xpyjs/gantt-core';
|
|
11
|
+
import { IOptionConfig } from '@xpyjs/gantt-core';
|
|
12
|
+
import { IOptions } from '@xpyjs/gantt-core';
|
|
13
|
+
import { RefObject } from 'react';
|
|
14
|
+
import { XGantt } from '@xpyjs/gantt-core';
|
|
15
|
+
|
|
16
|
+
export { Colorjs }
|
|
17
|
+
|
|
18
|
+
export { colorjs }
|
|
19
|
+
|
|
20
|
+
export { Dayjs }
|
|
21
|
+
|
|
22
|
+
export { dayjs }
|
|
23
|
+
|
|
24
|
+
export { EmitData }
|
|
25
|
+
|
|
26
|
+
export { ErrorType }
|
|
27
|
+
|
|
28
|
+
export { EventMap }
|
|
29
|
+
|
|
30
|
+
export { generateId }
|
|
31
|
+
|
|
32
|
+
export { ILink }
|
|
33
|
+
|
|
34
|
+
export { IOptionConfig }
|
|
35
|
+
|
|
36
|
+
export { IOptions }
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 使用甘特图的 Hook
|
|
40
|
+
*
|
|
41
|
+
* @description 提供更便捷的甘特图操作方法
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* import React from 'react';
|
|
46
|
+
* import { XGanttReact, useXGantt } from '@xpyjs/gantt-react';
|
|
47
|
+
*
|
|
48
|
+
* function MyGantt() {
|
|
49
|
+
* const { ganttRef, getInstance, jumpTo } = useXGantt();
|
|
50
|
+
*
|
|
51
|
+
* const handleJumpToToday = () => {
|
|
52
|
+
* jumpTo(); // 没有参数,默认跳转到今天
|
|
53
|
+
* };
|
|
54
|
+
*
|
|
55
|
+
* const handleUpdateOptions = () => {
|
|
56
|
+
* const instance = getInstance();
|
|
57
|
+
* if (instance) {
|
|
58
|
+
* instance.updateOptions({ unit: 'week' });
|
|
59
|
+
* }
|
|
60
|
+
* };
|
|
61
|
+
*
|
|
62
|
+
* return (
|
|
63
|
+
* <div>
|
|
64
|
+
* <button onClick={handleJumpToToday}>跳转到今天</button>
|
|
65
|
+
* <button onClick={handleUpdateOptions}>切换到周视图</button>
|
|
66
|
+
* <XGanttReact
|
|
67
|
+
* ref={ganttRef}
|
|
68
|
+
* options={{ data: [] }}
|
|
69
|
+
* />
|
|
70
|
+
* </div>
|
|
71
|
+
* );
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function useXGantt(): {
|
|
76
|
+
ganttRef: RefObject<XGanttReactRef>;
|
|
77
|
+
getInstance: () => XGantt | null;
|
|
78
|
+
jumpTo: (date?: any) => boolean;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* XGantt React 组件
|
|
83
|
+
*
|
|
84
|
+
* @description 基于 `@xpyjs/gantt-core` 的 React 封装组件,提供完整的甘特图功能
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```tsx
|
|
88
|
+
* import React, { useRef } from 'react';
|
|
89
|
+
* import { XGanttReact } from '@xpyjs/gantt-react';
|
|
90
|
+
* import type { XGanttReactRef } from '@xpyjs/gantt-react';
|
|
91
|
+
*
|
|
92
|
+
* function App() {
|
|
93
|
+
* const ganttRef = useRef<XGanttReactRef>(null);
|
|
94
|
+
*
|
|
95
|
+
* const handleTaskSelect = (data: any[], checked: boolean, all: any[]) => {
|
|
96
|
+
* console.log('任务选择:', { data, checked, all });
|
|
97
|
+
* };
|
|
98
|
+
*
|
|
99
|
+
* const jumpToToday = () => {
|
|
100
|
+
* ganttRef.current?.jumpTo();
|
|
101
|
+
* };
|
|
102
|
+
*
|
|
103
|
+
* return (
|
|
104
|
+
* <div>
|
|
105
|
+
* <button onClick={jumpToToday}>跳转到今天</button>
|
|
106
|
+
* <XGanttReact
|
|
107
|
+
* ref={ganttRef}
|
|
108
|
+
* style={{ height: '500px', width: '100%' }}
|
|
109
|
+
* options={{
|
|
110
|
+
* data: [
|
|
111
|
+
* {
|
|
112
|
+
* id: '1',
|
|
113
|
+
* name: '任务1',
|
|
114
|
+
* startTime: '2024-01-01',
|
|
115
|
+
* endTime: '2024-01-10',
|
|
116
|
+
* progress: 50
|
|
117
|
+
* }
|
|
118
|
+
* ]
|
|
119
|
+
* }}
|
|
120
|
+
* onSelect={handleTaskSelect}
|
|
121
|
+
* />
|
|
122
|
+
* </div>
|
|
123
|
+
* );
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
declare const XGanttReact: default_2.ForwardRefExoticComponent<XGanttReactProps & default_2.RefAttributes<XGanttReactRef>>;
|
|
128
|
+
export { XGanttReact }
|
|
129
|
+
export default XGanttReact;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* XGanttReact 组件的 Props 类型
|
|
133
|
+
*/
|
|
134
|
+
export declare interface XGanttReactProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onError" | "onSelect" | "onClick" | "onDoubleClick" | "onContextMenu"> {
|
|
135
|
+
/**
|
|
136
|
+
* XGantt 图表的配置选项
|
|
137
|
+
*
|
|
138
|
+
* @description
|
|
139
|
+
* 该选项包含所有 XGantt 图表的配置参数,包括数据源、表格配置、图表配置、样式配置等
|
|
140
|
+
*/
|
|
141
|
+
options: IOptions;
|
|
142
|
+
/**
|
|
143
|
+
* 容器的 className
|
|
144
|
+
*/
|
|
145
|
+
className?: string;
|
|
146
|
+
/**
|
|
147
|
+
* 容器的样式
|
|
148
|
+
*/
|
|
149
|
+
style?: React.CSSProperties;
|
|
150
|
+
/**
|
|
151
|
+
* 错误事件回调
|
|
152
|
+
*
|
|
153
|
+
* @description 当甘特图发生错误时触发
|
|
154
|
+
* @param error 错误信息对象
|
|
155
|
+
*/
|
|
156
|
+
onError?: EventMap["error"];
|
|
157
|
+
/**
|
|
158
|
+
* 关联线更新事件回调
|
|
159
|
+
*
|
|
160
|
+
* @description 当关联线被更新时触发
|
|
161
|
+
* @param link 更新的关联线对象
|
|
162
|
+
*/
|
|
163
|
+
onUpdateLink?: EventMap["update:link"];
|
|
164
|
+
/**
|
|
165
|
+
* 关联线创建事件回调
|
|
166
|
+
*
|
|
167
|
+
* @description 当新建关联线时触发
|
|
168
|
+
* @param link 新创建的关联线对象
|
|
169
|
+
*/
|
|
170
|
+
onCreateLink?: EventMap["create:link"];
|
|
171
|
+
/**
|
|
172
|
+
* 关联线选择事件回调
|
|
173
|
+
*
|
|
174
|
+
* @description 当关联线的选择状态发生变化时触发
|
|
175
|
+
* @param add 新增选择的关联线
|
|
176
|
+
* @param cancel 取消选择的关联线
|
|
177
|
+
* @param all 所有当前选择的关联线
|
|
178
|
+
*/
|
|
179
|
+
onSelectLink?: EventMap["select:link"];
|
|
180
|
+
/**
|
|
181
|
+
* 任务选择事件回调
|
|
182
|
+
*
|
|
183
|
+
* @description 当任务的选择状态发生变化时触发
|
|
184
|
+
* @param data 当前操作的任务数据数组
|
|
185
|
+
* @param checked 是否为选中状态
|
|
186
|
+
* @param all 所有当前选择的任务数据数组
|
|
187
|
+
*/
|
|
188
|
+
onSelect?: EventMap["select"];
|
|
189
|
+
/**
|
|
190
|
+
* 行点击事件回调
|
|
191
|
+
*
|
|
192
|
+
* @description 当点击表格行时触发
|
|
193
|
+
* @param e 鼠标事件对象
|
|
194
|
+
* @param data 点击行对应的任务数据
|
|
195
|
+
*/
|
|
196
|
+
onClickRow?: EventMap["click:row"];
|
|
197
|
+
/**
|
|
198
|
+
* 行双击事件回调
|
|
199
|
+
*
|
|
200
|
+
* @description 当双击表格行时触发
|
|
201
|
+
* @param e 鼠标事件对象
|
|
202
|
+
* @param data 双击行对应的任务数据
|
|
203
|
+
*/
|
|
204
|
+
onDoubleClickRow?: EventMap["dblclick:row"];
|
|
205
|
+
/**
|
|
206
|
+
* 行右键菜单事件回调
|
|
207
|
+
*
|
|
208
|
+
* @description 当在表格行上右键点击时触发
|
|
209
|
+
* @param e 鼠标事件对象
|
|
210
|
+
* @param data 右键行对应的任务数据
|
|
211
|
+
*/
|
|
212
|
+
onContextMenuRow?: EventMap["contextmenu:row"];
|
|
213
|
+
/**
|
|
214
|
+
* 任务条点击事件回调
|
|
215
|
+
*
|
|
216
|
+
* @description 当点击甘特图中的任务条时触发
|
|
217
|
+
* @param e 鼠标事件对象
|
|
218
|
+
* @param data 点击任务条对应的任务数据
|
|
219
|
+
*/
|
|
220
|
+
onClickSlider?: EventMap["click:slider"];
|
|
221
|
+
/**
|
|
222
|
+
* 任务条双击事件回调
|
|
223
|
+
*
|
|
224
|
+
* @description 当双击甘特图中的任务条时触发
|
|
225
|
+
* @param e 鼠标事件对象
|
|
226
|
+
* @param data 双击任务条对应的任务数据
|
|
227
|
+
*/
|
|
228
|
+
onDoubleClickSlider?: EventMap["dblclick:slider"];
|
|
229
|
+
/**
|
|
230
|
+
* 任务条右键菜单事件回调
|
|
231
|
+
*
|
|
232
|
+
* @description 当在甘特图中的任务条上右键点击时触发
|
|
233
|
+
* @param e 鼠标事件对象
|
|
234
|
+
* @param data 右键任务条对应的任务数据
|
|
235
|
+
*/
|
|
236
|
+
onContextMenuSlider?: EventMap["contextmenu:slider"];
|
|
237
|
+
/**
|
|
238
|
+
* 任务移动事件回调
|
|
239
|
+
*
|
|
240
|
+
* @description 当任务被拖拽移动完成时触发
|
|
241
|
+
* @param data 移动的任务信息数组,包含新旧位置信息
|
|
242
|
+
*/
|
|
243
|
+
onMove?: EventMap["move"];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* XGanttReact 组件实例类型
|
|
248
|
+
*/
|
|
249
|
+
export declare interface XGanttReactRef {
|
|
250
|
+
/**
|
|
251
|
+
* 获取甘特图核心实例
|
|
252
|
+
*
|
|
253
|
+
* @description
|
|
254
|
+
* 获取底层的 XGantt 核心实例,通过实例可以调用所有核心方法
|
|
255
|
+
*
|
|
256
|
+
* @returns XGantt 核心实例,如果组件未初始化则返回 null
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```tsx
|
|
260
|
+
* const ganttRef = useRef<XGanttReactRef>(null);
|
|
261
|
+
*
|
|
262
|
+
* const handleGetInstance = () => {
|
|
263
|
+
* const instance = ganttRef.current?.getInstance();
|
|
264
|
+
* if (instance) {
|
|
265
|
+
* // 调用核心实例的方法
|
|
266
|
+
* instance.updateOptions({ unit: 'week' });
|
|
267
|
+
* instance.render();
|
|
268
|
+
* instance.destroy();
|
|
269
|
+
* }
|
|
270
|
+
* };
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
getInstance: () => XGantt | null;
|
|
274
|
+
/**
|
|
275
|
+
* 跳转到指定日期
|
|
276
|
+
*
|
|
277
|
+
* @description
|
|
278
|
+
* 将甘特图的视图跳转到指定日期位置,如果不传参数则跳转到今天
|
|
279
|
+
*
|
|
280
|
+
* @param date 要跳转的日期,支持多种格式:
|
|
281
|
+
* - 字符串:'2024-06-01'、'2024/06/01'
|
|
282
|
+
* - Date 对象:new Date()
|
|
283
|
+
* - Dayjs 对象:dayjs('2024-06-01')
|
|
284
|
+
* - undefined:跳转到今天
|
|
285
|
+
*
|
|
286
|
+
* @returns 是否成功跳转
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```tsx
|
|
290
|
+
* const ganttRef = useRef<XGanttReactRef>(null);
|
|
291
|
+
*
|
|
292
|
+
* // 跳转到今天
|
|
293
|
+
* ganttRef.current?.jumpTo();
|
|
294
|
+
*
|
|
295
|
+
* // 跳转到指定日期
|
|
296
|
+
* ganttRef.current?.jumpTo('2024-06-01');
|
|
297
|
+
* ganttRef.current?.jumpTo(new Date());
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
jumpTo: (date?: any) => boolean;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useRef, useCallback, useImperativeHandle, useEffect } from "react";
|
|
3
|
+
import { XGantt } from "@xpyjs/gantt-core";
|
|
4
|
+
import { colorjs, dayjs, generateId } from "@xpyjs/gantt-core";
|
|
5
|
+
const XGanttReact = forwardRef(
|
|
6
|
+
(props, ref) => {
|
|
7
|
+
const {
|
|
8
|
+
options,
|
|
9
|
+
className,
|
|
10
|
+
style,
|
|
11
|
+
onError,
|
|
12
|
+
onUpdateLink,
|
|
13
|
+
onCreateLink,
|
|
14
|
+
onSelectLink,
|
|
15
|
+
onSelect,
|
|
16
|
+
onClickRow,
|
|
17
|
+
onDoubleClickRow,
|
|
18
|
+
onContextMenuRow,
|
|
19
|
+
onClickSlider,
|
|
20
|
+
onDoubleClickSlider,
|
|
21
|
+
onContextMenuSlider,
|
|
22
|
+
onMove,
|
|
23
|
+
...restProps
|
|
24
|
+
} = props;
|
|
25
|
+
const containerRef = useRef(null);
|
|
26
|
+
const ganttInstanceRef = useRef(null);
|
|
27
|
+
const registerEventListeners = useCallback(() => {
|
|
28
|
+
const instance = ganttInstanceRef.current;
|
|
29
|
+
if (!instance) return;
|
|
30
|
+
if (onError) {
|
|
31
|
+
instance.on("error", onError);
|
|
32
|
+
}
|
|
33
|
+
if (onUpdateLink) {
|
|
34
|
+
instance.on("update:link", onUpdateLink);
|
|
35
|
+
}
|
|
36
|
+
if (onCreateLink) {
|
|
37
|
+
instance.on("create:link", onCreateLink);
|
|
38
|
+
}
|
|
39
|
+
if (onSelectLink) {
|
|
40
|
+
instance.on("select:link", onSelectLink);
|
|
41
|
+
}
|
|
42
|
+
if (onSelect) {
|
|
43
|
+
instance.on("select", onSelect);
|
|
44
|
+
}
|
|
45
|
+
if (onClickRow) {
|
|
46
|
+
instance.on("click:row", onClickRow);
|
|
47
|
+
}
|
|
48
|
+
if (onDoubleClickRow) {
|
|
49
|
+
instance.on("dblclick:row", onDoubleClickRow);
|
|
50
|
+
}
|
|
51
|
+
if (onContextMenuRow) {
|
|
52
|
+
instance.on("contextmenu:row", onContextMenuRow);
|
|
53
|
+
}
|
|
54
|
+
if (onClickSlider) {
|
|
55
|
+
instance.on("click:slider", onClickSlider);
|
|
56
|
+
}
|
|
57
|
+
if (onDoubleClickSlider) {
|
|
58
|
+
instance.on("dblclick:slider", onDoubleClickSlider);
|
|
59
|
+
}
|
|
60
|
+
if (onContextMenuSlider) {
|
|
61
|
+
instance.on("contextmenu:slider", onContextMenuSlider);
|
|
62
|
+
}
|
|
63
|
+
if (onMove) {
|
|
64
|
+
instance.on("move", onMove);
|
|
65
|
+
}
|
|
66
|
+
}, [
|
|
67
|
+
onError,
|
|
68
|
+
onUpdateLink,
|
|
69
|
+
onCreateLink,
|
|
70
|
+
onSelectLink,
|
|
71
|
+
onSelect,
|
|
72
|
+
onClickRow,
|
|
73
|
+
onDoubleClickRow,
|
|
74
|
+
onContextMenuRow,
|
|
75
|
+
onClickSlider,
|
|
76
|
+
onDoubleClickSlider,
|
|
77
|
+
onContextMenuSlider,
|
|
78
|
+
onMove
|
|
79
|
+
]);
|
|
80
|
+
const initGantt = useCallback(() => {
|
|
81
|
+
if (!containerRef.current) return;
|
|
82
|
+
ganttInstanceRef.current = new XGantt(containerRef.current, options);
|
|
83
|
+
registerEventListeners();
|
|
84
|
+
}, [options, registerEventListeners]);
|
|
85
|
+
const jumpTo = useCallback((date) => {
|
|
86
|
+
if (ganttInstanceRef.current) {
|
|
87
|
+
return ganttInstanceRef.current.jumpTo(date);
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}, []);
|
|
91
|
+
const destroyGantt = useCallback(() => {
|
|
92
|
+
if (ganttInstanceRef.current) {
|
|
93
|
+
ganttInstanceRef.current.destroy();
|
|
94
|
+
ganttInstanceRef.current = null;
|
|
95
|
+
}
|
|
96
|
+
}, []);
|
|
97
|
+
useImperativeHandle(ref, () => ({
|
|
98
|
+
getInstance: () => ganttInstanceRef.current,
|
|
99
|
+
jumpTo
|
|
100
|
+
}), [jumpTo]);
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
initGantt();
|
|
103
|
+
return () => {
|
|
104
|
+
destroyGantt();
|
|
105
|
+
};
|
|
106
|
+
}, []);
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (ganttInstanceRef.current) {
|
|
109
|
+
ganttInstanceRef.current.updateOptions(options);
|
|
110
|
+
}
|
|
111
|
+
}, [options]);
|
|
112
|
+
return /* @__PURE__ */ jsx(
|
|
113
|
+
"div",
|
|
114
|
+
{
|
|
115
|
+
ref: containerRef,
|
|
116
|
+
"data-testid": "x-gantt-container",
|
|
117
|
+
className: `x-gantt-container ${className || ""}`,
|
|
118
|
+
style: {
|
|
119
|
+
position: "relative",
|
|
120
|
+
width: "100%",
|
|
121
|
+
height: "100%",
|
|
122
|
+
...style
|
|
123
|
+
},
|
|
124
|
+
...restProps
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
XGanttReact.displayName = "XGanttReact";
|
|
130
|
+
function useXGantt() {
|
|
131
|
+
const ganttRef = useRef(null);
|
|
132
|
+
const getInstance = useCallback(() => {
|
|
133
|
+
var _a;
|
|
134
|
+
return ((_a = ganttRef.current) == null ? void 0 : _a.getInstance()) || null;
|
|
135
|
+
}, []);
|
|
136
|
+
const jumpTo = useCallback((date) => {
|
|
137
|
+
var _a;
|
|
138
|
+
return ((_a = ganttRef.current) == null ? void 0 : _a.jumpTo(date)) || false;
|
|
139
|
+
}, []);
|
|
140
|
+
return {
|
|
141
|
+
ganttRef,
|
|
142
|
+
getInstance,
|
|
143
|
+
jumpTo
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export {
|
|
147
|
+
XGanttReact,
|
|
148
|
+
colorjs,
|
|
149
|
+
dayjs,
|
|
150
|
+
XGanttReact as default,
|
|
151
|
+
generateId,
|
|
152
|
+
useXGantt
|
|
153
|
+
};
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.x-gantt{--x-gantt-border-color: #e5e5e5}.x-gantt-table-container{flex-shrink:0;box-sizing:border-box;height:100%;overflow:hidden;display:flex;flex-direction:column;width:100%}.x-gantt-table-header{flex-shrink:0;box-sizing:border-box;border-bottom:1px solid var(--x-gantt-border-color)!important;display:flex;flex-direction:row;overflow:hidden;position:relative;flex-wrap:nowrap}.x-gantt-table-header .x-gantt-table-header-cell{position:relative;box-sizing:border-box;overflow:hidden;font-weight:var(--x-gantt-header-font-weight);flex-shrink:0;padding:0 8px}.x-gantt-table-header .x-gantt-table-header-cell.border{border-right:1px solid var(--x-gantt-border-color)!important}.x-gantt-table-header .x-gantt-table-header-cell .x-gantt-column-resize-handle{transition:background-color .2s ease}.x-gantt-table-header .x-gantt-table-header-cell .x-gantt-column-resize-handle:hover{background-color:#0000001a!important}.x-gantt-table-header>div:last-child.x-gantt-table-header-group.border>.x-gantt-table-header-cell.border{border-right:none}.x-gantt-table-header>div:last-child .x-gantt-table-header-group.border>.x-gantt-table-header-cell.border{border-right:none}.x-gantt-table-header>div:last-child.x-gantt-table-header-cell.border{border-right:none}.x-gantt-table-header-group{display:flex;flex-direction:column;box-sizing:border-box}.x-gantt-table-header-group>.x-gantt-table-header-cell{border-bottom:1px solid var(--x-gantt-border-color)!important}.x-gantt-table-header-group>.x-gantt-table-header-cell>.x-gantt-table-header-title{text-align:center}.x-gantt-table-header-children{display:flex;flex-direction:row}.x-gantt-table-body{flex:1;overflow:hidden;box-sizing:border-box;position:relative;width:100%;height:100%}.x-gantt-table-row{box-sizing:border-box}.x-gantt-table-row.hover>.x-gantt-table-cell{background-color:var(--x-gantt-row-hover-color, rgba(0, 0, 0, .05))!important}.x-gantt-table-row.selected>.x-gantt-table-cell{background-color:var(--x-gantt-row-selected-color, rgba(0, 0, 0, .1))!important}.x-gantt-table-cell{box-sizing:border-box;display:inline-block;border-bottom:1px solid var(--x-gantt-border-color)!important;padding:var(--x-gantt-cell-padding, 4px 8px)}.x-gantt-table-cell .x-gantt-table-cell__content{box-sizing:border-box}.x-gantt-table-cell.border{border-right:1px solid var(--x-gantt-border-color)!important}.x-gantt-content-wrapper{width:100%;height:100%;scrollbar-width:none}.x-gantt-content-wrapper::-webkit-scrollbar{display:none}.gantt-scrollbar{position:absolute;z-index:10;opacity:0;transition:opacity .2s ease-in-out;pointer-events:none}.gantt-scrollbar.visible{opacity:1;pointer-events:auto}.gantt-scrollbar-thumb{position:absolute;cursor:pointer;transition:background-color .2s ease-in-out,height .1s ease-out,width .1s ease-out,transform .05s linear}.gantt-scrollbar-vertical{top:0;right:0;bottom:0}.gantt-scrollbar-vertical .gantt-scrollbar-thumb-vertical{top:0;left:0;right:0}.gantt-scrollbar-horizontal{left:0;bottom:0;right:0}.gantt-scrollbar-horizontal .gantt-scrollbar-thumb-horizontal{left:0;top:0;bottom:0}.x-gantt-checkbox{display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--x-gantt-border-color);border-radius:3px;cursor:pointer;transition:all .15s ease-in-out;box-sizing:border-box;-webkit-user-select:none;user-select:none;position:relative;overflow:hidden}.x-gantt-checkbox:focus{outline:none}.x-gantt-checkbox:focus-visible{outline:none}.x-gantt-checkbox__icon svg{transition:all .15s ease-in-out}.x-gantt-checkbox:hover{border-color:var(--x-gantt-primary-color)}.x-gantt{width:100%;height:100%;display:flex;box-sizing:border-box;flex-wrap:nowrap;padding:0;margin:0;overflow:hidden;position:relative}.x-gantt.border{border:1px solid var(--x-gantt-border-color)}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xpyjs/gantt-react",
|
|
3
|
+
"version": "0.0.1-alpha.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "React wrapper for x-gantt",
|
|
6
|
+
"author": "JeremyJone",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.cjs"
|
|
17
|
+
},
|
|
18
|
+
"./style.css": "./dist/style.css"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"LICENSE",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@xpyjs/gantt-core": "0.0.1-alpha.1"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=16.8.0",
|
|
30
|
+
"react-dom": ">=16.8.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
34
|
+
"@testing-library/react": "^16.0.0",
|
|
35
|
+
"@testing-library/user-event": "^14.6.1",
|
|
36
|
+
"@types/react": "^18.3.3",
|
|
37
|
+
"@types/react-dom": "^18.3.0",
|
|
38
|
+
"jsdom": "^26.1.0",
|
|
39
|
+
"react": "^18.3.1",
|
|
40
|
+
"react-dom": "^18.3.1",
|
|
41
|
+
"typescript": "^5.4.5",
|
|
42
|
+
"vite": "^5.2.11",
|
|
43
|
+
"vite-plugin-dts": "^3.9.1",
|
|
44
|
+
"vitest": "^3.2.1"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"gantt",
|
|
48
|
+
"react",
|
|
49
|
+
"react-component",
|
|
50
|
+
"typescript",
|
|
51
|
+
"project-management",
|
|
52
|
+
"schedule",
|
|
53
|
+
"timeline"
|
|
54
|
+
],
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "https://github.com/xpyjs/gantt.git",
|
|
58
|
+
"directory": "packages/react"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://github.com/xpyjs/gantt#readme",
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/xpyjs/gantt/issues"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"dev": "tsc && vite build --watch",
|
|
66
|
+
"build": "tsc && vite build",
|
|
67
|
+
"test": "vitest",
|
|
68
|
+
"test:ui": "vitest --ui",
|
|
69
|
+
"coverage": "vitest run --coverage",
|
|
70
|
+
"release": "pnpm publish --access public --no-git-checks"
|
|
71
|
+
}
|
|
72
|
+
}
|