diff --git a/CHANGELOG.md b/CHANGELOG.md
index 978e24b..72c1293 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.7.0] - 2026-01-10
+
+### Added
+- TaskList和TaskBar声明式定义ContextMenu方式, 使用组件TaskListContextMenu和TaskBarContextMenu
+- TaskListContextMenu和TaskBarContextMenu的default Slots
+- TaskListContextMenu和TaskBarContextMenu是否展示属性 - enable-task-list-context-menu和enable-task-bar-context-menu
+- Declarative definition ContextMenu method for TaskList and TaskBar using the TaskListContextMenu and TaskBarContextMenu components
+- default Slots for TaskListContextMenu and TaskBarContextMenu
+- Properties to control the display of TaskListContextMenu and TaskBarContextMenu - enable-task-list-context-menu and enable-task-bar-context-menu
+
+### Enhancement
+- 拆分TaskList子组件代码,更易读、易维护
+- Split TaskList sub-component code for better readability and maintainability
+
## [1.6.2] - 2025-12-23
### Fixed
diff --git a/README-EN.md b/README-EN.md
index 8cded0a..47660c7 100644
--- a/README-EN.md
+++ b/README-EN.md
@@ -197,6 +197,8 @@ npm run dev
| `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date |
| `allowDragAndResize` | `boolean` | `true` | Whether to allow dragging and resizing tasks/milestones |
| `enableTaskRowMove` | `boolean` | `false` | Whether to allow dragging and dropping TaskRow |
+| `enableTaskListContextMenu` | `boolean` | `true` | Whether to enable TaskList (TaskRow) context menu. When `true`: uses built-in menu if `task-list-context-menu` slot is not declared, uses custom menu if slot is declared; when `false`: context menu is completely disabled |
+| `enableTaskBarContextMenu` | `boolean` | `true` | Whether to enable TaskBar context menu. When `true`: uses built-in menu if `task-bar-context-menu` slot is not declared, uses custom menu if slot is declared; when `false`: context menu is completely disabled |
| `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | Assignee dropdown options in task edit drawer |
#### TaskListColumn Component Props
@@ -232,6 +234,110 @@ The `TaskListColumn` component is used to define task list columns in declarativ
> - Column display order is determined by the declaration order of `TaskListColumn` components
> - For detailed column content customization and slot usage, see [Slots](#slots) section
+#### TaskListContextMenu Component Props
+
+The `TaskListContextMenu` component is used to declaratively define the context menu for TaskList (TaskRow). Takes effect when `enableTaskListContextMenu` is `true`.
+
+| Prop | Type | Default | Description |
+| ---------- | ---------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `taskType` | `string \| string[]` | `undefined` | Specifies which task types should display this context menu. When not set, follows existing logic (all tasks show menu). When set, only specified types show menu. Supports single type (e.g., `'task'`) or multiple types (e.g., `['task', 'milestone']`) |
+
+**Usage Examples**:
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+> **💡 Tips**:
+> - The `TaskListContextMenu` component itself does not render any content, it only declares menu configuration
+> - Must be used inside the `GanttChart` component with `enable-task-list-context-menu="true"` set
+> - Menu positioning and visibility are automatically managed internally, users only need to focus on menu content HTML structure
+> - Menu automatically closes when clicking outside or scrolling
+> - For detailed slot usage, see [Slots](#slots) section
+
+#### TaskBarContextMenu Component Props
+
+The `TaskBarContextMenu` component is used to declaratively define the context menu for TaskBar (timeline task bars). Takes effect when `enableTaskBarContextMenu` is `true`.
+
+| Prop | Type | Default | Description |
+| ---------- | ---------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `taskType` | `string \| string[]` | `undefined` | Specifies which task types should display this context menu. When not set, follows existing logic (all tasks show menu). When set, only specified types show menu. Supports single type (e.g., `'task'`) or multiple types (e.g., `['task', 'milestone']`) |
+
+**Usage Examples**:
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+> **💡 Tips**:
+> - The `TaskBarContextMenu` component itself does not render any content, it only declares menu configuration
+> - Must be used inside the `GanttChart` component with `enable-task-bar-context-menu="true"` set
+> - Menu positioning and visibility are automatically managed internally, users only need to focus on menu content HTML structure
+> - Menu automatically closes when clicking outside or scrolling
+> - For detailed slot usage, see [Slots](#slots) section
+
#### Configuration Object Props
For complete configuration object documentation, see [⚙️ Configuration & Customization](#⚙️-configuration--customization) section.
@@ -2391,6 +2497,208 @@ const props = defineProps()
> - TaskRow and TaskBar have different available space, need to adapt layout
> - Avoid using overly complex components in slot content, may affect performance
+##### TaskListContextMenu Slots
+
+Used to customize the context menu content for TaskRow (task list row).
+
+**Menu Display Logic:**
+- When `enableTaskListContextMenu=true` and TaskListContextMenu component is **not declared** → Uses **built-in** context menu
+- When `enableTaskListContextMenu=true` and TaskListContextMenu component is **declared** → Uses **custom** context menu
+- When `enableTaskListContextMenu=false` → Context menu is **completely disabled** (regardless of component declaration)
+
+**Slot List:**
+
+| Slot Name | Parameters | Description |
+| --------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- |
+| `default` | `scope: { row: Task, $index: number }` | Custom Task List Context Menu content. Access current task object via `scope.row`, access task index via `scope.$index`. |
+
+**Usage Example:**
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+##### TaskBarContextMenu Slots
+
+Used to customize the context menu content for TaskBar (timeline task bar).
+
+**Menu Display Logic:**
+- When `enableTaskBarContextMenu=true` and TaskBarContextMenu component is **not declared** → Uses **built-in** context menu
+- When `enableTaskBarContextMenu=true` and TaskBarContextMenu component is **declared** → Uses **custom** context menu
+- When `enableTaskBarContextMenu=false` → Context menu is **completely disabled** (regardless of component declaration)
+
+**Slot List:**
+
+| Slot Name | Parameters | Description |
+| --------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- |
+| `default` | `scope: { row: Task, $index: number }` | Custom Task Bar Context Menu content. Access current task object via `scope.row`, access task index via `scope.$index`. |
+
+**Usage Example:**
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+> **💡 Usage Scenarios**:
+>
+> - Customize context menu styles and layouts
+> - Add business-specific operations
+> - Dynamically show menu items based on task status
+> - Add permission control logic
+> - Integrate third-party UI component library menus
+
+> **⚠️ Notes**:
+>
+> - When `enableTaskListContextMenu=false` or `enableTaskBarContextMenu=false`, the menu will not be displayed even if the component is declared
+> - Context menus will automatically close when scrolling or clicking outside the menu
+> - Recommended to use `` to render the menu under body to avoid positioning and z-index issues
+> - Remember to call `onClose()` after menu item clicks to close the menu
+> - TaskRow and TaskBar context menus are independent and can be customized separately
+> - By default, the system provides a built-in context menu with common operations
+> - Declarative components do not render any content, only used for passing configuration
+
##### TaskListColumn Slots
The `TaskListColumn` component provides two slots for customizing task list column headers and cell content. Must be used in declarative mode (`taskListColumnRenderMode="declarative"`).
diff --git a/README.md b/README.md
index eb9096b..d2c1204 100644
--- a/README.md
+++ b/README.md
@@ -195,6 +195,8 @@ npm run dev
| `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
| `allowDragAndResize` | `boolean` | `true` | 是否允许拖拽和调整任务/里程碑大小 |
| `enableTaskRowMove` | `boolean` | `false` | 是否允许拖拽和摆放TaskRow |
+| `enableTaskListContextMenu` | `boolean` | `true` | 是否启用 TaskList(TaskRow)右键菜单功能。为 `true` 时:未声明 `task-list-context-menu` 插槽则使用内置菜单,声明了插槽则使用自定义菜单;为 `false` 时右键菜单完全禁用 |
+| `enableTaskBarContextMenu` | `boolean` | `true` | 是否启用 TaskBar 右键菜单功能。为 `true` 时:未声明 `task-bar-context-menu` 插槽则使用内置菜单,声明了插槽则使用自定义菜单;为 `false` 时右键菜单完全禁用 |
| `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | 任务编辑抽屉中负责人下拉菜单的选项列表 |
#### TaskListColumn 属性
@@ -230,6 +232,110 @@ npm run dev
> - 列的显示顺序由 `TaskListColumn` 组件的声明顺序决定
> - 关于列内容自定义和插槽的详细使用方法,请参考 [插槽 (Slots)](#插槽-slots) 章节
+#### TaskListContextMenu 属性
+
+`TaskListContextMenu` 组件用于声明式定义 TaskList(TaskRow)的右键菜单。当 `enableTaskListContextMenu` 为 `true` 时生效。
+
+| 属性名 | 类型 | 默认值 | 说明 |
+| ---------- | ---------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------- |
+| `taskType` | `string \| string[]` | `undefined` | 指定哪些任务类型显示此右键菜单。不设置时遵循现有逻辑(所有任务都显示),设置后仅对指定类型任务显示。支持单个类型(如 `'task'`)或多个类型(如 `['task', 'milestone']`) |
+
+**使用示例**:
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+> **💡 提示**:
+> - `TaskListContextMenu` 组件本身不渲染任何内容,仅用于声明菜单配置
+> - 必须在 `GanttChart` 组件内部使用,且设置 `enable-task-list-context-menu="true"`
+> - 菜单定位和显示状态由内部自动管理,用户只需关心菜单内容的 HTML 结构
+> - 菜单会在点击外部或滚动时自动关闭
+> - 关于插槽的详细使用方法,请参考 [插槽 (Slots)](#插槽-slots) 章节
+
+#### TaskBarContextMenu 属性
+
+`TaskBarContextMenu` 组件用于声明式定义 TaskBar(时间线任务条)的右键菜单。当 `enableTaskBarContextMenu` 为 `true` 时生效。
+
+| 属性名 | 类型 | 默认值 | 说明 |
+| ---------- | ---------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------- |
+| `taskType` | `string \| string[]` | `undefined` | 指定哪些任务类型显示此右键菜单。不设置时遵循现有逻辑(所有任务都显示),设置后仅对指定类型任务显示。支持单个类型(如 `'task'`)或多个类型(如 `['task', 'milestone']`) |
+
+**使用示例**:
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+> **💡 提示**:
+> - `TaskBarContextMenu` 组件本身不渲染任何内容,仅用于声明菜单配置
+> - 必须在 `GanttChart` 组件内部使用,且设置 `enable-task-bar-context-menu="true"`
+> - 菜单定位和显示状态由内部自动管理,用户只需关心菜单内容的 HTML 结构
+> - 菜单会在点击外部或滚动时自动关闭
+> - 关于插槽的详细使用方法,请参考 [插槽 (Slots)](#插槽-slots) 章节
+
#### 配置对象属性
完整的配置对象说明请参考 [⚙️ 配置与扩展](#⚙️-配置与扩展) 章节。
@@ -2382,6 +2488,208 @@ const props = defineProps()
> - TaskRow 和 TaskBar 的可用空间不同,需要适配布局
> - 避免在插槽内容中使用过于复杂的组件,可能影响性能
+##### TaskListContextMenu 插槽
+
+用于自定义 TaskRow(任务列表行)的右键菜单内容。
+
+**菜单显示逻辑:**
+- 当 `enableTaskListContextMenu=true` 且**未声明** TaskListContextMenu 组件时 → 使用**系统内置**的右键菜单
+- 当 `enableTaskListContextMenu=true` 且**声明了** TaskListContextMenu 组件时 → 使用**自定义**的右键菜单
+- 当 `enableTaskListContextMenu=false` 时 → 右键菜单**完全禁用**(无论是否声明组件)
+
+**插槽列表:**
+
+| 插槽名 | 参数 | 说明 |
+| --------- | --------------------------------- | ---------------------------------------------------------------------------------------------- |
+| `default` | `scope: { row: Task, $index: number }` | 自定义TaskRow的右键菜单。通过 `scope.row` 访问当前任务对象,通过 `scope.$index` 访问任务索引。 |
+
+**使用示例:**
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+##### TaskBarContextMenu 插槽
+
+用于自定义 TaskBar(时间轴任务条)的右键菜单内容。
+
+**菜单显示逻辑:**
+- 当 `enableTaskBarContextMenu=true` 且**未声明** TaskBarContextMenu 组件时 → 使用**系统内置**的右键菜单
+- 当 `enableTaskBarContextMenu=true` 且**声明了** TaskBarContextMenu 组件时 → 使用**自定义**的右键菜单
+- 当 `enableTaskBarContextMenu=false` 时 → 右键菜单**完全禁用**(无论是否声明组件)
+
+**插槽列表:**
+
+| 插槽名 | 参数 | 说明 |
+| --------- | --------------------------------- | ---------------------------------------------------------------------------------------------- |
+| `default` | `scope: { row: Task, $index: number }` | 自定义TaskBar的右键菜单。通过 `scope.row` 访问当前任务对象,通过 `scope.$index` 访问任务索引。 |
+
+**使用示例:**
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+> **💡 使用场景**:
+>
+> - 自定义右键菜单样式和布局
+> - 添加业务特定的操作项
+> - 根据任务状态动态显示菜单项
+> - 添加权限控制逻辑
+> - 集成第三方 UI 组件库的菜单组件
+
+> **⚠️ 注意事项**:
+>
+> - 当 `enableTaskListContextMenu=false` 或 `enableTaskBarContextMenu=false` 时,即使声明了组件也不会显示菜单
+> - 右键菜单会在滚动或点击菜单外部时自动关闭
+> - 推荐使用 `` 将菜单渲染到 body 下,避免定位和层级问题
+> - 记得在菜单项点击后调用 `onClose()` 关闭菜单
+> - TaskRow 和 TaskBar 的右键菜单是独立的,可以分别自定义
+> - 默认情况下,系统会提供内置的右键菜单,包含常用操作
+> - 声明式组件不会渲染任何内容,仅用于传递配置
+
##### TaskListColumn 插槽
`TaskListColumn` 组件提供了两个插槽,用于自定义任务列表的列头和单元格内容。必须在声明式模式(`taskListColumnRenderMode="declarative"`)下使用。
diff --git a/demo/App.vue b/demo/App.vue
index 18148c7..e9385d2 100644
--- a/demo/App.vue
+++ b/demo/App.vue
@@ -735,9 +735,9 @@ const handleTaskRowMoved = async (payload: {
}
// 自定义右键菜单操作处理
-const handleCustomMenuAction = (action: string, task: Task, onClose: () => void) => {
+const handleCustomMenuAction = (action: string, task: Task) => {
showMessage(`自定义操作: ${action} - 任务: ${task.name}`, 'info', { closable: true })
- onClose()
+ // 菜单会自动关闭(通过点击外部或滚动)
}
@@ -1239,7 +1239,6 @@ const handleCustomMenuAction = (action: string, task: Task, onClose: () => void)
:on-language-change="handleLanguageChange"
:on-theme-change="handleThemeChange"
:task-list-column-render-mode="taskListColumnRenderMode"
- :use-default-context-menu="true"
@milestone-saved="handleMilestoneSaved"
@milestone-deleted="handleMilestoneDeleted"
@milestone-icon-changed="handleMilestoneIconChanged"
@@ -1371,35 +1370,43 @@ const handleCustomMenuAction = (action: string, task: Task, onClose: () => void)
-
-
-
-
diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue
index 7f8a71c..cc5705c 100644
--- a/src/components/Timeline.vue
+++ b/src/components/Timeline.vue
@@ -3061,6 +3061,9 @@ const handleTimelineScroll = (event: Event) => {
// 立即更新关键滚动位置信息(用于虚拟滚动)
timelineScrollLeft.value = scrollLeft
+ // 滚动时关闭所有右键菜单
+ window.dispatchEvent(new CustomEvent('close-all-taskbar-menus'))
+
// 优化:滚动时失效 bodyRect 缓存(用于连接线拖拽)
bodyRectInvalidated = true
@@ -4306,6 +4309,7 @@ const handleAddSuccessor = (task: Task) => {
v-else-if="task.type !== 'milestone-group' && task.type !== 'milestone'"
:key="`taskbar-${task.id}-${taskBarRenderKey}`"
:task="task"
+ :row-index="originalIndex"
:row-height="50"
:day-width="dayWidth"
:start-date="
diff --git a/src/components/Timeline/TaskBarContextMenu.vue b/src/components/Timeline/TaskBarContextMenu.vue
new file mode 100644
index 0000000..2be0237
--- /dev/null
+++ b/src/components/Timeline/TaskBarContextMenu.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
diff --git a/src/components/Timeline/composables/useTaskBarContextMenu.ts b/src/components/Timeline/composables/useTaskBarContextMenu.ts
new file mode 100644
index 0000000..e153156
--- /dev/null
+++ b/src/components/Timeline/composables/useTaskBarContextMenu.ts
@@ -0,0 +1,133 @@
+import { computed, type VNode, type Slots, type VNodeChild, type Component } from 'vue'
+import type { Task } from '../../../models/classes/Task'
+
+/**
+ * 声明式右键菜单配置接口
+ */
+export interface DeclarativeContextMenuConfig {
+ // slot 渲染函数
+ defaultSlot?: (scope: {
+ row: Task
+ $index: number
+ }) => VNodeChild
+ // 指定哪些任务类型显示此右键菜单
+ taskType?: string | string[]
+}
+
+/**
+ * 从 VNode 中提取 task-bar-context-menu 的配置
+ */
+export function extractTaskBarContextMenuConfig(vnode: VNode): DeclarativeContextMenuConfig | null {
+ // 检查是否是 TaskBarContextMenu 组件
+ let isTaskBarContextMenu = false
+
+ if (typeof vnode.type === 'object') {
+ const component = vnode.type as Component & {
+ __name?: string
+ __file?: string
+ }
+ // 检查组件名称的多种可能性
+ isTaskBarContextMenu =
+ component.name === 'TaskBarContextMenu' ||
+ component.__name === 'TaskBarContextMenu' ||
+ // 检查文件名(setup script 组件)
+ (component.__file !== undefined && component.__file.includes('TaskBarContextMenu'))
+ }
+
+ if (!isTaskBarContextMenu) {
+ return null
+ }
+
+ // 提取 props
+ const props = vnode.props || {}
+
+ // 提取 slots
+ type ChildrenType =
+ | {
+ default?: (scope: {
+ row: Task
+ $index: number
+ }) => VNodeChild
+ }
+ | null
+ const children = vnode.children as ChildrenType
+
+ const defaultSlot = children?.default
+
+ if (!defaultSlot) {
+ return null
+ }
+
+ return {
+ defaultSlot,
+ taskType: props.taskType || props['task-type'],
+ }
+}
+
+/**
+ * 解析声明式右键菜单配置
+ * 从默认 slot 的 VNode 中提取 TaskBarContextMenu 的配置
+ */
+export function parseDeclarativeTaskBarContextMenu(
+ slots: Slots,
+): DeclarativeContextMenuConfig | null {
+ const defaultSlot = slots.default?.()
+
+ if (!defaultSlot || !Array.isArray(defaultSlot)) {
+ return null
+ }
+
+ // 递归查找 TaskBarContextMenu
+ const findContextMenu = (vnodes: VNode[]): DeclarativeContextMenuConfig | null => {
+ for (const vnode of vnodes) {
+ if (!vnode) {
+ continue
+ }
+
+ // 如果是 Fragment 或其他 Symbol 类型,直接处理子节点
+ if (typeof vnode.type === 'symbol') {
+ if (vnode.children && Array.isArray(vnode.children)) {
+ const result = findContextMenu(vnode.children as VNode[])
+ if (result) return result
+ }
+ continue
+ }
+
+ const config = extractTaskBarContextMenuConfig(vnode)
+ if (config) {
+ return config
+ }
+
+ // 递归处理子节点
+ if (vnode.children && Array.isArray(vnode.children)) {
+ const result = findContextMenu(vnode.children as VNode[])
+ if (result) return result
+ }
+ }
+
+ return null
+ }
+
+ return findContextMenu(defaultSlot)
+}
+
+/**
+ * TaskBar Context Menu Composable
+ * 用于管理 TaskBar 的右键菜单(支持声明式)
+ */
+export function useTaskBarContextMenu(slots: Slots) {
+ // 声明式菜单配置
+ const declarativeContextMenu = computed(() => {
+ return parseDeclarativeTaskBarContextMenu(slots)
+ })
+
+ // 是否有声明式菜单
+ const hasDeclarativeContextMenu = computed(() => {
+ return !!declarativeContextMenu.value
+ })
+
+ return {
+ declarativeContextMenu,
+ hasDeclarativeContextMenu,
+ }
+}
diff --git a/src/components/index.ts b/src/components/index.ts
index 17fcbb1..a517bc3 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -2,9 +2,11 @@ export { default as GanttChart } from './GanttChart.vue'
export { default as GanttToolbar } from './GanttToolbar.vue'
export { default as TaskList } from './TaskList/TaskList.vue'
export { default as TaskListColumn } from './TaskList/TaskListColumn.vue'
+export { default as TaskListContextMenu } from './TaskList/TaskListContextMenu.vue'
export { default as TaskRow } from './TaskList/taskRow/TaskRow.vue'
export { default as Timeline } from './Timeline.vue'
export { default as TaskBar } from './TaskBar.vue'
+export { default as TaskBarContextMenu } from './Timeline/TaskBarContextMenu.vue'
export { default as MilestonePoint } from './MilestonePoint.vue'
export { default as MilestoneDialog } from './MilestoneDialog.vue'
export { default as TaskDrawer } from './TaskDrawer.vue'
diff --git a/src/index.ts b/src/index.ts
index 8fe62c8..459e4b2 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,8 +2,10 @@
export { default as GanttChart } from './components/GanttChart.vue'
export { default as TaskList } from './components/TaskList/TaskList.vue'
export { default as TaskListColumn } from './components/TaskList/TaskListColumn.vue'
+export { default as TaskListContextMenu } from './components/TaskList/TaskListContextMenu.vue'
export { default as Timeline } from './components/Timeline.vue'
export { default as TaskBar } from './components/TaskBar.vue'
+export { default as TaskBarContextMenu } from './components/Timeline/TaskBarContextMenu.vue'
export { default as TaskDrawer } from './components/TaskDrawer.vue'
export { default as MilestonePoint } from './components/MilestonePoint.vue'
export { default as MilestoneDialog } from './components/MilestoneDialog.vue'
@@ -31,10 +33,14 @@ import './styles/theme-variables.css'
import type { App } from 'vue'
import GanttChart from './components/GanttChart.vue'
import TaskListColumn from './components/TaskList/TaskListColumn.vue'
+import TaskListContextMenu from './components/TaskList/TaskListContextMenu.vue'
+import TaskBarContextMenu from './components/Timeline/TaskBarContextMenu.vue'
export const install = (app: App) => {
app.component('GanttChart', GanttChart)
app.component('TaskListColumn', TaskListColumn)
+ app.component('TaskListContextMenu', TaskListContextMenu)
+ app.component('TaskBarContextMenu', TaskBarContextMenu)
}
export default {