@mogura/moguchart-core 0.11.0 → 0.12.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/README.en.md +348 -140
- package/README.md +147 -5
- package/dist/components/gantt-bar.d.ts +3 -0
- package/dist/components/gantt-chart.d.ts +10 -0
- package/dist/core/i18n.d.ts +2 -0
- package/dist/core/types.d.ts +65 -0
- package/dist/core/utils.d.ts +28 -1
- package/dist/index.d.ts +1 -0
- package/dist/moguchart-core.mjs +345 -47
- package/dist/moguchart-core.umd.js +177 -14
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -2,44 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
[日本語](./README.md) | [Demo](https://moguchart-core.vercel.app/)
|
|
4
4
|
|
|
5
|
-
A lightweight yet feature-rich Gantt chart Web Component built with Lit. Works with Vue, React, Angular, Svelte, and any other framework.
|
|
5
|
+
A lightweight yet feature-rich Gantt chart Web Component built with Lit. Works seamlessly with Vue, React, Angular, Svelte, and any other modern web framework.
|
|
6
6
|
|
|
7
|
-
- **Demo**: [https://moguchart-core.vercel.app/](https://moguchart-core.vercel.app/)
|
|
7
|
+
- **Online Demo**: [https://moguchart-core.vercel.app/](https://moguchart-core.vercel.app/)
|
|
8
|
+
- **npm Package**: [@mogura/moguchart-core](https://www.npmjs.com/package/@mogura/moguchart-core)
|
|
8
9
|
|
|
9
10
|
## Features
|
|
10
11
|
|
|
11
|
-
- 🚀 **Framework-agnostic**: Built as Web Components (Custom Elements),
|
|
12
|
-
- ⚡ **Virtual Scrolling**: Smooth
|
|
13
|
-
- 🖱️ **Interactive**:
|
|
14
|
-
- Drag & drop task movement (
|
|
15
|
-
- Handle-based duration resizing
|
|
12
|
+
- 🚀 **Framework-agnostic**: Built as standard Web Components (Custom Elements), easily integrated into any frontend framework.
|
|
13
|
+
- ⚡ **Virtual Scrolling**: Smooth 60fps rendering even with extensive tasks and rows.
|
|
14
|
+
- 🖱️ **Rich Interactive Controls**:
|
|
15
|
+
- Drag & drop task movement (with optional cross-row vertical movement)
|
|
16
|
+
- Handle-based task duration resizing
|
|
16
17
|
- Drag & drop row reordering
|
|
17
18
|
- Column header width resizing
|
|
18
|
-
-
|
|
19
|
+
- Marquee selection (rubberband drag selection) for batch task selection (with Shift / Ctrl / Cmd additive selection support)
|
|
20
|
+
- Multi-task selection and synchronized batch dragging (Ctrl / Cmd + click, marquee selection)
|
|
21
|
+
- Safe drag cancellation and snapback when cursor exits chart boundaries
|
|
19
22
|
- Double-click and right-click event handling
|
|
20
23
|
- 🎨 **Highly Customizable**:
|
|
21
|
-
- Custom rendering for task bars, row headers, tooltips, and drag info
|
|
22
|
-
- Light/Dark/System theme switching + custom color
|
|
23
|
-
-
|
|
24
|
-
- CSS styling
|
|
25
|
-
- 🔗 **Dependency Visualization**:
|
|
26
|
-
-
|
|
24
|
+
- Custom rendering for task bars, row headers, row header tooltips, tooltips, and drag info overlays
|
|
25
|
+
- Light / Dark / System theme switching + custom color palettes
|
|
26
|
+
- 13 built-in task bar fill patterns (stripes, dots, checkerboard, grid, etc.)
|
|
27
|
+
- Native CSS variable-driven styling
|
|
28
|
+
- 🔗 **Dependency Visualization**:
|
|
29
|
+
- Smooth curved lines with directional arrows showing task dependencies
|
|
30
|
+
- Automatic S-curve calculation for reverse-direction dependencies
|
|
31
|
+
- Proximity connector toggle (`showConnectors`)
|
|
32
|
+
- Automatic critical path detection and highlighted visualization (`showCriticalPath`)
|
|
33
|
+
- 📅 **Flexible Calendar & Timeline**:
|
|
27
34
|
- Day / Week / Month view switching
|
|
28
|
-
-
|
|
29
|
-
- Current time line with badge (auto-refresh support)
|
|
35
|
+
- Dynamic zoom levels (`pxPerDay` or `pxPerMonth`) with smooth mouse-wheel zoom support
|
|
36
|
+
- Current time indicator line with date badge (auto-refresh support)
|
|
30
37
|
- Custom holiday detection logic
|
|
31
38
|
- Configurable week start day
|
|
32
|
-
-
|
|
33
|
-
- 🏁 **Milestones**: Display milestones
|
|
34
|
-
- 📍 **Markers**:
|
|
35
|
-
- 🗺️ **Overview Minimap**:
|
|
39
|
+
- Built-in internationalization (Japanese, English, and custom locale extensibility)
|
|
40
|
+
- 🏁 **Milestones**: Display key milestones with vertical markers and customizable badges.
|
|
41
|
+
- 📍 **Markers**: Place labeled triangle marker indicators on individual row timelines.
|
|
42
|
+
- 🗺️ **Overview Minimap**: Floating bird's-eye canvas preview of the entire chart, interactive pan & scroll synchronization, click-to-jump, drag-to-move, edge drag-resizing, opacity slider, and collapsible window state.
|
|
43
|
+
- 📊 **Task Progress Management**:
|
|
44
|
+
- Task bar progress overlay (full, bottom, or top indicator styles)
|
|
45
|
+
- Interactive drag-adjust handle for quick progress modification (with snap increments)
|
|
46
|
+
- Configurable progress labels (custom positioning & formatters)
|
|
47
|
+
- `task-progress-change` custom event
|
|
48
|
+
- Progress calculation utility functions (simple & duration-weighted row/project averages)
|
|
49
|
+
- Automatic progress visualization on the overview minimap
|
|
50
|
+
- 📷 **High-Fidelity Export**: Export the full Gantt chart to PNG image or multi-page PDF documents (with scroll position preservation and auto-download support).
|
|
36
51
|
- ✨ **Advanced Integration**:
|
|
37
52
|
- External drag & drop for task creation
|
|
38
|
-
- Task move/copy
|
|
39
|
-
- Snap feature (
|
|
40
|
-
- `hitTest` method for
|
|
53
|
+
- Task move / copy modes
|
|
54
|
+
- Snap feature (time unit grid snapping, automatic monthly boundary snap in month view)
|
|
55
|
+
- `hitTest` method for calculating row ID and datetime from screen coordinates
|
|
41
56
|
- Programmatic task selection + auto-scroll (`selectTask`)
|
|
42
|
-
-
|
|
57
|
+
- Row layout coordinates inspection (`getRowPositions`)
|
|
58
|
+
- ⌨️ **Keyboard Navigation**: Arrow key navigation & selection, Shift + Arrow task movement, Delete / Backspace deletion.
|
|
43
59
|
|
|
44
60
|
## Installation
|
|
45
61
|
|
|
@@ -47,22 +63,28 @@ A lightweight yet feature-rich Gantt chart Web Component built with Lit. Works w
|
|
|
47
63
|
pnpm add @mogura/moguchart-core
|
|
48
64
|
# or
|
|
49
65
|
npm install @mogura/moguchart-core
|
|
66
|
+
# or
|
|
67
|
+
yarn add @mogura/moguchart-core
|
|
50
68
|
```
|
|
51
69
|
|
|
52
70
|
## API Reference
|
|
53
71
|
|
|
54
|
-
|
|
72
|
+
For exhaustive configuration properties, methods, and event signatures, refer to the [API Reference (API.en.md)](./doc/API.en.md) or the [Japanese API Reference (API.md)](./doc/API.md).
|
|
55
73
|
|
|
56
74
|
## Usage with Vue.js
|
|
57
75
|
|
|
58
|
-
Example using Vue
|
|
59
|
-
When using Web Components
|
|
76
|
+
Example using Vue 3 (Composition API / `<script setup>`).
|
|
77
|
+
When using Web Components in Vue, configure `compilerOptions.isCustomElement` in `vite.config.ts` to recognize `gantt-chart`.
|
|
60
78
|
|
|
61
79
|
```html
|
|
62
80
|
<script setup lang="ts">
|
|
63
81
|
import { ref } from 'vue'
|
|
64
82
|
import '@mogura/moguchart-core'
|
|
65
|
-
import type {
|
|
83
|
+
import type {
|
|
84
|
+
GanttRow,
|
|
85
|
+
GanttChartOption,
|
|
86
|
+
TaskUpdateEventDetail,
|
|
87
|
+
} from '@mogura/moguchart-core'
|
|
66
88
|
|
|
67
89
|
const rows = ref<GanttRow[]>([
|
|
68
90
|
{
|
|
@@ -72,8 +94,9 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
72
94
|
{
|
|
73
95
|
id: 't-1',
|
|
74
96
|
name: 'Task 1',
|
|
75
|
-
start: new Date('
|
|
76
|
-
end: new Date('
|
|
97
|
+
start: new Date('2025-01-01'),
|
|
98
|
+
end: new Date('2025-01-05'),
|
|
99
|
+
progress: 60,
|
|
77
100
|
style: 'background-color: #60a5fa',
|
|
78
101
|
},
|
|
79
102
|
],
|
|
@@ -81,7 +104,7 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
81
104
|
{
|
|
82
105
|
id: 'marker-1',
|
|
83
106
|
name: 'Review Deadline',
|
|
84
|
-
date: new Date('
|
|
107
|
+
date: new Date('2025-01-03'),
|
|
85
108
|
type: 'triangle-down',
|
|
86
109
|
color: '#ef4444',
|
|
87
110
|
},
|
|
@@ -91,15 +114,15 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
91
114
|
|
|
92
115
|
const option = ref<GanttChartOption>({
|
|
93
116
|
calendar: {
|
|
94
|
-
start: new Date('
|
|
95
|
-
end: new Date('
|
|
117
|
+
start: new Date('2025-01-01'),
|
|
118
|
+
end: new Date('2025-03-31'),
|
|
96
119
|
pxPerDay: 30,
|
|
97
120
|
showCurrentTime: true,
|
|
98
121
|
milestones: [
|
|
99
122
|
{
|
|
100
123
|
id: 'ms-1',
|
|
101
124
|
name: 'Release',
|
|
102
|
-
start: new Date('
|
|
125
|
+
start: new Date('2025-02-01'),
|
|
103
126
|
color: '#8b5cf6',
|
|
104
127
|
},
|
|
105
128
|
],
|
|
@@ -107,6 +130,18 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
107
130
|
bar: { height: 28 },
|
|
108
131
|
rowHeader: { width: 200 },
|
|
109
132
|
theme: 'system',
|
|
133
|
+
enableCrossRowMove: true,
|
|
134
|
+
progress: {
|
|
135
|
+
enabled: true,
|
|
136
|
+
editable: true,
|
|
137
|
+
showLabel: true,
|
|
138
|
+
},
|
|
139
|
+
selection: {
|
|
140
|
+
marquee: true,
|
|
141
|
+
},
|
|
142
|
+
minimap: {
|
|
143
|
+
enabled: true,
|
|
144
|
+
},
|
|
110
145
|
})
|
|
111
146
|
|
|
112
147
|
const handleTaskUpdate = (e: Event) => {
|
|
@@ -116,23 +151,31 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
116
151
|
</script>
|
|
117
152
|
|
|
118
153
|
<template>
|
|
119
|
-
<div style="height:
|
|
120
|
-
<gantt-chart
|
|
154
|
+
<div style="height: 600px;">
|
|
155
|
+
<gantt-chart
|
|
156
|
+
:rows="rows"
|
|
157
|
+
:option="option"
|
|
158
|
+
@task-update="handleTaskUpdate"
|
|
159
|
+
></gantt-chart>
|
|
121
160
|
</div>
|
|
122
161
|
</template>
|
|
123
162
|
```
|
|
124
163
|
|
|
125
164
|
## Usage with React
|
|
126
165
|
|
|
127
|
-
Example using React.
|
|
128
|
-
Since Web Components
|
|
166
|
+
Example using React (TypeScript).
|
|
167
|
+
Since Web Components interact via DOM properties and native event listeners, use a `ref` to bind complex objects and events.
|
|
129
168
|
|
|
130
169
|
```tsx
|
|
131
170
|
import { useEffect, useRef, useState } from 'react'
|
|
132
171
|
import '@mogura/moguchart-core'
|
|
133
|
-
import type {
|
|
172
|
+
import type {
|
|
173
|
+
GanttRow,
|
|
174
|
+
GanttChartOption,
|
|
175
|
+
TaskUpdateEventDetail,
|
|
176
|
+
} from '@mogura/moguchart-core'
|
|
134
177
|
|
|
135
|
-
// Type definition for
|
|
178
|
+
// Type definition for JSX Custom Element
|
|
136
179
|
declare global {
|
|
137
180
|
namespace JSX {
|
|
138
181
|
interface IntrinsicElements {
|
|
@@ -152,8 +195,9 @@ export default function App() {
|
|
|
152
195
|
{
|
|
153
196
|
id: 't-1',
|
|
154
197
|
name: 'Task 1',
|
|
155
|
-
start: new Date('
|
|
156
|
-
end: new Date('
|
|
198
|
+
start: new Date('2025-01-01'),
|
|
199
|
+
end: new Date('2025-01-05'),
|
|
200
|
+
progress: 50,
|
|
157
201
|
style: 'background-color: #60a5fa',
|
|
158
202
|
},
|
|
159
203
|
],
|
|
@@ -161,7 +205,7 @@ export default function App() {
|
|
|
161
205
|
{
|
|
162
206
|
id: 'marker-1',
|
|
163
207
|
name: 'Review Deadline',
|
|
164
|
-
date: new Date('
|
|
208
|
+
date: new Date('2025-01-03'),
|
|
165
209
|
type: 'triangle-down',
|
|
166
210
|
color: '#ef4444',
|
|
167
211
|
},
|
|
@@ -171,15 +215,15 @@ export default function App() {
|
|
|
171
215
|
|
|
172
216
|
const [option] = useState<GanttChartOption>({
|
|
173
217
|
calendar: {
|
|
174
|
-
start: new Date('
|
|
175
|
-
end: new Date('
|
|
218
|
+
start: new Date('2025-01-01'),
|
|
219
|
+
end: new Date('2025-03-31'),
|
|
176
220
|
pxPerDay: 30,
|
|
177
221
|
showCurrentTime: true,
|
|
178
222
|
milestones: [
|
|
179
223
|
{
|
|
180
224
|
id: 'ms-1',
|
|
181
225
|
name: 'Release',
|
|
182
|
-
start: new Date('
|
|
226
|
+
start: new Date('2025-02-01'),
|
|
183
227
|
color: '#8b5cf6',
|
|
184
228
|
},
|
|
185
229
|
],
|
|
@@ -187,17 +231,28 @@ export default function App() {
|
|
|
187
231
|
bar: { height: 28 },
|
|
188
232
|
rowHeader: { width: 200 },
|
|
189
233
|
theme: 'system',
|
|
234
|
+
enableCrossRowMove: true,
|
|
235
|
+
progress: {
|
|
236
|
+
enabled: true,
|
|
237
|
+
editable: true,
|
|
238
|
+
},
|
|
239
|
+
selection: {
|
|
240
|
+
marquee: true,
|
|
241
|
+
},
|
|
242
|
+
minimap: {
|
|
243
|
+
enabled: true,
|
|
244
|
+
},
|
|
190
245
|
})
|
|
191
246
|
|
|
192
247
|
useEffect(() => {
|
|
193
248
|
const chart = chartRef.current
|
|
194
249
|
if (!chart) return
|
|
195
250
|
|
|
196
|
-
//
|
|
251
|
+
// Bind properties
|
|
197
252
|
chart.rows = rows
|
|
198
253
|
chart.option = option
|
|
199
254
|
|
|
200
|
-
//
|
|
255
|
+
// Bind event listeners
|
|
201
256
|
const handleTaskUpdate = (e: Event) => {
|
|
202
257
|
const detail = (e as CustomEvent<TaskUpdateEventDetail>).detail
|
|
203
258
|
console.log('Task updated:', detail)
|
|
@@ -211,7 +266,7 @@ export default function App() {
|
|
|
211
266
|
}, [rows, option])
|
|
212
267
|
|
|
213
268
|
return (
|
|
214
|
-
<div style={{ height: '
|
|
269
|
+
<div style={{ height: '600px' }}>
|
|
215
270
|
<gantt-chart ref={chartRef}></gantt-chart>
|
|
216
271
|
</div>
|
|
217
272
|
)
|
|
@@ -222,7 +277,7 @@ export default function App() {
|
|
|
222
277
|
|
|
223
278
|
### Themes
|
|
224
279
|
|
|
225
|
-
Three theme modes are supported: light
|
|
280
|
+
Three theme modes are supported: `light`, `dark`, and `system` (automatic OS preference). Individual color tokens can be overridden using `customTheme`.
|
|
226
281
|
|
|
227
282
|
```javascript
|
|
228
283
|
const option = {
|
|
@@ -231,75 +286,15 @@ const option = {
|
|
|
231
286
|
bg: '#1a1a2e',
|
|
232
287
|
text: '#e0e0e0',
|
|
233
288
|
currentTimeLine: '#ff6b6b',
|
|
289
|
+
criticalPath: '#ef4444',
|
|
234
290
|
},
|
|
235
291
|
// ...
|
|
236
292
|
}
|
|
237
293
|
```
|
|
238
294
|
|
|
239
|
-
### Dependency Line Settings
|
|
240
|
-
|
|
241
|
-
Customize the dependency line display with the `dependency` option. Control arrow visibility and size.
|
|
242
|
-
Reverse-direction (right-to-left) dependencies are automatically rendered with S-curves, with horizontal connections at contact points.
|
|
243
|
-
|
|
244
|
-
```javascript
|
|
245
|
-
const option = {
|
|
246
|
-
dependency: {
|
|
247
|
-
showArrows: true, // Show arrows (default: true)
|
|
248
|
-
arrowSize: 12, // Arrow size in px (default: 8)
|
|
249
|
-
},
|
|
250
|
-
// ...
|
|
251
|
-
}
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
### Internationalization (i18n)
|
|
255
|
-
|
|
256
|
-
moguchart-core provides built-in locale support. Japanese is the default locale for backward compatibility. Switch to English or create custom locales.
|
|
257
|
-
|
|
258
|
-
```javascript
|
|
259
|
-
import { enLocale } from '@mogura/moguchart-core'
|
|
260
|
-
|
|
261
|
-
const option = {
|
|
262
|
-
locale: enLocale,
|
|
263
|
-
// ...
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
To create a custom locale, implement the `MoguchartLocale` interface:
|
|
268
|
-
|
|
269
|
-
```typescript
|
|
270
|
-
import type { MoguchartLocale } from '@mogura/moguchart-core'
|
|
271
|
-
|
|
272
|
-
const frLocale: MoguchartLocale = {
|
|
273
|
-
monthFormat: 'MMM YYYY',
|
|
274
|
-
monthRowFormat: 'MMM',
|
|
275
|
-
dateFormat: (d) => `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`,
|
|
276
|
-
timeUnitDateFormat: (d) => `${d.getDate()} ${['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'][d.getMonth()]} ${d.getFullYear()}`,
|
|
277
|
-
dateTimeFormat: (d) => {
|
|
278
|
-
const date = `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`
|
|
279
|
-
const h = d.getHours()
|
|
280
|
-
const m = d.getMinutes()
|
|
281
|
-
if (h === 0 && m === 0) return date
|
|
282
|
-
return `${date} ${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`
|
|
283
|
-
},
|
|
284
|
-
yearMonthFormat: (d) => `${d.getFullYear()}/${d.getMonth() + 1}`,
|
|
285
|
-
duration: {
|
|
286
|
-
days: (n) => `${n} jour${n > 1 ? 's' : ''}`,
|
|
287
|
-
hours: (n) => `${n} heure${n > 1 ? 's' : ''}`,
|
|
288
|
-
minutes: (n) => `${n} minute${n > 1 ? 's' : ''}`,
|
|
289
|
-
zero: '0 minute',
|
|
290
|
-
},
|
|
291
|
-
tooltip: { duration: (d) => `Durée: ${d} jour${d > 1 ? 's' : ''}` },
|
|
292
|
-
dragOverlay: {
|
|
293
|
-
noTitle: 'Sans titre',
|
|
294
|
-
moveTo: (name) => `Déplacer vers: ${name}`,
|
|
295
|
-
movingTasks: (c) => `Déplacement de ${c} tâche${c > 1 ? 's' : ''}`,
|
|
296
|
-
},
|
|
297
|
-
}
|
|
298
|
-
```
|
|
299
|
-
|
|
300
295
|
### Milestones
|
|
301
296
|
|
|
302
|
-
Pass an array of
|
|
297
|
+
Pass an array of milestone definitions to `calendar.milestones` to render vertical milestone lines with name badges across the chart. Hover effects provide smooth visual feedback.
|
|
303
298
|
|
|
304
299
|
```javascript
|
|
305
300
|
option.calendar.milestones = [
|
|
@@ -321,16 +316,14 @@ option.calendar.milestones = [
|
|
|
321
316
|
|
|
322
317
|
### Markers
|
|
323
318
|
|
|
324
|
-
|
|
319
|
+
Add markers to any row's `markers` property to display triangle icons with text labels along the timeline.
|
|
325
320
|
|
|
326
321
|
```javascript
|
|
327
322
|
const rows = [
|
|
328
323
|
{
|
|
329
324
|
id: 'row-1',
|
|
330
325
|
name: 'Task A',
|
|
331
|
-
tasks: [
|
|
332
|
-
/* ... */
|
|
333
|
-
],
|
|
326
|
+
tasks: [/* ... */],
|
|
334
327
|
markers: [
|
|
335
328
|
{
|
|
336
329
|
id: 'marker-1',
|
|
@@ -338,6 +331,7 @@ const rows = [
|
|
|
338
331
|
date: new Date('2025-04-10'),
|
|
339
332
|
anchor: 'end',
|
|
340
333
|
type: 'triangle-right',
|
|
334
|
+
fontSize: 'sm', // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
341
335
|
color: '#ef4444',
|
|
342
336
|
},
|
|
343
337
|
],
|
|
@@ -347,7 +341,7 @@ const rows = [
|
|
|
347
341
|
|
|
348
342
|
### Task Bar Patterns
|
|
349
343
|
|
|
350
|
-
Apply 13
|
|
344
|
+
Apply any of the 13 built-in SVG patterns to task bars. Preset constants are exported for type safety.
|
|
351
345
|
|
|
352
346
|
```javascript
|
|
353
347
|
import { PATTERN_DIAGONAL_STRIPE } from '@mogura/moguchart-core'
|
|
@@ -355,20 +349,21 @@ import { PATTERN_DIAGONAL_STRIPE } from '@mogura/moguchart-core'
|
|
|
355
349
|
const task = {
|
|
356
350
|
id: 't-1',
|
|
357
351
|
name: 'WIP',
|
|
358
|
-
start: new Date('
|
|
359
|
-
end: new Date('
|
|
352
|
+
start: new Date('2025-01-01'),
|
|
353
|
+
end: new Date('2025-01-05'),
|
|
360
354
|
style: 'background-color: #60a5fa',
|
|
361
|
-
pattern: PATTERN_DIAGONAL_STRIPE, //
|
|
362
|
-
// or specify
|
|
355
|
+
pattern: PATTERN_DIAGONAL_STRIPE, // Using preset
|
|
356
|
+
// or specify custom pattern:
|
|
363
357
|
// pattern: { type: 'checkerboard', color: '#ffffff80' }
|
|
364
358
|
}
|
|
365
359
|
```
|
|
366
360
|
|
|
367
|
-
Available
|
|
361
|
+
Available pattern types:
|
|
362
|
+
`diagonal-stripe`, `diagonal-stripe-thin`, `diagonal-stripe-thick`, `diagonal-stripe-reverse`, `vertical-stripe`, `horizontal-stripe`, `checkerboard`, `dots`, `dots-dense`, `triangle`, `circle`, `grid`, `diagonal-grid`.
|
|
368
363
|
|
|
369
364
|
### Row Reordering
|
|
370
365
|
|
|
371
|
-
Set `enableRowReordering: true` to
|
|
366
|
+
Set `enableRowReordering: true` to allow users to reorder rows via drag & drop.
|
|
372
367
|
|
|
373
368
|
```javascript
|
|
374
369
|
const option = {
|
|
@@ -381,15 +376,26 @@ chart.addEventListener('row-reordered', (e) => {
|
|
|
381
376
|
})
|
|
382
377
|
```
|
|
383
378
|
|
|
379
|
+
### Cross-Row Task Movement (`enableCrossRowMove`)
|
|
380
|
+
|
|
381
|
+
By default, dragging a task bar permits moving it vertically across different rows (`enableCrossRowMove: true`). Set this option to `false` to restrict movement strictly to the horizontal timeline of its original row.
|
|
382
|
+
|
|
383
|
+
```javascript
|
|
384
|
+
const option = {
|
|
385
|
+
enableCrossRowMove: false, // Restrict task drag movement to the same row
|
|
386
|
+
// ...
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
384
390
|
### Multi-Task Selection & Batch Operations
|
|
385
391
|
|
|
386
|
-
Hold `Ctrl` (
|
|
392
|
+
Hold `Ctrl` (macOS: `Cmd`) and click task bars, or use **Marquee Selection** to select multiple tasks. Once selected, dragging any selected task moves all of them collectively while preserving their relative dates.
|
|
387
393
|
|
|
388
394
|
```javascript
|
|
389
395
|
chart.addEventListener('task-update', (e) => {
|
|
390
396
|
const detail = e.detail
|
|
391
397
|
if (!detail.isDragging && detail.selectedTaskIds?.length > 1) {
|
|
392
|
-
//
|
|
398
|
+
// Drop event for multi-task selection
|
|
393
399
|
for (const taskId of detail.selectedTaskIds) {
|
|
394
400
|
applyDxToTask(taskId, detail.dx)
|
|
395
401
|
}
|
|
@@ -399,11 +405,11 @@ chart.addEventListener('task-update', (e) => {
|
|
|
399
405
|
|
|
400
406
|
### Snap Feature
|
|
401
407
|
|
|
402
|
-
Control the
|
|
408
|
+
Control the time-snapping interval during drag movement and resizing via `snapDuration` (in minutes). When using monthly view mode (`pxPerMonth`), snapping automatically aligns to month boundaries.
|
|
403
409
|
|
|
404
410
|
```javascript
|
|
405
411
|
const option = {
|
|
406
|
-
snapDuration: 60, // Snap
|
|
412
|
+
snapDuration: 60, // Snap to 1-hour increments (default: 1440 = 1 day)
|
|
407
413
|
// ...
|
|
408
414
|
}
|
|
409
415
|
```
|
|
@@ -412,7 +418,7 @@ const option = {
|
|
|
412
418
|
|
|
413
419
|
#### Week View Mode
|
|
414
420
|
|
|
415
|
-
Set `calendar.showWeeks: true`
|
|
421
|
+
Set `calendar.showWeeks: true` to display a two-tiered calendar header with week numbers. Automatically activates when `pxPerDay` is under 20.
|
|
416
422
|
|
|
417
423
|
```javascript
|
|
418
424
|
const option = {
|
|
@@ -429,7 +435,7 @@ const option = {
|
|
|
429
435
|
|
|
430
436
|
#### Monthly View Mode
|
|
431
437
|
|
|
432
|
-
Set `calendar.pxPerMonth` to render
|
|
438
|
+
Set `calendar.pxPerMonth` to render months with equal pixel widths, suitable for long-term project planning.
|
|
433
439
|
|
|
434
440
|
```javascript
|
|
435
441
|
const option = {
|
|
@@ -438,7 +444,160 @@ const option = {
|
|
|
438
444
|
end: new Date('2027-12-31'),
|
|
439
445
|
pxPerDay: 1,
|
|
440
446
|
pxPerMonth: 120, // 120px per month
|
|
441
|
-
showMonthsRow: true, // Two-row header: top
|
|
447
|
+
showMonthsRow: true, // Two-row header: year on top, month below
|
|
448
|
+
},
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Dependency Line Settings
|
|
453
|
+
|
|
454
|
+
Configure task dependency curves with the `dependency` option:
|
|
455
|
+
|
|
456
|
+
- `showArrows`: Toggle directional arrow heads (default: `true`).
|
|
457
|
+
- `arrowSize`: Arrow dimensions in pixels (default: `8`).
|
|
458
|
+
- `showConnectors`: Control whether circular connection handles appear on hover (default: `true`). Set to `false` to prevent creating new dependencies.
|
|
459
|
+
- `showCriticalPath`: Automatically detect the longest chain (critical path) and highlight connected tasks and lines in a distinct color (configurable via `theme.criticalPath`).
|
|
460
|
+
|
|
461
|
+
Reverse dependencies (right-to-left) automatically render smooth S-curves with perpendicular contact alignment.
|
|
462
|
+
|
|
463
|
+
```javascript
|
|
464
|
+
const option = {
|
|
465
|
+
dependency: {
|
|
466
|
+
showArrows: true,
|
|
467
|
+
arrowSize: 10,
|
|
468
|
+
showConnectors: true,
|
|
469
|
+
showCriticalPath: true, // Highlight critical path tasks and links
|
|
470
|
+
},
|
|
471
|
+
// ...
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Task Progress Management
|
|
476
|
+
|
|
477
|
+
Visualize and interactively edit progress on task bars by specifying `progress` (`0` to `100`). Set `editable: true` to enable dragging the progress adjustment handle on the task bar.
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
import {
|
|
481
|
+
clampProgress,
|
|
482
|
+
calculateRowProgress,
|
|
483
|
+
calculateWeightedRowProgress,
|
|
484
|
+
calculateProjectProgress,
|
|
485
|
+
} from '@mogura/moguchart-core'
|
|
486
|
+
|
|
487
|
+
const option = {
|
|
488
|
+
progress: {
|
|
489
|
+
enabled: true,
|
|
490
|
+
editable: true, // Allow interactive handle dragging
|
|
491
|
+
showLabel: true, // Display progress text (e.g. "50%")
|
|
492
|
+
labelPosition: 'inside', // 'inside' | 'right' | 'left' | 'center'
|
|
493
|
+
snapStep: 5, // Snap in 5% increments
|
|
494
|
+
indicatorPosition: 'full', // 'full' | 'bottom' | 'top'
|
|
495
|
+
},
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Progress change event listener
|
|
499
|
+
chart.addEventListener('task-progress-change', (e) => {
|
|
500
|
+
const { task, progress, originalProgress, cancelled } = e.detail
|
|
501
|
+
console.log(`Task ${task.id}: ${originalProgress}% -> ${progress}%`)
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
// Progress calculation helper functions
|
|
505
|
+
const rowSimpleAvg = calculateRowProgress(row)
|
|
506
|
+
const rowWeightedAvg = calculateWeightedRowProgress(row)
|
|
507
|
+
const projectWeightedAvg = calculateProjectProgress(rows)
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Marquee Range Selection (Rubberband Selection)
|
|
511
|
+
|
|
512
|
+
Click and drag on empty calendar background space to select multiple task bars enclosed or intersected by the selection rectangle.
|
|
513
|
+
Hold `Shift`, `Ctrl`, or `Cmd` while dragging to accumulate selections additively.
|
|
514
|
+
|
|
515
|
+
```javascript
|
|
516
|
+
const option = {
|
|
517
|
+
selection: {
|
|
518
|
+
marquee: true, // Enable marquee selection (default: true)
|
|
519
|
+
borderColor: '#3b82f6', // Selection border color
|
|
520
|
+
backgroundColor: 'rgba(59, 130, 246, 0.15)', // Box fill color
|
|
521
|
+
},
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Selection change event listener
|
|
525
|
+
chart.addEventListener('bar-selection-change', (e) => {
|
|
526
|
+
console.log('Selected task IDs:', e.detail.selectedIds)
|
|
527
|
+
})
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Overview Minimap
|
|
531
|
+
|
|
532
|
+
Display a floating bird's-eye preview window that renders the entire project's tasks, milestones, and current viewport finder.
|
|
533
|
+
The minimap supports drag-panning, edge-resizing, opacity adjustment, and collapsing.
|
|
534
|
+
|
|
535
|
+
```javascript
|
|
536
|
+
const option = {
|
|
537
|
+
minimap: {
|
|
538
|
+
enabled: true,
|
|
539
|
+
width: 240,
|
|
540
|
+
preserveAspectRatio: true,
|
|
541
|
+
resizable: true,
|
|
542
|
+
collapsible: true,
|
|
543
|
+
collapsed: false,
|
|
544
|
+
opacity: 0.85,
|
|
545
|
+
position: { right: 16, bottom: 16 }, // Anchor offset from bottom-right (px)
|
|
546
|
+
},
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Minimap interaction events
|
|
550
|
+
chart.addEventListener('minimap-move', (e) => console.log('Position:', e.detail.position))
|
|
551
|
+
chart.addEventListener('minimap-resize', (e) => console.log('Size:', e.detail.width, e.detail.height))
|
|
552
|
+
chart.addEventListener('minimap-collapse', (e) => console.log('Collapsed:', e.detail.collapsed))
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Internationalization (i18n) & Locales
|
|
556
|
+
|
|
557
|
+
moguchart-core comes with built-in Japanese (`jaLocale`, default) and English (`enLocale`) support. You can also define custom locales implementing the `MoguchartLocale` interface.
|
|
558
|
+
|
|
559
|
+
```javascript
|
|
560
|
+
import { enLocale } from '@mogura/moguchart-core'
|
|
561
|
+
|
|
562
|
+
const option = {
|
|
563
|
+
locale: enLocale,
|
|
564
|
+
// ...
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Custom locale implementation example:
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
import type { MoguchartLocale } from '@mogura/moguchart-core'
|
|
572
|
+
|
|
573
|
+
const frLocale: MoguchartLocale = {
|
|
574
|
+
monthFormat: 'MMM YYYY',
|
|
575
|
+
monthRowFormat: 'MMM',
|
|
576
|
+
dateFormat: (d) => `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`,
|
|
577
|
+
timeUnitDateFormat: (d) =>
|
|
578
|
+
`${d.getDate()} ${['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'][d.getMonth()]} ${d.getFullYear()}`,
|
|
579
|
+
dateTimeFormat: (d) => {
|
|
580
|
+
const date = `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`
|
|
581
|
+
const h = d.getHours()
|
|
582
|
+
const m = d.getMinutes()
|
|
583
|
+
if (h === 0 && m === 0) return date
|
|
584
|
+
return `${date} ${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`
|
|
585
|
+
},
|
|
586
|
+
yearMonthFormat: (d) => `${d.getFullYear()}/${d.getMonth() + 1}`,
|
|
587
|
+
duration: {
|
|
588
|
+
days: (n) => `${n} jour${n > 1 ? 's' : ''}`,
|
|
589
|
+
hours: (n) => `${n} heure${n > 1 ? 's' : ''}`,
|
|
590
|
+
minutes: (n) => `${n} minute${n > 1 ? 's' : ''}`,
|
|
591
|
+
zero: '0 minute',
|
|
592
|
+
},
|
|
593
|
+
tooltip: {
|
|
594
|
+
duration: (d) => `Durée: ${d} jour${d > 1 ? 's' : ''}`,
|
|
595
|
+
progress: (p) => `Progression: ${p}%`,
|
|
596
|
+
},
|
|
597
|
+
dragOverlay: {
|
|
598
|
+
noTitle: 'Sans titre',
|
|
599
|
+
moveTo: (name) => `Déplacer vers: ${name}`,
|
|
600
|
+
movingTasks: (c) => `Déplacement de ${c} tâche${c > 1 ? 's' : ''}`,
|
|
442
601
|
},
|
|
443
602
|
}
|
|
444
603
|
```
|
|
@@ -447,7 +606,7 @@ const option = {
|
|
|
447
606
|
|
|
448
607
|
#### selectTask
|
|
449
608
|
|
|
450
|
-
Selects
|
|
609
|
+
Selects a task by ID and automatically scrolls the chart to bring it into view.
|
|
451
610
|
|
|
452
611
|
```javascript
|
|
453
612
|
const chart = document.querySelector('gantt-chart')
|
|
@@ -456,7 +615,7 @@ const found = chart.selectTask('task-1')
|
|
|
456
615
|
|
|
457
616
|
#### hitTest
|
|
458
617
|
|
|
459
|
-
|
|
618
|
+
Determines the row ID and calendar date corresponding to a given screen coordinate (e.g. from mouse events).
|
|
460
619
|
|
|
461
620
|
```javascript
|
|
462
621
|
document.addEventListener('mousemove', (e) => {
|
|
@@ -467,25 +626,74 @@ document.addEventListener('mousemove', (e) => {
|
|
|
467
626
|
})
|
|
468
627
|
```
|
|
469
628
|
|
|
629
|
+
#### exportImage
|
|
630
|
+
|
|
631
|
+
Exports the entire Gantt chart to a PNG image or PDF document. Preserves the user's scroll offset during export.
|
|
632
|
+
|
|
633
|
+
```javascript
|
|
634
|
+
// Automatically download as PNG image
|
|
635
|
+
await chart.exportImage('png', {
|
|
636
|
+
fileName: 'gantt-chart.png',
|
|
637
|
+
download: true,
|
|
638
|
+
})
|
|
639
|
+
|
|
640
|
+
// Retrieve as PDF Blob
|
|
641
|
+
const pdfBlob = await chart.exportImage('pdf')
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
#### Zoom Operations (`zoomTo`, `zoomToFit`, `resetZoom`)
|
|
645
|
+
|
|
646
|
+
Enable zoom via `option.zoom` (wheel zoom with Ctrl / Cmd key) and control zoom level programmatically:
|
|
647
|
+
|
|
648
|
+
```javascript
|
|
649
|
+
const option = {
|
|
650
|
+
zoom: {
|
|
651
|
+
enabled: true,
|
|
652
|
+
min: 5,
|
|
653
|
+
max: 150,
|
|
654
|
+
step: 1.2,
|
|
655
|
+
},
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Programmatic zoom control
|
|
659
|
+
chart.zoomTo(50) // Set zoom level to 50px per day (or month)
|
|
660
|
+
chart.zoomToFit() // Auto-fit all tasks into the visible container width
|
|
661
|
+
chart.resetZoom() // Reset to original configuration scale
|
|
662
|
+
|
|
663
|
+
// Listen to zoom level changes
|
|
664
|
+
chart.addEventListener('zoom-change', (e) => {
|
|
665
|
+
console.log('New zoom level:', e.detail.pxPerDay || e.detail.pxPerMonth)
|
|
666
|
+
})
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
#### getRowPositions
|
|
670
|
+
|
|
671
|
+
Returns layout metrics (`top`, `height`, `bottom`) for all rows within the virtual container.
|
|
672
|
+
|
|
673
|
+
```javascript
|
|
674
|
+
const rowPositions = chart.getRowPositions()
|
|
675
|
+
console.log('Row positions:', rowPositions)
|
|
676
|
+
```
|
|
677
|
+
|
|
470
678
|
### Keyboard Operations
|
|
471
679
|
|
|
472
|
-
When the Gantt chart
|
|
680
|
+
When the Gantt chart element is focused, keyboard shortcuts allow fast navigation, selection, movement, and deletion:
|
|
473
681
|
|
|
474
682
|
| Key | Action |
|
|
475
683
|
| :--- | :--- |
|
|
476
684
|
| `←` `→` | Move focus between tasks |
|
|
477
685
|
| `↑` `↓` | Move focus to another row |
|
|
478
686
|
| `Enter` / `Space` | Select the focused task |
|
|
479
|
-
| `Ctrl/Cmd + Enter` | Toggle selection (multi-select) |
|
|
480
|
-
| `Shift + ←` `→` | Move selected tasks |
|
|
481
|
-
| `Delete` / `Backspace` |
|
|
482
|
-
| `Escape` | Clear selection and focus |
|
|
687
|
+
| `Ctrl/Cmd + Enter` | Toggle selection state (multi-select) |
|
|
688
|
+
| `Shift + ←` `→` | Move selected tasks backward / forward |
|
|
689
|
+
| `Delete` / `Backspace` | Trigger `task-delete` event |
|
|
690
|
+
| `Escape` | Clear current selection and focus |
|
|
483
691
|
|
|
484
692
|
```javascript
|
|
485
693
|
const option = {
|
|
486
694
|
keyboard: {
|
|
487
|
-
enabled: true,
|
|
488
|
-
moveStep: 60,
|
|
695
|
+
enabled: true, // Default: true
|
|
696
|
+
moveStep: 60, // Move distance per Shift+Arrow key press (minutes)
|
|
489
697
|
},
|
|
490
698
|
// ...
|
|
491
699
|
}
|
|
@@ -493,4 +701,4 @@ const option = {
|
|
|
493
701
|
|
|
494
702
|
## License
|
|
495
703
|
|
|
496
|
-
MIT
|
|
704
|
+
[MIT License](LICENSE)
|