@mogura/moguchart-core 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +491 -0
- package/README.md +470 -0
- package/dist/components/gantt-bar.d.ts +38 -0
- package/dist/components/gantt-calendar.d.ts +43 -0
- package/dist/components/gantt-chart-dependency-path.d.ts +15 -0
- package/dist/components/gantt-chart-export.d.ts +20 -0
- package/dist/components/gantt-chart-styles.d.ts +11 -0
- package/dist/components/gantt-chart.d.ts +169 -0
- package/dist/components/gantt-row-background.d.ts +21 -0
- package/dist/components/gantt-row.d.ts +53 -0
- package/dist/core/constants.d.ts +14 -0
- package/dist/core/i18n.d.ts +52 -0
- package/dist/core/patterns.d.ts +21 -0
- package/dist/core/theme.d.ts +2 -0
- package/dist/core/types.d.ts +612 -0
- package/dist/core/utils.d.ts +57 -0
- package/dist/favicon.png +0 -0
- package/dist/index.d.ts +7 -0
- package/dist/moguchart-core.mjs +3163 -0
- package/dist/moguchart-core.umd.js +1115 -0
- package/package.json +76 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-present Murakami Hiroyuki
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
# @mogura/moguchart-core
|
|
2
|
+
|
|
3
|
+
A lightweight yet feature-rich Gantt chart Web Component built with Lit. Works with Vue, React, Angular, Svelte, and any other framework.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Framework-agnostic**: Built as Web Components (Custom Elements), works in any environment.
|
|
8
|
+
- ⚡ **Virtual Scrolling**: Smooth performance even with large numbers of tasks and rows.
|
|
9
|
+
- 🖱️ **Interactive**:
|
|
10
|
+
- Drag & drop task movement (including cross-row moves)
|
|
11
|
+
- Handle-based duration resizing
|
|
12
|
+
- Drag & drop row reordering
|
|
13
|
+
- Column header width resizing
|
|
14
|
+
- Multi-task selection & batch drag (Ctrl/Cmd + click)
|
|
15
|
+
- Double-click and right-click event handling
|
|
16
|
+
- 🎨 **Highly Customizable**:
|
|
17
|
+
- Custom rendering for task bars, row headers, tooltips, and drag info
|
|
18
|
+
- Light/Dark/System theme switching + custom color themes
|
|
19
|
+
- Task bar fill patterns (13 types including stripes, dots, checkerboard, etc.)
|
|
20
|
+
- CSS styling
|
|
21
|
+
- 🔗 **Dependency Visualization**: Curved lines with arrows showing task dependencies (S-curve support for reverse direction)
|
|
22
|
+
- 📅 **Flexible Calendar**:
|
|
23
|
+
- Day / Week / Month view switching
|
|
24
|
+
- Adjustable zoom level (pixels per day or per month) and display period
|
|
25
|
+
- Current time line with badge (auto-refresh support)
|
|
26
|
+
- Custom holiday detection logic
|
|
27
|
+
- Configurable week start day
|
|
28
|
+
- Locale support (Japanese, English, and custom locales)
|
|
29
|
+
- 🏁 **Milestones**: Display milestones (vertical line + name badge) on the chart
|
|
30
|
+
- 📍 **Markers**: Show triangle icons with labels on row timelines
|
|
31
|
+
- ✨ **Advanced Integration**:
|
|
32
|
+
- External drag & drop for task creation
|
|
33
|
+
- Task move/copy mode
|
|
34
|
+
- Snap feature (grid snap by time unit, automatic monthly snap in month view)
|
|
35
|
+
- `hitTest` method for getting row/date from coordinates
|
|
36
|
+
- Programmatic task selection + auto-scroll (`selectTask`)
|
|
37
|
+
- ⌨️ **Keyboard Operations**: Arrow key navigation & selection, Shift+Arrow task movement, Delete key deletion
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pnpm add @mogura/moguchart-core
|
|
43
|
+
# or
|
|
44
|
+
npm install @mogura/moguchart-core
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API Reference
|
|
48
|
+
|
|
49
|
+
See [API.en.md](./doc/API.en.md) for a detailed API reference.
|
|
50
|
+
|
|
51
|
+
## Usage with Vue.js
|
|
52
|
+
|
|
53
|
+
Example using Vue.js (Vue 3).
|
|
54
|
+
When using Web Components, you may need to configure your build tool (e.g., `vite.config.ts`) to recognize custom elements.
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<script setup lang="ts">
|
|
58
|
+
import { ref } from 'vue'
|
|
59
|
+
import '@mogura/moguchart-core'
|
|
60
|
+
import type { GanttRow, GanttChartOption, TaskUpdateEventDetail } from '@mogura/moguchart-core'
|
|
61
|
+
|
|
62
|
+
const rows = ref<GanttRow[]>([
|
|
63
|
+
{
|
|
64
|
+
id: 'row-1',
|
|
65
|
+
name: 'Project A',
|
|
66
|
+
tasks: [
|
|
67
|
+
{
|
|
68
|
+
id: 't-1',
|
|
69
|
+
name: 'Task 1',
|
|
70
|
+
start: new Date('2024-01-01'),
|
|
71
|
+
end: new Date('2024-01-05'),
|
|
72
|
+
style: 'background-color: #60a5fa',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
markers: [
|
|
76
|
+
{
|
|
77
|
+
id: 'marker-1',
|
|
78
|
+
name: 'Review Deadline',
|
|
79
|
+
date: new Date('2024-01-03'),
|
|
80
|
+
type: 'triangle-down',
|
|
81
|
+
color: '#ef4444',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
])
|
|
86
|
+
|
|
87
|
+
const option = ref<GanttChartOption>({
|
|
88
|
+
calendar: {
|
|
89
|
+
start: new Date('2024-01-01'),
|
|
90
|
+
end: new Date('2024-03-31'),
|
|
91
|
+
pxPerDay: 30,
|
|
92
|
+
showCurrentTime: true,
|
|
93
|
+
milestones: [
|
|
94
|
+
{
|
|
95
|
+
id: 'ms-1',
|
|
96
|
+
name: 'Release',
|
|
97
|
+
start: new Date('2024-02-01'),
|
|
98
|
+
color: '#8b5cf6',
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
bar: { height: 28 },
|
|
103
|
+
rowHeader: { width: 200 },
|
|
104
|
+
theme: 'system',
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const handleTaskUpdate = (e: Event) => {
|
|
108
|
+
const detail = (e as CustomEvent<TaskUpdateEventDetail>).detail
|
|
109
|
+
console.log('Task updated:', detail)
|
|
110
|
+
}
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<template>
|
|
114
|
+
<div style="height: 500px;">
|
|
115
|
+
<gantt-chart :rows="rows" :option="option" @task-update="handleTaskUpdate"></gantt-chart>
|
|
116
|
+
</div>
|
|
117
|
+
</template>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Usage with React
|
|
121
|
+
|
|
122
|
+
Example using React.
|
|
123
|
+
Since Web Components require direct property and event handling, use `ref` for implementation.
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { useEffect, useRef, useState } from 'react'
|
|
127
|
+
import '@mogura/moguchart-core'
|
|
128
|
+
import type { GanttRow, GanttChartOption, TaskUpdateEventDetail } from '@mogura/moguchart-core'
|
|
129
|
+
|
|
130
|
+
// Type definition for TypeScript
|
|
131
|
+
declare global {
|
|
132
|
+
namespace JSX {
|
|
133
|
+
interface IntrinsicElements {
|
|
134
|
+
'gantt-chart': any
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export default function App() {
|
|
140
|
+
const chartRef = useRef<any>(null)
|
|
141
|
+
|
|
142
|
+
const [rows] = useState<GanttRow[]>([
|
|
143
|
+
{
|
|
144
|
+
id: 'row-1',
|
|
145
|
+
name: 'Project A',
|
|
146
|
+
tasks: [
|
|
147
|
+
{
|
|
148
|
+
id: 't-1',
|
|
149
|
+
name: 'Task 1',
|
|
150
|
+
start: new Date('2024-01-01'),
|
|
151
|
+
end: new Date('2024-01-05'),
|
|
152
|
+
style: 'background-color: #60a5fa',
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
markers: [
|
|
156
|
+
{
|
|
157
|
+
id: 'marker-1',
|
|
158
|
+
name: 'Review Deadline',
|
|
159
|
+
date: new Date('2024-01-03'),
|
|
160
|
+
type: 'triangle-down',
|
|
161
|
+
color: '#ef4444',
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
])
|
|
166
|
+
|
|
167
|
+
const [option] = useState<GanttChartOption>({
|
|
168
|
+
calendar: {
|
|
169
|
+
start: new Date('2024-01-01'),
|
|
170
|
+
end: new Date('2024-03-31'),
|
|
171
|
+
pxPerDay: 30,
|
|
172
|
+
showCurrentTime: true,
|
|
173
|
+
milestones: [
|
|
174
|
+
{
|
|
175
|
+
id: 'ms-1',
|
|
176
|
+
name: 'Release',
|
|
177
|
+
start: new Date('2024-02-01'),
|
|
178
|
+
color: '#8b5cf6',
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
bar: { height: 28 },
|
|
183
|
+
rowHeader: { width: 200 },
|
|
184
|
+
theme: 'system',
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
const chart = chartRef.current
|
|
189
|
+
if (!chart) return
|
|
190
|
+
|
|
191
|
+
// Set properties
|
|
192
|
+
chart.rows = rows
|
|
193
|
+
chart.option = option
|
|
194
|
+
|
|
195
|
+
// Set up event listeners
|
|
196
|
+
const handleTaskUpdate = (e: Event) => {
|
|
197
|
+
const detail = (e as CustomEvent<TaskUpdateEventDetail>).detail
|
|
198
|
+
console.log('Task updated:', detail)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
chart.addEventListener('task-update', handleTaskUpdate)
|
|
202
|
+
|
|
203
|
+
return () => {
|
|
204
|
+
chart.removeEventListener('task-update', handleTaskUpdate)
|
|
205
|
+
}
|
|
206
|
+
}, [rows, option])
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<div style={{ height: '500px' }}>
|
|
210
|
+
<gantt-chart ref={chartRef}></gantt-chart>
|
|
211
|
+
</div>
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Key Features
|
|
217
|
+
|
|
218
|
+
### Themes
|
|
219
|
+
|
|
220
|
+
Three theme modes are supported: light, dark, and system. Individual colors can be overridden using `customTheme`.
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
const option = {
|
|
224
|
+
theme: 'dark', // 'light' | 'dark' | 'system'
|
|
225
|
+
customTheme: {
|
|
226
|
+
bg: '#1a1a2e',
|
|
227
|
+
text: '#e0e0e0',
|
|
228
|
+
currentTimeLine: '#ff6b6b',
|
|
229
|
+
},
|
|
230
|
+
// ...
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Dependency Line Settings
|
|
235
|
+
|
|
236
|
+
Customize the dependency line display with the `dependency` option. Control arrow visibility and size.
|
|
237
|
+
Reverse-direction (right-to-left) dependencies are automatically rendered with S-curves, with horizontal connections at contact points.
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
const option = {
|
|
241
|
+
dependency: {
|
|
242
|
+
showArrows: true, // Show arrows (default: true)
|
|
243
|
+
arrowSize: 12, // Arrow size in px (default: 8)
|
|
244
|
+
},
|
|
245
|
+
// ...
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Internationalization (i18n)
|
|
250
|
+
|
|
251
|
+
moguchart-core provides built-in locale support. Japanese is the default locale for backward compatibility. Switch to English or create custom locales.
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
import { enLocale } from '@mogura/moguchart-core'
|
|
255
|
+
|
|
256
|
+
const option = {
|
|
257
|
+
locale: enLocale,
|
|
258
|
+
// ...
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
To create a custom locale, implement the `MoguchartLocale` interface:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import type { MoguchartLocale } from '@mogura/moguchart-core'
|
|
266
|
+
|
|
267
|
+
const frLocale: MoguchartLocale = {
|
|
268
|
+
monthFormat: 'MMM YYYY',
|
|
269
|
+
monthRowFormat: 'MMM',
|
|
270
|
+
dateFormat: (d) => `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`,
|
|
271
|
+
timeUnitDateFormat: (d) => `${d.getDate()} ${['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'][d.getMonth()]} ${d.getFullYear()}`,
|
|
272
|
+
dateTimeFormat: (d) => {
|
|
273
|
+
const date = `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`
|
|
274
|
+
const h = d.getHours()
|
|
275
|
+
const m = d.getMinutes()
|
|
276
|
+
if (h === 0 && m === 0) return date
|
|
277
|
+
return `${date} ${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`
|
|
278
|
+
},
|
|
279
|
+
yearMonthFormat: (d) => `${d.getFullYear()}/${d.getMonth() + 1}`,
|
|
280
|
+
duration: {
|
|
281
|
+
days: (n) => `${n} jour${n > 1 ? 's' : ''}`,
|
|
282
|
+
hours: (n) => `${n} heure${n > 1 ? 's' : ''}`,
|
|
283
|
+
minutes: (n) => `${n} minute${n > 1 ? 's' : ''}`,
|
|
284
|
+
zero: '0 minute',
|
|
285
|
+
},
|
|
286
|
+
tooltip: { duration: (d) => `Durée: ${d} jour${d > 1 ? 's' : ''}` },
|
|
287
|
+
dragOverlay: {
|
|
288
|
+
noTitle: 'Sans titre',
|
|
289
|
+
moveTo: (name) => `Déplacer vers: ${name}`,
|
|
290
|
+
movingTasks: (c) => `Déplacement de ${c} tâche${c > 1 ? 's' : ''}`,
|
|
291
|
+
},
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Milestones
|
|
296
|
+
|
|
297
|
+
Pass an array of milestones to `calendar.milestones` to display vertical lines and badges on the chart. Hover effects transition opacity on mouseover.
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
option.calendar.milestones = [
|
|
301
|
+
{
|
|
302
|
+
id: 'ms-1',
|
|
303
|
+
name: 'Alpha Release',
|
|
304
|
+
start: new Date('2025-04-08'),
|
|
305
|
+
color: '#8b5cf6',
|
|
306
|
+
width: 4,
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: 'ms-2',
|
|
310
|
+
name: 'Production Release',
|
|
311
|
+
start: new Date('2025-05-01'),
|
|
312
|
+
color: '#10b981',
|
|
313
|
+
},
|
|
314
|
+
]
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Markers
|
|
318
|
+
|
|
319
|
+
Pass an array of markers to each row's `markers` property to display triangle icons with labels on the timeline.
|
|
320
|
+
|
|
321
|
+
```javascript
|
|
322
|
+
const rows = [
|
|
323
|
+
{
|
|
324
|
+
id: 'row-1',
|
|
325
|
+
name: 'Task A',
|
|
326
|
+
tasks: [
|
|
327
|
+
/* ... */
|
|
328
|
+
],
|
|
329
|
+
markers: [
|
|
330
|
+
{
|
|
331
|
+
id: 'marker-1',
|
|
332
|
+
name: 'Review Deadline',
|
|
333
|
+
date: new Date('2025-04-10'),
|
|
334
|
+
anchor: 'end',
|
|
335
|
+
type: 'triangle-right',
|
|
336
|
+
color: '#ef4444',
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
},
|
|
340
|
+
]
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Task Bar Patterns
|
|
344
|
+
|
|
345
|
+
Apply 13 types of fill patterns to task bars. Preset constants are also available.
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
import { PATTERN_DIAGONAL_STRIPE } from '@mogura/moguchart-core'
|
|
349
|
+
|
|
350
|
+
const task = {
|
|
351
|
+
id: 't-1',
|
|
352
|
+
name: 'WIP',
|
|
353
|
+
start: new Date('2024-01-01'),
|
|
354
|
+
end: new Date('2024-01-05'),
|
|
355
|
+
style: 'background-color: #60a5fa',
|
|
356
|
+
pattern: PATTERN_DIAGONAL_STRIPE, // Use preset
|
|
357
|
+
// or specify directly:
|
|
358
|
+
// pattern: { type: 'checkerboard', color: '#ffffff80' }
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
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`
|
|
363
|
+
|
|
364
|
+
### Row Reordering
|
|
365
|
+
|
|
366
|
+
Set `enableRowReordering: true` to enable drag & drop row reordering.
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
const option = {
|
|
370
|
+
enableRowReordering: true,
|
|
371
|
+
// ...
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
chart.addEventListener('row-reordered', (e) => {
|
|
375
|
+
console.log('Reordered rows:', e.detail.rows)
|
|
376
|
+
})
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Multi-Task Selection & Batch Operations
|
|
380
|
+
|
|
381
|
+
Hold `Ctrl` (Mac: `Cmd`) and click task bars to select multiple tasks, then drag them together.
|
|
382
|
+
|
|
383
|
+
```javascript
|
|
384
|
+
chart.addEventListener('task-update', (e) => {
|
|
385
|
+
const detail = e.detail
|
|
386
|
+
if (!detail.isDragging && detail.selectedTaskIds?.length > 1) {
|
|
387
|
+
// Multi-selection drag drop: apply same dx to all selected tasks
|
|
388
|
+
for (const taskId of detail.selectedTaskIds) {
|
|
389
|
+
applyDxToTask(taskId, detail.dx)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
})
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Snap Feature
|
|
396
|
+
|
|
397
|
+
Control the snap interval when dragging tasks with `snapDuration` (in minutes). When using monthly view mode (`pxPerMonth`), snapping is automatically enforced at monthly boundaries.
|
|
398
|
+
|
|
399
|
+
```javascript
|
|
400
|
+
const option = {
|
|
401
|
+
snapDuration: 60, // Snap every hour (default: 1440 = 1 day)
|
|
402
|
+
// ...
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### View Modes
|
|
407
|
+
|
|
408
|
+
#### Week View Mode
|
|
409
|
+
|
|
410
|
+
Set `calendar.showWeeks: true` for a two-row calendar header with week numbers. This mode is enabled automatically when `pxPerDay` is less than 20.
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
const option = {
|
|
414
|
+
calendar: {
|
|
415
|
+
start: new Date('2025-01-01'),
|
|
416
|
+
end: new Date('2025-12-31'),
|
|
417
|
+
pxPerDay: 15,
|
|
418
|
+
showWeeks: true,
|
|
419
|
+
weekStartDay: 1, // 1 = Monday (default)
|
|
420
|
+
weekFormat: (weekNum) => `W${weekNum}`,
|
|
421
|
+
},
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
#### Monthly View Mode
|
|
426
|
+
|
|
427
|
+
Set `calendar.pxPerMonth` to render each month at a fixed equal width. Snapping is automatically enforced at monthly boundaries.
|
|
428
|
+
|
|
429
|
+
```javascript
|
|
430
|
+
const option = {
|
|
431
|
+
calendar: {
|
|
432
|
+
start: new Date('2025-01-01'),
|
|
433
|
+
end: new Date('2027-12-31'),
|
|
434
|
+
pxPerDay: 1,
|
|
435
|
+
pxPerMonth: 120, // 120px per month
|
|
436
|
+
showMonthsRow: true, // Two-row header: top=year, bottom=month
|
|
437
|
+
},
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Public Methods
|
|
442
|
+
|
|
443
|
+
#### selectTask
|
|
444
|
+
|
|
445
|
+
Selects the task with the specified ID and auto-scrolls if it's off-screen.
|
|
446
|
+
|
|
447
|
+
```javascript
|
|
448
|
+
const chart = document.querySelector('gantt-chart')
|
|
449
|
+
const found = chart.selectTask('task-1')
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### hitTest
|
|
453
|
+
|
|
454
|
+
Returns the corresponding row ID and date from client coordinates (pixel position on screen).
|
|
455
|
+
|
|
456
|
+
```javascript
|
|
457
|
+
document.addEventListener('mousemove', (e) => {
|
|
458
|
+
const result = chart.hitTest(e.clientX, e.clientY)
|
|
459
|
+
if (result) {
|
|
460
|
+
console.log(`Row: ${result.rowId}, Date: ${result.date}`)
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Keyboard Operations
|
|
466
|
+
|
|
467
|
+
When the Gantt chart has focus, you can navigate, select, move, and delete tasks using the keyboard.
|
|
468
|
+
|
|
469
|
+
| Key | Action |
|
|
470
|
+
| :--- | :--- |
|
|
471
|
+
| `←` `→` | Move focus between tasks |
|
|
472
|
+
| `↑` `↓` | Move focus to another row |
|
|
473
|
+
| `Enter` / `Space` | Select the focused task |
|
|
474
|
+
| `Ctrl/Cmd + Enter` | Toggle selection (multi-select) |
|
|
475
|
+
| `Shift + ←` `→` | Move selected tasks |
|
|
476
|
+
| `Delete` / `Backspace` | Fire `task-delete` event |
|
|
477
|
+
| `Escape` | Clear selection and focus |
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
const option = {
|
|
481
|
+
keyboard: {
|
|
482
|
+
enabled: true, // Default: true
|
|
483
|
+
moveStep: 60, // Move amount per Shift+Arrow key press (minutes)
|
|
484
|
+
},
|
|
485
|
+
// ...
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## License
|
|
490
|
+
|
|
491
|
+
MIT
|