@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 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), works in any environment.
12
- - ⚡ **Virtual Scrolling**: Smooth performance even with large numbers of tasks and rows.
13
- - 🖱️ **Interactive**:
14
- - Drag & drop task movement (including cross-row moves)
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
- - Multi-task selection & batch drag (Ctrl/Cmd + click)
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 themes
23
- - Task bar fill patterns (13 types including stripes, dots, checkerboard, etc.)
24
- - CSS styling
25
- - 🔗 **Dependency Visualization**: Curved lines with arrows showing task dependencies (S-curve support for reverse direction). Automatic critical path detection and highlighting
26
- - 📅 **Flexible Calendar**:
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
- - Adjustable zoom level (pixels per day or per month) and display period
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
- - Locale support (Japanese, English, and custom locales)
33
- - 🏁 **Milestones**: Display milestones (vertical line + name badge) on the chart
34
- - 📍 **Markers**: Show triangle icons with labels on row timelines
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 mode
38
- - Snap feature (grid snap by time unit, automatic monthly snap in month view)
39
- - `hitTest` method for getting row/date from coordinates
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
- - ⌨️ **Keyboard Operations**: Arrow key navigation & selection, Shift+Arrow task movement, Delete key deletion
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
- See [API.en.md](./doc/API.en.md) for a detailed API reference.
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.js (Vue 3).
58
- When using Web Components, you may need to configure your build tool (e.g., `vite.config.ts`) to recognize custom elements.
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 { GanttRow, GanttChartOption, TaskUpdateEventDetail } from '@mogura/moguchart-core'
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('2024-01-01'),
75
- end: new Date('2024-01-05'),
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('2024-01-03'),
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('2024-01-01'),
94
- end: new Date('2024-03-31'),
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('2024-02-01'),
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: 500px;">
119
- <gantt-chart :rows="rows" :option="option" @task-update="handleTaskUpdate"></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 require direct property and event handling, use `ref` for implementation.
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 { GanttRow, GanttChartOption, TaskUpdateEventDetail } from '@mogura/moguchart-core'
172
+ import type {
173
+ GanttRow,
174
+ GanttChartOption,
175
+ TaskUpdateEventDetail,
176
+ } from '@mogura/moguchart-core'
133
177
 
134
- // Type definition for TypeScript
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('2024-01-01'),
155
- end: new Date('2024-01-05'),
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('2024-01-03'),
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('2024-01-01'),
174
- end: new Date('2024-03-31'),
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('2024-02-01'),
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
- // Set properties
251
+ // Bind properties
196
252
  chart.rows = rows
197
253
  chart.option = option
198
254
 
199
- // Set up event listeners
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: '500px' }}>
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, dark, and system. Individual colors can be overridden using `customTheme`.
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 milestones to `calendar.milestones` to display vertical lines and badges on the chart. Hover effects transition opacity on mouseover.
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
- Pass an array of markers to each row's `markers` property to display triangle icons with labels on the timeline.
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 types of fill patterns to task bars. Preset constants are also available.
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('2024-01-01'),
358
- end: new Date('2024-01-05'),
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, // Use preset
361
- // or specify directly:
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 patterns: `diagonal-stripe` `diagonal-stripe-thin` `diagonal-stripe-thick` `diagonal-stripe-reverse` `vertical-stripe` `horizontal-stripe` `checkerboard` `dots` `dots-dense` `triangle` `circle` `grid` `diagonal-grid`
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 enable drag & drop row reordering.
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` (Mac: `Cmd`) and click task bars to select multiple tasks, then drag them together.
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
- // Multi-selection drag drop: apply same dx to all selected tasks
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 snap interval when dragging tasks with `snapDuration` (in minutes). When using monthly view mode (`pxPerMonth`), snapping is automatically enforced at monthly boundaries.
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 every hour (default: 1440 = 1 day)
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` for a two-row calendar header with week numbers. This mode is enabled automatically when `pxPerDay` is less than 20.
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 each month at a fixed equal width. Snapping is automatically enforced at monthly boundaries.
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=year, bottom=month
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 the task with the specified ID and auto-scrolls if it's off-screen.
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
- Returns the corresponding row ID and date from client coordinates (pixel position on screen).
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 has focus, you can navigate, select, move, and delete tasks using the keyboard.
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` | Fire `task-delete` event |
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, // Default: true
487
- moveStep: 60, // Move amount per Shift+Arrow key press (minutes)
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)