apexgantt 3.10.2 → 3.10.3

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.
@@ -7,17 +7,80 @@ on:
7
7
 
8
8
  permissions:
9
9
  id-token: write
10
- contents: read
10
+ contents: write
11
11
 
12
12
  jobs:
13
13
  publish:
14
14
  runs-on: ubuntu-latest
15
+ if: startsWith(github.event.head_commit.message, 'release:')
16
+
15
17
  steps:
16
18
  - uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0
21
+
22
+ - name: Check commit message and extract version
23
+ id: check
24
+ run: |
25
+ MSG="${{ github.event.head_commit.message }}"
26
+ if echo "$MSG" | grep -qE '^release: [0-9]+\.[0-9]+\.[0-9]+'; then
27
+ VERSION=$(echo "$MSG" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+[^ ]*' | head -1)
28
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
29
+ if echo "$VERSION" | grep -qE '[-]'; then
30
+ echo "tag=next" >> $GITHUB_OUTPUT
31
+ else
32
+ echo "tag=latest" >> $GITHUB_OUTPUT
33
+ fi
34
+ else
35
+ echo "❌ Commit message must match 'release: X.Y.Z'"
36
+ exit 1
37
+ fi
38
+
39
+ - name: Verify package.json version matches commit message
40
+ run: |
41
+ PKG_VERSION=$(node -p "require('./package.json').version")
42
+ MSG_VERSION="${{ steps.check.outputs.version }}"
43
+ if [ "$PKG_VERSION" != "$MSG_VERSION" ]; then
44
+ echo "❌ package.json version ($PKG_VERSION) does not match commit message version ($MSG_VERSION)"
45
+ exit 1
46
+ fi
47
+ echo "✅ Version $PKG_VERSION confirmed"
48
+
17
49
  - uses: actions/setup-node@v4
18
50
  with:
19
51
  node-version: "20"
20
52
 
21
53
  - run: npm install -g npm@latest
22
54
  - run: npm install
23
- - run: npm publish --provenance
55
+
56
+ - name: Publish to npm
57
+ run: npm publish --provenance --tag ${{ steps.check.outputs.tag }}
58
+
59
+ - name: Create git tag
60
+ run: |
61
+ TAG="v${{ steps.check.outputs.version }}"
62
+ git config user.name "github-actions[bot]"
63
+ git config user.email "github-actions[bot]@users.noreply.github.com"
64
+ if git rev-parse "$TAG" >/dev/null 2>&1; then
65
+ echo "Tag $TAG already exists, skipping"
66
+ else
67
+ git tag -a "$TAG" -m "Release $TAG"
68
+ git push origin "$TAG"
69
+ fi
70
+
71
+ - name: Create GitHub Release
72
+ env:
73
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
74
+ run: |
75
+ TAG="v${{ steps.check.outputs.version }}"
76
+ PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
77
+ if [ -n "$PREV_TAG" ]; then
78
+ NOTES=$(git log "$PREV_TAG..HEAD" --pretty=format:"- %s" --no-merges)
79
+ else
80
+ NOTES=$(git log --pretty=format:"- %s" --no-merges)
81
+ fi
82
+ if gh release view "$TAG" >/dev/null 2>&1; then
83
+ echo "Release $TAG already exists, skipping"
84
+ else
85
+ gh release create "$TAG" --notes "$NOTES" --title "$TAG"
86
+ fi
package/README.md CHANGED
@@ -93,13 +93,12 @@ The layout can be configured by passing a second argument to `ApexGantt` with th
93
93
  | `enableTaskEdit` | `boolean` | `false` | Show the inline task-edit form when a task row is clicked. |
94
94
  | `enableTaskResize` | `boolean` | `true` | Allow task bars to be resized by dragging their handles. |
95
95
  | `enableTooltip` | `boolean` | `true` | Show a tooltip on task-bar hover. |
96
+ | `enableSelection` | `boolean` | `false` | Enable row selection (click, Ctrl+Click, Shift+Click, keyboard). |
97
+ | `showCheckboxColumn` | `boolean` | `true` | Show a checkbox column for multi-select. Only applies when `enableSelection` is true. |
96
98
  | `enableCriticalPath` | `boolean` | `false` | Calculate and highlight the critical path through dependent tasks. |
97
99
  | `criticalBarColor` | `string` | `'#e53935'` | Fill color for task bars on the critical path. |
98
100
  | `criticalArrowColor` | `string` | `'#e53935'` | Stroke color for dependency arrows on the critical path. |
99
101
  | `baseline` | `Partial<BaselineOptions>` | `undefined` | When `enabled: true`, renders a thin baseline bar below each task bar. |
100
- | `enableSelection` | `boolean` | `false` | Enable row selection (click, Ctrl+Click, Shift+Click, keyboard). |
101
- | `showCheckboxColumn` | `boolean` | `true` | Show a checkbox column for multi-select. Only applies when `enableSelection` is `true`. |
102
- | `toolbarItems` | `ToolbarItem[]` | `[]` | Custom controls rendered in the toolbar alongside the built-in zoom and export buttons. See [Custom Toolbar](#custom-toolbar). |
103
102
  | `tooltipId` | `string` | `'apexgantt-tooltip-container'` | HTML `id` for the tooltip container element. |
104
103
  | `tooltipTemplate` | `(task, dateFormat) => string` | built-in | Custom function returning an HTML string for the task tooltip. |
105
104
  | `tooltipBorderColor` | `string` | `'#BCBCBC'` | Border color of the tooltip. |
@@ -115,6 +114,7 @@ The layout can be configured by passing a second argument to `ApexGantt` with th
115
114
  | `annotationOrientation` | `Orientation` | `Orientation.Horizontal` | Whether annotation lines are drawn horizontally or vertically. |
116
115
  | `annotations` | `Annotation[]` | `[]` | Array of annotation objects to overlay on the timeline. |
117
116
  | `parsing` | `ParsingConfig` | `undefined` | Field-mapping config to parse non-standard task shapes. See Data Parsing below. |
117
+ | `toolbarItems` | `ToolbarItem[]` | `[]` | Custom controls rendered in the toolbar alongside the built-in zoom and export buttons. Each item can be a `ToolbarButton`, `ToolbarSelect`, or `ToolbarSeparator`. |
118
118
  | `taskListAriaLabel` | `string` | `'Task list'` | `aria-label` for the task-list table, used by screen readers. |
119
119
 
120
120
  Default tooltip template
@@ -176,43 +176,21 @@ tooltipTemplate(task, dateFormat) {
176
176
 
177
177
  ### Expected data format to set as Options.series
178
178
 
179
- Each task should be in the following format:
179
+ Each tasks should be in below format
180
180
 
181
181
  ```js
182
182
  [
183
183
  {
184
- id: 'a', // unique id of the task
185
- startTime: '10-11-2024', // start time of the task
186
- endTime: '11-01-2024', // end time of the task
187
- name: 'task 1', // task name
188
- parentId: 'a', // parent task id
189
- progress: 65, // progress in percentage (0–100)
190
- type: 'task', // 'task' (default) or 'milestone'
191
- dependency: 'other-id', // simple string (Finish-to-Start) or typed object (see below)
192
- barBackgroundColor: '#537CFA', // override bar color for this task
193
- rowBackgroundColor: '#FFFFFF', // override row background for this task
194
- collapsed: false, // whether child tasks are collapsed
195
- baseline: { // optional planned dates (requires baseline.enabled: true)
196
- start: '10-10-2024',
197
- end: '10-30-2024',
198
- },
184
+ id: 'a', // unique id of the task
185
+ startTime: '10-11-2024', // start time of the task
186
+ endTime: '11-01-2024', // end time of the task
187
+ name: 'task 1', // task name
188
+ parentId: 'a', // parent task id
189
+ progress: 65, // progress in percentage
199
190
  },
200
191
  ];
201
192
  ```
202
193
 
203
- ### Typed dependency
204
-
205
- The `dependency` field accepts either a plain task ID string (treated as Finish-to-Start with 0 lag) or a typed object for full control:
206
-
207
- ```js
208
- {
209
- id: 'task-2',
210
- dependency: { taskId: 'task-1', type: 'FS', lag: 2 }, // start 2 days after task-1 finishes
211
- }
212
- ```
213
-
214
- Supported dependency types: `'FS'` (Finish-to-Start, default), `'FF'` (Finish-to-Finish), `'SF'` (Start-to-Finish), `'SS'` (Start-to-Start). `lag` is in days; negative values create lead (overlap).
215
-
216
194
  ### Expected annotation format to set as Options.annotations
217
195
 
218
196
  Each tasks should be in below format
@@ -395,45 +373,6 @@ const gantt = new ApexGantt(document.getElementById('gantt'), {
395
373
 
396
374
  **Supported fields:** `id`, `name`, `startTime`, `endTime`, `progress`, `type`, `parentId`, `dependency`, `barBackgroundColor`, `rowBackgroundColor`, `collapsed`
397
375
 
398
- ## Theming
399
-
400
- ApexGantt ships with built-in light and dark themes. Use the `theme` option to select a preset, or supply a full `GanttTheme` object for complete control.
401
-
402
- ```js
403
- import ApexGantt, {LightTheme, DarkTheme, getTheme} from 'apexgantt';
404
-
405
- // Built-in presets via string shorthand
406
- const gantt = new ApexGantt(element, {series: tasks, theme: 'dark'});
407
-
408
- // Programmatic preset access
409
- const dark = getTheme('dark');
410
-
411
- // Override individual colors based on a preset
412
- const gantt = new ApexGantt(element, {
413
- series: tasks,
414
- theme: {...DarkTheme, barBackgroundColor: '#7C3AED'},
415
- });
416
- ```
417
-
418
- ## Enums and Constants
419
-
420
- ```js
421
- import {ViewMode, TaskType, ColumnKey, Orientation} from 'apexgantt';
422
-
423
- // ViewMode — timeline granularity
424
- ViewMode.Day | ViewMode.Week | ViewMode.Month | ViewMode.Quarter | ViewMode.Year
425
-
426
- // TaskType — how a task is rendered
427
- TaskType.Task // horizontal bar
428
- TaskType.Milestone // diamond marker
429
-
430
- // ColumnKey — built-in task-list columns
431
- ColumnKey.Name | ColumnKey.StartTime | ColumnKey.EndTime | ColumnKey.Duration | ColumnKey.Progress
432
-
433
- // Orientation — annotation line direction
434
- Orientation.Horizontal | Orientation.Vertical
435
- ```
436
-
437
376
  ## 📘 Public API
438
377
 
439
378
  ### 1. `update(options)`
@@ -488,17 +427,17 @@ ganttInstance.updateTask('task-1', {
488
427
 
489
428
  ### 3. `zoomIn()`
490
429
 
491
- Zooms in the gantt based on current view mode. View mode direction for zoom in: year -> quarter -> month -> week -> day
430
+ Zooms in the gantt based on current view mode. View mode direction for zoom in year -> quarter -> month -> week -> day
492
431
 
493
432
  #### Example
494
433
 
495
434
  ```js
496
- ganttInstance.zoomIn();
435
+ ganttInstance.zoomOut();
497
436
  ```
498
437
 
499
438
  ### 4. `zoomOut()`
500
439
 
501
- Zooms out the gantt based on current view mode. View mode direction for zoom out: day -> week -> month -> quarter -> year
440
+ Zooms out the gantt based on current view mode. View mode direction for zoom in day -> week -> month -> quarter -> year
502
441
 
503
442
  #### Example
504
443
 
@@ -506,143 +445,6 @@ Zooms out the gantt based on current view mode. View mode direction for zoom out
506
445
  ganttInstance.zoomOut();
507
446
  ```
508
447
 
509
- ### 5. `getSelectedTasks()`
510
-
511
- Returns an array of currently selected `Task` objects. Requires `enableSelection: true`.
512
-
513
- ```js
514
- const selected = ganttInstance.getSelectedTasks();
515
- console.log(selected.map((t) => t.id));
516
- ```
517
-
518
- ### 6. `setSelectedTasks(ids)`
519
-
520
- Programmatically set the selection to the given task IDs. Requires `enableSelection: true`.
521
-
522
- ```js
523
- ganttInstance.setSelectedTasks(['task-1', 'task-3']);
524
- ```
525
-
526
- ### 7. `clearSelection()`
527
-
528
- Clear all selected tasks. Requires `enableSelection: true`.
529
-
530
- ```js
531
- ganttInstance.clearSelection();
532
- ```
533
-
534
- ### 8. `renderToolbar(container)`
535
-
536
- Render the built-in toolbar into a custom DOM element. Normally called automatically by `render()`. Use this only when you need to mount the toolbar in a custom slot outside the chart.
537
-
538
- ```js
539
- const toolbarEl = document.getElementById('my-toolbar');
540
- ganttInstance.renderToolbar(toolbarEl);
541
- ```
542
-
543
- ### 9. `isDestroyed()`
544
-
545
- Returns `true` after `destroy()` has been called, `false` while the chart is live. Use this guard before calling other methods when you are unsure whether the instance is still active.
546
-
547
- ```js
548
- if (!ganttInstance.isDestroyed()) {
549
- ganttInstance.update({series: newTasks});
550
- }
551
- ```
552
-
553
- ### 10. `destroy()`
554
-
555
- Destroy the chart instance and free all associated resources. Removes all event listeners, disconnects `ResizeObserver`s, clears the tooltip, and clears the DOM. After calling `destroy()` the instance cannot be reused — create a new `ApexGantt` instead.
556
-
557
- Always call `destroy()` before removing the host element from the DOM or when cleaning up in frameworks.
558
-
559
- ```js
560
- // React cleanup example
561
- useEffect(() => {
562
- const gantt = new ApexGantt(ref.current, options);
563
- gantt.render();
564
- return () => gantt.destroy();
565
- }, []);
566
- ```
567
-
568
- ## Custom Toolbar
569
-
570
- Add custom buttons, dropdowns, and separators to the toolbar alongside the built-in zoom and export controls. Pass an array of `ToolbarItem` objects to the `toolbarItems` option.
571
-
572
- ### Toolbar Button
573
-
574
- ```js
575
- import ApexGantt, {GanttEvents} from 'apexgantt';
576
-
577
- const gantt = new ApexGantt(element, {
578
- series: tasks,
579
- enableSelection: true,
580
- toolbarItems: [
581
- {
582
- type: 'button',
583
- label: 'Export Selected',
584
- tooltip: 'Export selected tasks to CSV',
585
- position: 'right', // 'left' inserts before built-in controls
586
- requiresSelection: true, // auto-disabled when nothing is selected
587
- showCount: true, // label becomes "Export Selected (3)"
588
- onClick: ({selectedTasks}) => exportToCsv(selectedTasks),
589
- },
590
- ],
591
- });
592
- ```
593
-
594
- ### Toolbar Select
595
-
596
- ```js
597
- toolbarItems: [
598
- {
599
- type: 'select',
600
- label: 'Filter',
601
- placeholder: 'All types…',
602
- position: 'left',
603
- options: [
604
- {value: 'task', text: 'Tasks'},
605
- {value: 'milestone', text: 'Milestones'},
606
- ],
607
- onChange: (value, {selectedTasks}) => console.log(value, selectedTasks),
608
- },
609
- ],
610
- ```
611
-
612
- ### Toolbar Separator
613
-
614
- ```js
615
- toolbarItems: [
616
- {type: 'separator', position: 'right'},
617
- {type: 'button', label: 'Save', onClick: () => save()},
618
- ],
619
- ```
620
-
621
- ### ToolbarButton properties
622
-
623
- | Property | Type | Default | Description |
624
- | --- | --- | --- | --- |
625
- | `type` | `'button'` | — | Required discriminator. |
626
- | `label` | `string` | — | Text label inside the button. |
627
- | `icon` | `string` | — | SVG string rendered as the button icon. |
628
- | `tooltip` | `string` | — | Tooltip shown on hover. |
629
- | `position` | `'left' \| 'right'` | `'right'` | Where to insert relative to built-in controls. |
630
- | `disabled` | `boolean \| (context) => boolean` | — | Static flag or function evaluated on every selection change. |
631
- | `requiresSelection` | `boolean` | `false` | Auto-disabled when no tasks are selected. |
632
- | `showCount` | `boolean` | `false` | Appends the selection count to the label, e.g. `"Export (3)"`. |
633
- | `onClick` | `(context) => void` | — | Called when the button is clicked. |
634
-
635
- ### ToolbarSelect properties
636
-
637
- | Property | Type | Default | Description |
638
- | --- | --- | --- | --- |
639
- | `type` | `'select'` | — | Required discriminator. |
640
- | `label` | `string` | — | Optional label rendered before the `<select>`. |
641
- | `placeholder` | `string` | — | Placeholder option shown when no value is chosen. |
642
- | `position` | `'left' \| 'right'` | `'right'` | Where to insert relative to built-in controls. |
643
- | `options` | `{value, text}[]` | — | Options shown in the dropdown. |
644
- | `onChange` | `(value, context) => void` | — | Called when the selected value changes. |
645
-
646
448
  ## Events
647
449
 
648
450
  ApexGantt emits CustomEvents on the container element for various user interactions, allowing you to track and respond to changes in real-time.
@@ -651,14 +453,12 @@ ApexGantt emits CustomEvents on the container element for various user interacti
651
453
 
652
454
  | Event | When | Detail |
653
455
  | --- | --- | --- |
654
- | `taskUpdate` | Task is being updated (before completion) | `{ taskId, updates, updatedTask, timestamp }` |
456
+ | `taskUpdate` | Task is being updated | `{ taskId, updates, updatedTask, timestamp }` |
655
457
  | `taskUpdateSuccess` | Update completed successfully | `{ taskId, updatedTask, timestamp }` |
656
458
  | `taskValidationError` | Form validation failed | `{ taskId, errors, timestamp }` |
657
459
  | `taskUpdateError` | Update failed | `{ taskId, error, timestamp }` |
658
- | `taskDragged` | Task bar is dragged to a new position | `{ taskId, oldStartTime, oldEndTime, newStartTime, newEndTime, daysMoved, affectedChildTasks, timestamp }` |
659
- | `taskResized` | Task bar is resized via its handles | `{ taskId, resizeHandle, oldStartTime, oldEndTime, newStartTime, newEndTime, durationChange, timestamp }` |
660
- | `selectionChange` | Selected task rows change | `{ selectedTasks, selectedIds, timestamp }` |
661
- | `dependencyArrowUpdate` | Dependency arrow created, updated, or removed | `{ fromId, toId, type, lag, chartInstanceId, arrowLinkInstanceId }` |
460
+ | `taskDragged` | Task bar is dragged | `{ taskId, oldStartTime, oldEndTime, newStartTime, newEndTime, daysMoved, affectedChildTasks, timestamp }` |
461
+ | `taskResized` | Task bar is resized | `{ taskId, resizeHandle, oldStartTime, oldEndTime, newStartTime, newEndTime, durationChange, timestamp }` |
662
462
 
663
463
  ### Events Usage
664
464
 
@@ -712,29 +512,3 @@ function GanttChart({tasks}) {
712
512
  return <div ref={containerRef} />;
713
513
  }
714
514
  ```
715
-
716
- #### TypeScript — typed events with `GanttEventMap`
717
-
718
- Use the `GanttEventMap` interface for fully-typed `CustomEvent.detail` access:
719
-
720
- ```typescript
721
- import ApexGantt, {GanttEventMap} from 'apexgantt';
722
-
723
- const container = document.getElementById('gantt') as HTMLElement;
724
- const chart = new ApexGantt(container, {series: tasks, enableSelection: true});
725
- chart.render();
726
-
727
- container.addEventListener('taskDragged', (e: GanttEventMap['taskDragged']) => {
728
- console.log(e.detail.taskId, e.detail.daysMoved);
729
- });
730
-
731
- container.addEventListener('selectionChange', (e: GanttEventMap['selectionChange']) => {
732
- console.log('selected IDs:', e.detail.selectedIds);
733
- });
734
-
735
- container.addEventListener('dependencyArrowUpdate', (e: GanttEventMap['dependencyArrowUpdate']) => {
736
- const {fromId, toId, type, lag} = e.detail;
737
- console.log(`${fromId} → ${toId} (${type}, lag: ${lag ?? 0})`);
738
- });
739
- ```
740
-