@mogura/moguchart-core 0.10.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 -139
- package/README.md +147 -4
- package/dist/components/gantt-bar.d.ts +3 -0
- package/dist/components/gantt-chart.d.ts +15 -0
- package/dist/components/gantt-minimap.d.ts +105 -0
- package/dist/core/i18n.d.ts +2 -0
- package/dist/core/types.d.ts +145 -0
- package/dist/core/utils.d.ts +28 -1
- package/dist/index.d.ts +2 -0
- package/dist/moguchart-core.mjs +1210 -142
- package/dist/moguchart-core.umd.js +567 -12
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -2,43 +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**:
|
|
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).
|
|
35
51
|
- ✨ **Advanced Integration**:
|
|
36
52
|
- External drag & drop for task creation
|
|
37
|
-
- Task move/copy
|
|
38
|
-
- Snap feature (
|
|
39
|
-
- `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
|
|
40
56
|
- Programmatic task selection + auto-scroll (`selectTask`)
|
|
41
|
-
-
|
|
57
|
+
- Row layout coordinates inspection (`getRowPositions`)
|
|
58
|
+
- ⌨️ **Keyboard Navigation**: Arrow key navigation & selection, Shift + Arrow task movement, Delete / Backspace deletion.
|
|
42
59
|
|
|
43
60
|
## Installation
|
|
44
61
|
|
|
@@ -46,22 +63,28 @@ A lightweight yet feature-rich Gantt chart Web Component built with Lit. Works w
|
|
|
46
63
|
pnpm add @mogura/moguchart-core
|
|
47
64
|
# or
|
|
48
65
|
npm install @mogura/moguchart-core
|
|
66
|
+
# or
|
|
67
|
+
yarn add @mogura/moguchart-core
|
|
49
68
|
```
|
|
50
69
|
|
|
51
70
|
## API Reference
|
|
52
71
|
|
|
53
|
-
|
|
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).
|
|
54
73
|
|
|
55
74
|
## Usage with Vue.js
|
|
56
75
|
|
|
57
|
-
Example using Vue
|
|
58
|
-
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`.
|
|
59
78
|
|
|
60
79
|
```html
|
|
61
80
|
<script setup lang="ts">
|
|
62
81
|
import { ref } from 'vue'
|
|
63
82
|
import '@mogura/moguchart-core'
|
|
64
|
-
import type {
|
|
83
|
+
import type {
|
|
84
|
+
GanttRow,
|
|
85
|
+
GanttChartOption,
|
|
86
|
+
TaskUpdateEventDetail,
|
|
87
|
+
} from '@mogura/moguchart-core'
|
|
65
88
|
|
|
66
89
|
const rows = ref<GanttRow[]>([
|
|
67
90
|
{
|
|
@@ -71,8 +94,9 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
71
94
|
{
|
|
72
95
|
id: 't-1',
|
|
73
96
|
name: 'Task 1',
|
|
74
|
-
start: new Date('
|
|
75
|
-
end: new Date('
|
|
97
|
+
start: new Date('2025-01-01'),
|
|
98
|
+
end: new Date('2025-01-05'),
|
|
99
|
+
progress: 60,
|
|
76
100
|
style: 'background-color: #60a5fa',
|
|
77
101
|
},
|
|
78
102
|
],
|
|
@@ -80,7 +104,7 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
80
104
|
{
|
|
81
105
|
id: 'marker-1',
|
|
82
106
|
name: 'Review Deadline',
|
|
83
|
-
date: new Date('
|
|
107
|
+
date: new Date('2025-01-03'),
|
|
84
108
|
type: 'triangle-down',
|
|
85
109
|
color: '#ef4444',
|
|
86
110
|
},
|
|
@@ -90,15 +114,15 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
90
114
|
|
|
91
115
|
const option = ref<GanttChartOption>({
|
|
92
116
|
calendar: {
|
|
93
|
-
start: new Date('
|
|
94
|
-
end: new Date('
|
|
117
|
+
start: new Date('2025-01-01'),
|
|
118
|
+
end: new Date('2025-03-31'),
|
|
95
119
|
pxPerDay: 30,
|
|
96
120
|
showCurrentTime: true,
|
|
97
121
|
milestones: [
|
|
98
122
|
{
|
|
99
123
|
id: 'ms-1',
|
|
100
124
|
name: 'Release',
|
|
101
|
-
start: new Date('
|
|
125
|
+
start: new Date('2025-02-01'),
|
|
102
126
|
color: '#8b5cf6',
|
|
103
127
|
},
|
|
104
128
|
],
|
|
@@ -106,6 +130,18 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
106
130
|
bar: { height: 28 },
|
|
107
131
|
rowHeader: { width: 200 },
|
|
108
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
|
+
},
|
|
109
145
|
})
|
|
110
146
|
|
|
111
147
|
const handleTaskUpdate = (e: Event) => {
|
|
@@ -115,23 +151,31 @@ When using Web Components, you may need to configure your build tool (e.g., `vit
|
|
|
115
151
|
</script>
|
|
116
152
|
|
|
117
153
|
<template>
|
|
118
|
-
<div style="height:
|
|
119
|
-
<gantt-chart
|
|
154
|
+
<div style="height: 600px;">
|
|
155
|
+
<gantt-chart
|
|
156
|
+
:rows="rows"
|
|
157
|
+
:option="option"
|
|
158
|
+
@task-update="handleTaskUpdate"
|
|
159
|
+
></gantt-chart>
|
|
120
160
|
</div>
|
|
121
161
|
</template>
|
|
122
162
|
```
|
|
123
163
|
|
|
124
164
|
## Usage with React
|
|
125
165
|
|
|
126
|
-
Example using React.
|
|
127
|
-
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.
|
|
128
168
|
|
|
129
169
|
```tsx
|
|
130
170
|
import { useEffect, useRef, useState } from 'react'
|
|
131
171
|
import '@mogura/moguchart-core'
|
|
132
|
-
import type {
|
|
172
|
+
import type {
|
|
173
|
+
GanttRow,
|
|
174
|
+
GanttChartOption,
|
|
175
|
+
TaskUpdateEventDetail,
|
|
176
|
+
} from '@mogura/moguchart-core'
|
|
133
177
|
|
|
134
|
-
// Type definition for
|
|
178
|
+
// Type definition for JSX Custom Element
|
|
135
179
|
declare global {
|
|
136
180
|
namespace JSX {
|
|
137
181
|
interface IntrinsicElements {
|
|
@@ -151,8 +195,9 @@ export default function App() {
|
|
|
151
195
|
{
|
|
152
196
|
id: 't-1',
|
|
153
197
|
name: 'Task 1',
|
|
154
|
-
start: new Date('
|
|
155
|
-
end: new Date('
|
|
198
|
+
start: new Date('2025-01-01'),
|
|
199
|
+
end: new Date('2025-01-05'),
|
|
200
|
+
progress: 50,
|
|
156
201
|
style: 'background-color: #60a5fa',
|
|
157
202
|
},
|
|
158
203
|
],
|
|
@@ -160,7 +205,7 @@ export default function App() {
|
|
|
160
205
|
{
|
|
161
206
|
id: 'marker-1',
|
|
162
207
|
name: 'Review Deadline',
|
|
163
|
-
date: new Date('
|
|
208
|
+
date: new Date('2025-01-03'),
|
|
164
209
|
type: 'triangle-down',
|
|
165
210
|
color: '#ef4444',
|
|
166
211
|
},
|
|
@@ -170,15 +215,15 @@ export default function App() {
|
|
|
170
215
|
|
|
171
216
|
const [option] = useState<GanttChartOption>({
|
|
172
217
|
calendar: {
|
|
173
|
-
start: new Date('
|
|
174
|
-
end: new Date('
|
|
218
|
+
start: new Date('2025-01-01'),
|
|
219
|
+
end: new Date('2025-03-31'),
|
|
175
220
|
pxPerDay: 30,
|
|
176
221
|
showCurrentTime: true,
|
|
177
222
|
milestones: [
|
|
178
223
|
{
|
|
179
224
|
id: 'ms-1',
|
|
180
225
|
name: 'Release',
|
|
181
|
-
start: new Date('
|
|
226
|
+
start: new Date('2025-02-01'),
|
|
182
227
|
color: '#8b5cf6',
|
|
183
228
|
},
|
|
184
229
|
],
|
|
@@ -186,17 +231,28 @@ export default function App() {
|
|
|
186
231
|
bar: { height: 28 },
|
|
187
232
|
rowHeader: { width: 200 },
|
|
188
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
|
+
},
|
|
189
245
|
})
|
|
190
246
|
|
|
191
247
|
useEffect(() => {
|
|
192
248
|
const chart = chartRef.current
|
|
193
249
|
if (!chart) return
|
|
194
250
|
|
|
195
|
-
//
|
|
251
|
+
// Bind properties
|
|
196
252
|
chart.rows = rows
|
|
197
253
|
chart.option = option
|
|
198
254
|
|
|
199
|
-
//
|
|
255
|
+
// Bind event listeners
|
|
200
256
|
const handleTaskUpdate = (e: Event) => {
|
|
201
257
|
const detail = (e as CustomEvent<TaskUpdateEventDetail>).detail
|
|
202
258
|
console.log('Task updated:', detail)
|
|
@@ -210,7 +266,7 @@ export default function App() {
|
|
|
210
266
|
}, [rows, option])
|
|
211
267
|
|
|
212
268
|
return (
|
|
213
|
-
<div style={{ height: '
|
|
269
|
+
<div style={{ height: '600px' }}>
|
|
214
270
|
<gantt-chart ref={chartRef}></gantt-chart>
|
|
215
271
|
</div>
|
|
216
272
|
)
|
|
@@ -221,7 +277,7 @@ export default function App() {
|
|
|
221
277
|
|
|
222
278
|
### Themes
|
|
223
279
|
|
|
224
|
-
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`.
|
|
225
281
|
|
|
226
282
|
```javascript
|
|
227
283
|
const option = {
|
|
@@ -230,75 +286,15 @@ const option = {
|
|
|
230
286
|
bg: '#1a1a2e',
|
|
231
287
|
text: '#e0e0e0',
|
|
232
288
|
currentTimeLine: '#ff6b6b',
|
|
289
|
+
criticalPath: '#ef4444',
|
|
233
290
|
},
|
|
234
291
|
// ...
|
|
235
292
|
}
|
|
236
293
|
```
|
|
237
294
|
|
|
238
|
-
### Dependency Line Settings
|
|
239
|
-
|
|
240
|
-
Customize the dependency line display with the `dependency` option. Control arrow visibility and size.
|
|
241
|
-
Reverse-direction (right-to-left) dependencies are automatically rendered with S-curves, with horizontal connections at contact points.
|
|
242
|
-
|
|
243
|
-
```javascript
|
|
244
|
-
const option = {
|
|
245
|
-
dependency: {
|
|
246
|
-
showArrows: true, // Show arrows (default: true)
|
|
247
|
-
arrowSize: 12, // Arrow size in px (default: 8)
|
|
248
|
-
},
|
|
249
|
-
// ...
|
|
250
|
-
}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### Internationalization (i18n)
|
|
254
|
-
|
|
255
|
-
moguchart-core provides built-in locale support. Japanese is the default locale for backward compatibility. Switch to English or create custom locales.
|
|
256
|
-
|
|
257
|
-
```javascript
|
|
258
|
-
import { enLocale } from '@mogura/moguchart-core'
|
|
259
|
-
|
|
260
|
-
const option = {
|
|
261
|
-
locale: enLocale,
|
|
262
|
-
// ...
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
To create a custom locale, implement the `MoguchartLocale` interface:
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
import type { MoguchartLocale } from '@mogura/moguchart-core'
|
|
270
|
-
|
|
271
|
-
const frLocale: MoguchartLocale = {
|
|
272
|
-
monthFormat: 'MMM YYYY',
|
|
273
|
-
monthRowFormat: 'MMM',
|
|
274
|
-
dateFormat: (d) => `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`,
|
|
275
|
-
timeUnitDateFormat: (d) => `${d.getDate()} ${['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'][d.getMonth()]} ${d.getFullYear()}`,
|
|
276
|
-
dateTimeFormat: (d) => {
|
|
277
|
-
const date = `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`
|
|
278
|
-
const h = d.getHours()
|
|
279
|
-
const m = d.getMinutes()
|
|
280
|
-
if (h === 0 && m === 0) return date
|
|
281
|
-
return `${date} ${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`
|
|
282
|
-
},
|
|
283
|
-
yearMonthFormat: (d) => `${d.getFullYear()}/${d.getMonth() + 1}`,
|
|
284
|
-
duration: {
|
|
285
|
-
days: (n) => `${n} jour${n > 1 ? 's' : ''}`,
|
|
286
|
-
hours: (n) => `${n} heure${n > 1 ? 's' : ''}`,
|
|
287
|
-
minutes: (n) => `${n} minute${n > 1 ? 's' : ''}`,
|
|
288
|
-
zero: '0 minute',
|
|
289
|
-
},
|
|
290
|
-
tooltip: { duration: (d) => `Durée: ${d} jour${d > 1 ? 's' : ''}` },
|
|
291
|
-
dragOverlay: {
|
|
292
|
-
noTitle: 'Sans titre',
|
|
293
|
-
moveTo: (name) => `Déplacer vers: ${name}`,
|
|
294
|
-
movingTasks: (c) => `Déplacement de ${c} tâche${c > 1 ? 's' : ''}`,
|
|
295
|
-
},
|
|
296
|
-
}
|
|
297
|
-
```
|
|
298
|
-
|
|
299
295
|
### Milestones
|
|
300
296
|
|
|
301
|
-
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.
|
|
302
298
|
|
|
303
299
|
```javascript
|
|
304
300
|
option.calendar.milestones = [
|
|
@@ -320,16 +316,14 @@ option.calendar.milestones = [
|
|
|
320
316
|
|
|
321
317
|
### Markers
|
|
322
318
|
|
|
323
|
-
|
|
319
|
+
Add markers to any row's `markers` property to display triangle icons with text labels along the timeline.
|
|
324
320
|
|
|
325
321
|
```javascript
|
|
326
322
|
const rows = [
|
|
327
323
|
{
|
|
328
324
|
id: 'row-1',
|
|
329
325
|
name: 'Task A',
|
|
330
|
-
tasks: [
|
|
331
|
-
/* ... */
|
|
332
|
-
],
|
|
326
|
+
tasks: [/* ... */],
|
|
333
327
|
markers: [
|
|
334
328
|
{
|
|
335
329
|
id: 'marker-1',
|
|
@@ -337,6 +331,7 @@ const rows = [
|
|
|
337
331
|
date: new Date('2025-04-10'),
|
|
338
332
|
anchor: 'end',
|
|
339
333
|
type: 'triangle-right',
|
|
334
|
+
fontSize: 'sm', // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
340
335
|
color: '#ef4444',
|
|
341
336
|
},
|
|
342
337
|
],
|
|
@@ -346,7 +341,7 @@ const rows = [
|
|
|
346
341
|
|
|
347
342
|
### Task Bar Patterns
|
|
348
343
|
|
|
349
|
-
Apply 13
|
|
344
|
+
Apply any of the 13 built-in SVG patterns to task bars. Preset constants are exported for type safety.
|
|
350
345
|
|
|
351
346
|
```javascript
|
|
352
347
|
import { PATTERN_DIAGONAL_STRIPE } from '@mogura/moguchart-core'
|
|
@@ -354,20 +349,21 @@ import { PATTERN_DIAGONAL_STRIPE } from '@mogura/moguchart-core'
|
|
|
354
349
|
const task = {
|
|
355
350
|
id: 't-1',
|
|
356
351
|
name: 'WIP',
|
|
357
|
-
start: new Date('
|
|
358
|
-
end: new Date('
|
|
352
|
+
start: new Date('2025-01-01'),
|
|
353
|
+
end: new Date('2025-01-05'),
|
|
359
354
|
style: 'background-color: #60a5fa',
|
|
360
|
-
pattern: PATTERN_DIAGONAL_STRIPE, //
|
|
361
|
-
// or specify
|
|
355
|
+
pattern: PATTERN_DIAGONAL_STRIPE, // Using preset
|
|
356
|
+
// or specify custom pattern:
|
|
362
357
|
// pattern: { type: 'checkerboard', color: '#ffffff80' }
|
|
363
358
|
}
|
|
364
359
|
```
|
|
365
360
|
|
|
366
|
-
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`.
|
|
367
363
|
|
|
368
364
|
### Row Reordering
|
|
369
365
|
|
|
370
|
-
Set `enableRowReordering: true` to
|
|
366
|
+
Set `enableRowReordering: true` to allow users to reorder rows via drag & drop.
|
|
371
367
|
|
|
372
368
|
```javascript
|
|
373
369
|
const option = {
|
|
@@ -380,15 +376,26 @@ chart.addEventListener('row-reordered', (e) => {
|
|
|
380
376
|
})
|
|
381
377
|
```
|
|
382
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
|
+
|
|
383
390
|
### Multi-Task Selection & Batch Operations
|
|
384
391
|
|
|
385
|
-
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.
|
|
386
393
|
|
|
387
394
|
```javascript
|
|
388
395
|
chart.addEventListener('task-update', (e) => {
|
|
389
396
|
const detail = e.detail
|
|
390
397
|
if (!detail.isDragging && detail.selectedTaskIds?.length > 1) {
|
|
391
|
-
//
|
|
398
|
+
// Drop event for multi-task selection
|
|
392
399
|
for (const taskId of detail.selectedTaskIds) {
|
|
393
400
|
applyDxToTask(taskId, detail.dx)
|
|
394
401
|
}
|
|
@@ -398,11 +405,11 @@ chart.addEventListener('task-update', (e) => {
|
|
|
398
405
|
|
|
399
406
|
### Snap Feature
|
|
400
407
|
|
|
401
|
-
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.
|
|
402
409
|
|
|
403
410
|
```javascript
|
|
404
411
|
const option = {
|
|
405
|
-
snapDuration: 60, // Snap
|
|
412
|
+
snapDuration: 60, // Snap to 1-hour increments (default: 1440 = 1 day)
|
|
406
413
|
// ...
|
|
407
414
|
}
|
|
408
415
|
```
|
|
@@ -411,7 +418,7 @@ const option = {
|
|
|
411
418
|
|
|
412
419
|
#### Week View Mode
|
|
413
420
|
|
|
414
|
-
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.
|
|
415
422
|
|
|
416
423
|
```javascript
|
|
417
424
|
const option = {
|
|
@@ -428,7 +435,7 @@ const option = {
|
|
|
428
435
|
|
|
429
436
|
#### Monthly View Mode
|
|
430
437
|
|
|
431
|
-
Set `calendar.pxPerMonth` to render
|
|
438
|
+
Set `calendar.pxPerMonth` to render months with equal pixel widths, suitable for long-term project planning.
|
|
432
439
|
|
|
433
440
|
```javascript
|
|
434
441
|
const option = {
|
|
@@ -437,7 +444,160 @@ const option = {
|
|
|
437
444
|
end: new Date('2027-12-31'),
|
|
438
445
|
pxPerDay: 1,
|
|
439
446
|
pxPerMonth: 120, // 120px per month
|
|
440
|
-
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' : ''}`,
|
|
441
601
|
},
|
|
442
602
|
}
|
|
443
603
|
```
|
|
@@ -446,7 +606,7 @@ const option = {
|
|
|
446
606
|
|
|
447
607
|
#### selectTask
|
|
448
608
|
|
|
449
|
-
Selects
|
|
609
|
+
Selects a task by ID and automatically scrolls the chart to bring it into view.
|
|
450
610
|
|
|
451
611
|
```javascript
|
|
452
612
|
const chart = document.querySelector('gantt-chart')
|
|
@@ -455,7 +615,7 @@ const found = chart.selectTask('task-1')
|
|
|
455
615
|
|
|
456
616
|
#### hitTest
|
|
457
617
|
|
|
458
|
-
|
|
618
|
+
Determines the row ID and calendar date corresponding to a given screen coordinate (e.g. from mouse events).
|
|
459
619
|
|
|
460
620
|
```javascript
|
|
461
621
|
document.addEventListener('mousemove', (e) => {
|
|
@@ -466,25 +626,74 @@ document.addEventListener('mousemove', (e) => {
|
|
|
466
626
|
})
|
|
467
627
|
```
|
|
468
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
|
+
|
|
469
678
|
### Keyboard Operations
|
|
470
679
|
|
|
471
|
-
When the Gantt chart
|
|
680
|
+
When the Gantt chart element is focused, keyboard shortcuts allow fast navigation, selection, movement, and deletion:
|
|
472
681
|
|
|
473
682
|
| Key | Action |
|
|
474
683
|
| :--- | :--- |
|
|
475
684
|
| `←` `→` | Move focus between tasks |
|
|
476
685
|
| `↑` `↓` | Move focus to another row |
|
|
477
686
|
| `Enter` / `Space` | Select the focused task |
|
|
478
|
-
| `Ctrl/Cmd + Enter` | Toggle selection (multi-select) |
|
|
479
|
-
| `Shift + ←` `→` | Move selected tasks |
|
|
480
|
-
| `Delete` / `Backspace` |
|
|
481
|
-
| `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 |
|
|
482
691
|
|
|
483
692
|
```javascript
|
|
484
693
|
const option = {
|
|
485
694
|
keyboard: {
|
|
486
|
-
enabled: true,
|
|
487
|
-
moveStep: 60,
|
|
695
|
+
enabled: true, // Default: true
|
|
696
|
+
moveStep: 60, // Move distance per Shift+Arrow key press (minutes)
|
|
488
697
|
},
|
|
489
698
|
// ...
|
|
490
699
|
}
|
|
@@ -492,4 +701,4 @@ const option = {
|
|
|
492
701
|
|
|
493
702
|
## License
|
|
494
703
|
|
|
495
|
-
MIT
|
|
704
|
+
[MIT License](LICENSE)
|