@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 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), 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
35
- - 🗺️ **Overview Minimap**: Bird's-eye preview of the entire chart, interactive pan & scroll synchronization, click-to-jump, and collapsible floating window
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 mode
39
- - Snap feature (grid snap by time unit, automatic monthly snap in month view)
40
- - `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
41
56
  - Programmatic task selection + auto-scroll (`selectTask`)
42
- - ⌨️ **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.
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
- 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).
55
73
 
56
74
  ## Usage with Vue.js
57
75
 
58
- Example using Vue.js (Vue 3).
59
- 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`.
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 { GanttRow, GanttChartOption, TaskUpdateEventDetail } from '@mogura/moguchart-core'
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('2024-01-01'),
76
- end: new Date('2024-01-05'),
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('2024-01-03'),
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('2024-01-01'),
95
- end: new Date('2024-03-31'),
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('2024-02-01'),
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: 500px;">
120
- <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>
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 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.
129
168
 
130
169
  ```tsx
131
170
  import { useEffect, useRef, useState } from 'react'
132
171
  import '@mogura/moguchart-core'
133
- import type { GanttRow, GanttChartOption, TaskUpdateEventDetail } from '@mogura/moguchart-core'
172
+ import type {
173
+ GanttRow,
174
+ GanttChartOption,
175
+ TaskUpdateEventDetail,
176
+ } from '@mogura/moguchart-core'
134
177
 
135
- // Type definition for TypeScript
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('2024-01-01'),
156
- end: new Date('2024-01-05'),
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('2024-01-03'),
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('2024-01-01'),
175
- end: new Date('2024-03-31'),
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('2024-02-01'),
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
- // Set properties
251
+ // Bind properties
197
252
  chart.rows = rows
198
253
  chart.option = option
199
254
 
200
- // Set up event listeners
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: '500px' }}>
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, 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`.
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 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.
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
- 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.
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 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.
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('2024-01-01'),
359
- end: new Date('2024-01-05'),
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, // Use preset
362
- // or specify directly:
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 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`.
368
363
 
369
364
  ### Row Reordering
370
365
 
371
- Set `enableRowReordering: true` to enable drag & drop row reordering.
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` (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.
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
- // Multi-selection drag drop: apply same dx to all selected tasks
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 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.
403
409
 
404
410
  ```javascript
405
411
  const option = {
406
- snapDuration: 60, // Snap every hour (default: 1440 = 1 day)
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` 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.
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 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.
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=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' : ''}`,
442
601
  },
443
602
  }
444
603
  ```
@@ -447,7 +606,7 @@ const option = {
447
606
 
448
607
  #### selectTask
449
608
 
450
- 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.
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
- 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).
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 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:
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` | Fire `task-delete` event |
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, // Default: true
488
- 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)
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)