@stonecrop/atable 0.30.0 → 0.32.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/dist/assets/index.css +804 -1
- package/dist/atable.js +2809 -1944
- package/dist/atable.js.map +1 -1
- package/dist/src/components/ACell.vue.d.ts +17 -0
- package/dist/src/components/ACell.vue.d.ts.map +1 -0
- package/dist/src/components/AGanttCell.vue.d.ts +34 -0
- package/dist/src/components/AGanttCell.vue.d.ts.map +1 -0
- package/dist/src/components/AGanttConnection.vue.d.ts +13 -0
- package/dist/src/components/AGanttConnection.vue.d.ts.map +1 -0
- package/dist/src/components/ARow.vue.d.ts +2693 -0
- package/dist/src/components/ARow.vue.d.ts.map +1 -0
- package/dist/src/components/ARowActions.vue.d.ts +16 -0
- package/dist/src/components/ARowActions.vue.d.ts.map +1 -0
- package/dist/src/components/ATable.vue.d.ts +13358 -0
- package/dist/src/components/ATable.vue.d.ts.map +1 -0
- package/dist/src/components/ATableColumnFilter.vue.d.ts +11 -0
- package/dist/src/components/ATableColumnFilter.vue.d.ts.map +1 -0
- package/dist/src/components/ATableHeader.vue.d.ts +20 -0
- package/dist/src/components/ATableHeader.vue.d.ts.map +1 -0
- package/dist/src/components/ATableLoading.vue.d.ts +14 -0
- package/dist/src/components/ATableLoading.vue.d.ts.map +1 -0
- package/dist/src/components/ATableLoadingBar.vue.d.ts +14 -0
- package/dist/src/components/ATableLoadingBar.vue.d.ts.map +1 -0
- package/dist/src/components/ATableModal.vue.d.ts +18 -0
- package/dist/src/components/ATableModal.vue.d.ts.map +1 -0
- package/dist/src/components/ATablePaginationFooter.vue.d.ts +17 -0
- package/dist/src/components/ATablePaginationFooter.vue.d.ts.map +1 -0
- package/dist/src/icons/index.d.ts +14 -7
- package/dist/src/icons/index.d.ts.map +1 -1
- package/dist/{tsdoc-metadata.json → src/tsdoc-metadata.json} +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/package.json +35 -29
- package/dist/atable.d.ts +0 -3560
- package/dist/atable.tsbuildinfo +0 -1
- package/dist/icons/stonecrop-ui-icon-add.svg +0 -5
- package/dist/icons/stonecrop-ui-icon-delete.svg +0 -5
- package/dist/icons/stonecrop-ui-icon-duplicate.svg +0 -5
- package/dist/icons/stonecrop-ui-icon-insert-above.svg +0 -15
- package/dist/icons/stonecrop-ui-icon-insert-below.svg +0 -15
- package/dist/icons/stonecrop-ui-icon-move.svg +0 -4
- package/dist/icons/stonecrop-ui-icon-open.svg +0 -5
- package/dist/src/composables/table-pagination.js +0 -108
- package/dist/src/icons/index.js +0 -32
- package/dist/src/index.js +0 -33
- package/dist/src/linkSearchableText.js +0 -44
- package/dist/src/resolveFilterType.js +0 -27
- package/dist/src/schemaToColumns.js +0 -59
- package/dist/src/stores/table.js +0 -833
- package/dist/src/types/index.js +0 -0
- package/dist/src/utils.js +0 -39
- package/src/components/ACell.vue +0 -410
- package/src/components/AGanttCell.vue +0 -638
- package/src/components/AGanttConnection.vue +0 -164
- package/src/components/ARow.vue +0 -251
- package/src/components/ARowActions.vue +0 -407
- package/src/components/ATable.vue +0 -538
- package/src/components/ATableColumnFilter.vue +0 -216
- package/src/components/ATableHeader.vue +0 -141
- package/src/components/ATableLoading.vue +0 -86
- package/src/components/ATableLoadingBar.vue +0 -81
- package/src/components/ATableModal.vue +0 -52
- package/src/components/ATablePaginationFooter.vue +0 -100
- package/src/composables/table-pagination.ts +0 -172
- package/src/icons/index.ts +0 -38
- package/src/icons/stonecrop-ui-icon-add.svg +0 -5
- package/src/icons/stonecrop-ui-icon-delete.svg +0 -5
- package/src/icons/stonecrop-ui-icon-duplicate.svg +0 -5
- package/src/icons/stonecrop-ui-icon-insert-above.svg +0 -15
- package/src/icons/stonecrop-ui-icon-insert-below.svg +0 -15
- package/src/icons/stonecrop-ui-icon-move.svg +0 -4
- package/src/icons/stonecrop-ui-icon-open.svg +0 -5
- package/src/index.ts +0 -62
- package/src/linkSearchableText.ts +0 -42
- package/src/resolveFilterType.ts +0 -32
- package/src/schemaToColumns.ts +0 -67
- package/src/shims-vue.d.ts +0 -10
- package/src/stores/table.ts +0 -978
- package/src/types/index.ts +0 -794
- package/src/utils.ts +0 -40
|
@@ -1,638 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<td class="aganttcell" :colspan="colspan">
|
|
3
|
-
<div ref="container" class="gantt-container">
|
|
4
|
-
<!-- Draggable gantt bar -->
|
|
5
|
-
<div
|
|
6
|
-
ref="bar"
|
|
7
|
-
:data-rowindex="rowIndex"
|
|
8
|
-
:data-colindex="colIndex"
|
|
9
|
-
class="gantt-bar"
|
|
10
|
-
:class="{ 'is-dragging': isAnyDragging }"
|
|
11
|
-
:style="barStyle"
|
|
12
|
-
@mouseenter="showConnectionHandles"
|
|
13
|
-
@mouseleave="hideConnectionHandles">
|
|
14
|
-
<!-- Connection handles for linking bars - only show if dependency graph is enabled -->
|
|
15
|
-
<div
|
|
16
|
-
v-if="store.isDependencyGraphEnabled"
|
|
17
|
-
ref="leftConnectionHandle"
|
|
18
|
-
class="connection-handle left-connection-handle"
|
|
19
|
-
:class="{ visible: isLeftConnectionVisible, 'is-dragging': isLeftConnectionDragging }"
|
|
20
|
-
@mousedown.stop="startConnectionDrag('left', $event)">
|
|
21
|
-
<div class="connection-dot"></div>
|
|
22
|
-
</div>
|
|
23
|
-
|
|
24
|
-
<div
|
|
25
|
-
v-if="store.isDependencyGraphEnabled"
|
|
26
|
-
ref="rightConnectionHandle"
|
|
27
|
-
class="connection-handle right-connection-handle"
|
|
28
|
-
:class="{ visible: isRightConnectionVisible, 'is-dragging': isRightConnectionDragging }"
|
|
29
|
-
@mousedown.stop="startConnectionDrag('right', $event)">
|
|
30
|
-
<div class="connection-dot"></div>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<!-- Resize handles for changing bar length -->
|
|
34
|
-
<div ref="leftResizeHandle" class="resize-handle left-resize-handle" :class="{ 'is-dragging': isLeftResizing }">
|
|
35
|
-
<div class="handle-grip"></div>
|
|
36
|
-
<div class="vertical-indicator left-indicator"></div>
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<label v-if="label" class="gantt-label">{{ label }}</label>
|
|
40
|
-
|
|
41
|
-
<div
|
|
42
|
-
ref="rightResizeHandle"
|
|
43
|
-
class="resize-handle right-resize-handle"
|
|
44
|
-
:class="{ 'is-dragging': isRightResizing }">
|
|
45
|
-
<div class="handle-grip"></div>
|
|
46
|
-
<div class="vertical-indicator right-indicator"></div>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
<!-- Connection drag preview line - only show if dependency graph is enabled -->
|
|
52
|
-
<svg v-if="store.isDependencyGraphEnabled && showDragPreview" :style="connectionDragStyle">
|
|
53
|
-
<line
|
|
54
|
-
:x1="dragPreview.startX"
|
|
55
|
-
:y1="dragPreview.startY"
|
|
56
|
-
:x2="dragPreview.endX"
|
|
57
|
-
:y2="dragPreview.endY"
|
|
58
|
-
stroke="#2196f3"
|
|
59
|
-
stroke-width="2"
|
|
60
|
-
stroke-dasharray="5,5" />
|
|
61
|
-
</svg>
|
|
62
|
-
</td>
|
|
63
|
-
</template>
|
|
64
|
-
|
|
65
|
-
<script setup lang="ts">
|
|
66
|
-
import { useDraggable, useElementBounding } from '@vueuse/core'
|
|
67
|
-
import { ref, computed, onMounted, onUnmounted, useTemplateRef, type StyleValue } from 'vue'
|
|
68
|
-
|
|
69
|
-
import { createTableStore } from '../stores/table'
|
|
70
|
-
import type { ConnectionPath } from '../types'
|
|
71
|
-
|
|
72
|
-
const {
|
|
73
|
-
store,
|
|
74
|
-
columnsCount,
|
|
75
|
-
rowIndex,
|
|
76
|
-
colIndex,
|
|
77
|
-
start = 0,
|
|
78
|
-
end = 0,
|
|
79
|
-
colspan = 1,
|
|
80
|
-
label = '',
|
|
81
|
-
color = '#cccccc',
|
|
82
|
-
} = defineProps<{
|
|
83
|
-
store: ReturnType<typeof createTableStore>
|
|
84
|
-
columnsCount: number
|
|
85
|
-
rowIndex: number
|
|
86
|
-
colIndex: number
|
|
87
|
-
start?: number
|
|
88
|
-
end?: number
|
|
89
|
-
colspan?: number
|
|
90
|
-
label?: string
|
|
91
|
-
color?: string
|
|
92
|
-
}>()
|
|
93
|
-
|
|
94
|
-
const emit = defineEmits<{
|
|
95
|
-
'connection:create': [connection: ConnectionPath]
|
|
96
|
-
}>()
|
|
97
|
-
|
|
98
|
-
// Core refs and state
|
|
99
|
-
const barColor = ref(color.length >= 6 ? color : '#cccccc')
|
|
100
|
-
const barId = `gantt-bar-row-${rowIndex}-col-${colIndex}`
|
|
101
|
-
|
|
102
|
-
// Template refs
|
|
103
|
-
const containerRef = useTemplateRef<HTMLDivElement>('container')
|
|
104
|
-
const barRef = useTemplateRef<HTMLDivElement>('bar')
|
|
105
|
-
const leftResizeHandleRef = useTemplateRef<HTMLDivElement>('leftResizeHandle')
|
|
106
|
-
const rightResizeHandleRef = useTemplateRef<HTMLDivElement>('rightResizeHandle')
|
|
107
|
-
const leftConnectionHandleRef = useTemplateRef<HTMLDivElement>('leftConnectionHandle')
|
|
108
|
-
const rightConnectionHandleRef = useTemplateRef<HTMLDivElement>('rightConnectionHandle')
|
|
109
|
-
|
|
110
|
-
// Position tracking
|
|
111
|
-
const { width: totalBarWidth } = useElementBounding(containerRef)
|
|
112
|
-
const { left: barLeft, right: barRight } = useElementBounding(barRef)
|
|
113
|
-
|
|
114
|
-
// Bar positioning
|
|
115
|
-
const currentStart = ref(start)
|
|
116
|
-
const currentEnd = ref(end || currentStart.value + colspan)
|
|
117
|
-
|
|
118
|
-
// Drag states
|
|
119
|
-
const isLeftConnectionVisible = ref(false)
|
|
120
|
-
const isRightConnectionVisible = ref(false)
|
|
121
|
-
const isLeftConnectionDragging = ref(false)
|
|
122
|
-
const isRightConnectionDragging = ref(false)
|
|
123
|
-
const showDragPreview = ref(false)
|
|
124
|
-
const dragPreview = ref({ startX: 0, startY: 0, endX: 0, endY: 0 })
|
|
125
|
-
|
|
126
|
-
// Computed properties
|
|
127
|
-
const isAnyDragging = computed(() => isBarDragging.value || isLeftResizing.value || isRightResizing.value)
|
|
128
|
-
|
|
129
|
-
const pixelsPerColumn = computed(() => (colspan > 0 ? totalBarWidth.value / colspan : 0))
|
|
130
|
-
|
|
131
|
-
const barStyle = computed((): StyleValue => {
|
|
132
|
-
const startPercent = (currentStart.value / colspan) * 100
|
|
133
|
-
const endPercent = (currentEnd.value / colspan) * 100
|
|
134
|
-
return {
|
|
135
|
-
left: `${startPercent}%`,
|
|
136
|
-
width: `${endPercent - startPercent}%`,
|
|
137
|
-
backgroundColor: barColor.value,
|
|
138
|
-
}
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
const connectionDragStyle = computed((): StyleValue => ({
|
|
142
|
-
position: 'fixed',
|
|
143
|
-
top: 0,
|
|
144
|
-
left: 0,
|
|
145
|
-
width: '100vw',
|
|
146
|
-
height: '100vh',
|
|
147
|
-
pointerEvents: 'none',
|
|
148
|
-
zIndex: 1000,
|
|
149
|
-
}))
|
|
150
|
-
|
|
151
|
-
// Drag setup data
|
|
152
|
-
const dragStartData = ref({ startX: 0, startPos: 0 })
|
|
153
|
-
|
|
154
|
-
// Left resize handle dragging
|
|
155
|
-
const { isDragging: isLeftResizing } = useDraggable(leftResizeHandleRef, {
|
|
156
|
-
axis: 'x',
|
|
157
|
-
onStart: () => setupDragStart(barLeft.value, currentStart.value),
|
|
158
|
-
onMove: ({ x }) => handleLeftResize(x),
|
|
159
|
-
onEnd: ({ x }) => finishLeftResize(x),
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
// Right resize handle dragging
|
|
163
|
-
const { isDragging: isRightResizing } = useDraggable(rightResizeHandleRef, {
|
|
164
|
-
axis: 'x',
|
|
165
|
-
onStart: () => setupDragStart(barRight.value, currentEnd.value),
|
|
166
|
-
onMove: ({ x }) => handleRightResize(x),
|
|
167
|
-
onEnd: ({ x }) => finishRightResize(x),
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
// Bar movement dragging
|
|
171
|
-
const { isDragging: isBarDragging } = useDraggable(barRef, {
|
|
172
|
-
exact: true,
|
|
173
|
-
axis: 'x',
|
|
174
|
-
onStart: () => setupDragStart(barLeft.value, currentStart.value),
|
|
175
|
-
onMove: ({ x }) => handleBarMove(x),
|
|
176
|
-
onEnd: ({ x }) => finishBarMove(x),
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
// Lifecycle
|
|
180
|
-
onMounted(() => {
|
|
181
|
-
registerGanttComponents()
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
onUnmounted(() => {
|
|
185
|
-
unregisterGanttComponents()
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
// Helper functions
|
|
189
|
-
function setupDragStart(startX: number, startPos: number) {
|
|
190
|
-
if (barRef.value) barRef.value.style.transition = 'none'
|
|
191
|
-
dragStartData.value = { startX, startPos }
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function handleLeftResize(x: number) {
|
|
195
|
-
if (!isLeftResizing.value || !barRef.value) return
|
|
196
|
-
|
|
197
|
-
const deltaX = x - dragStartData.value.startX
|
|
198
|
-
const deltaColumns = deltaX / pixelsPerColumn.value
|
|
199
|
-
const newStart = Math.max(0, Math.min(currentEnd.value - 1, dragStartData.value.startPos + deltaColumns))
|
|
200
|
-
|
|
201
|
-
barRef.value.style.left = `${(newStart / colspan) * 100}%`
|
|
202
|
-
barRef.value.style.width = `${((currentEnd.value - newStart) / colspan) * 100}%`
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function finishLeftResize(x: number) {
|
|
206
|
-
if (!barRef.value) return
|
|
207
|
-
|
|
208
|
-
const deltaX = x - dragStartData.value.startX
|
|
209
|
-
const deltaColumns = Math.round(deltaX / pixelsPerColumn.value)
|
|
210
|
-
const oldStart = currentStart.value
|
|
211
|
-
const newStart = Math.max(0, Math.min(currentEnd.value - 1, dragStartData.value.startPos + deltaColumns))
|
|
212
|
-
|
|
213
|
-
currentStart.value = newStart
|
|
214
|
-
store.updateGanttBar({
|
|
215
|
-
rowIndex,
|
|
216
|
-
colIndex,
|
|
217
|
-
type: 'resize',
|
|
218
|
-
edge: 'start',
|
|
219
|
-
oldStart,
|
|
220
|
-
newStart,
|
|
221
|
-
end: currentEnd.value,
|
|
222
|
-
delta: deltaColumns,
|
|
223
|
-
oldColspan: currentEnd.value - oldStart,
|
|
224
|
-
newColspan: currentEnd.value - newStart,
|
|
225
|
-
})
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function handleRightResize(x: number) {
|
|
229
|
-
if (!isRightResizing.value || !barRef.value) return
|
|
230
|
-
|
|
231
|
-
const deltaX = x - dragStartData.value.startX
|
|
232
|
-
const deltaColumns = deltaX / pixelsPerColumn.value
|
|
233
|
-
const newEnd = Math.max(currentStart.value + 1, Math.min(columnsCount, dragStartData.value.startPos + deltaColumns))
|
|
234
|
-
|
|
235
|
-
barRef.value.style.width = `${((newEnd - currentStart.value) / colspan) * 100}%`
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
function finishRightResize(x: number) {
|
|
239
|
-
if (!barRef.value) return
|
|
240
|
-
|
|
241
|
-
const deltaX = x - dragStartData.value.startX
|
|
242
|
-
const deltaColumns = Math.round(deltaX / pixelsPerColumn.value)
|
|
243
|
-
const oldEnd = currentEnd.value
|
|
244
|
-
const newEnd = Math.max(currentStart.value + 1, Math.min(columnsCount, dragStartData.value.startPos + deltaColumns))
|
|
245
|
-
|
|
246
|
-
currentEnd.value = newEnd
|
|
247
|
-
store.updateGanttBar({
|
|
248
|
-
rowIndex,
|
|
249
|
-
colIndex,
|
|
250
|
-
type: 'resize',
|
|
251
|
-
edge: 'end',
|
|
252
|
-
oldEnd,
|
|
253
|
-
newEnd,
|
|
254
|
-
start: currentStart.value,
|
|
255
|
-
delta: deltaColumns,
|
|
256
|
-
oldColspan: oldEnd - currentStart.value,
|
|
257
|
-
newColspan: newEnd - currentStart.value,
|
|
258
|
-
})
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function handleBarMove(x: number) {
|
|
262
|
-
if (!isBarDragging.value || !barRef.value) return
|
|
263
|
-
|
|
264
|
-
const deltaX = x - dragStartData.value.startX
|
|
265
|
-
const deltaColumns = deltaX / pixelsPerColumn.value
|
|
266
|
-
const barWidth = currentEnd.value - currentStart.value
|
|
267
|
-
const newStart = Math.max(0, Math.min(dragStartData.value.startPos + deltaColumns, columnsCount - barWidth))
|
|
268
|
-
|
|
269
|
-
barRef.value.style.left = `${(newStart / colspan) * 100}%`
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
function finishBarMove(x: number) {
|
|
273
|
-
if (!barRef.value) return
|
|
274
|
-
|
|
275
|
-
const deltaX = x - dragStartData.value.startX
|
|
276
|
-
const deltaColumns = Math.round(deltaX / pixelsPerColumn.value)
|
|
277
|
-
const barWidth = currentEnd.value - currentStart.value
|
|
278
|
-
|
|
279
|
-
const oldStart = currentStart.value
|
|
280
|
-
const oldEnd = currentEnd.value
|
|
281
|
-
let newStart = dragStartData.value.startPos + deltaColumns
|
|
282
|
-
let newEnd = newStart + barWidth
|
|
283
|
-
|
|
284
|
-
// Boundary checks
|
|
285
|
-
if (newStart < 0) {
|
|
286
|
-
newStart = 0
|
|
287
|
-
newEnd = barWidth
|
|
288
|
-
} else if (newEnd > columnsCount) {
|
|
289
|
-
newEnd = columnsCount
|
|
290
|
-
newStart = newEnd - barWidth
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
currentStart.value = newStart
|
|
294
|
-
currentEnd.value = newEnd
|
|
295
|
-
|
|
296
|
-
store.updateGanttBar({
|
|
297
|
-
rowIndex,
|
|
298
|
-
colIndex,
|
|
299
|
-
type: 'bar',
|
|
300
|
-
oldStart,
|
|
301
|
-
oldEnd,
|
|
302
|
-
newStart,
|
|
303
|
-
newEnd,
|
|
304
|
-
delta: deltaColumns,
|
|
305
|
-
colspan: newEnd - newStart,
|
|
306
|
-
})
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function registerGanttComponents() {
|
|
310
|
-
const { x: barX, y: barY } = useElementBounding(barRef)
|
|
311
|
-
const { x: leftX, y: leftY } = useElementBounding(leftConnectionHandleRef)
|
|
312
|
-
const { x: rightX, y: rightY } = useElementBounding(rightConnectionHandleRef)
|
|
313
|
-
|
|
314
|
-
store.registerGanttBar({
|
|
315
|
-
id: barId,
|
|
316
|
-
rowIndex,
|
|
317
|
-
colIndex,
|
|
318
|
-
startIndex: currentStart,
|
|
319
|
-
endIndex: currentEnd,
|
|
320
|
-
color: barColor,
|
|
321
|
-
label,
|
|
322
|
-
position: { x: barX, y: barY },
|
|
323
|
-
})
|
|
324
|
-
|
|
325
|
-
// Only register connection handles if dependency graph is enabled
|
|
326
|
-
if (store.isDependencyGraphEnabled) {
|
|
327
|
-
store.registerConnectionHandle({
|
|
328
|
-
id: `${barId}-connection-left`,
|
|
329
|
-
rowIndex,
|
|
330
|
-
colIndex,
|
|
331
|
-
side: 'left',
|
|
332
|
-
position: { x: leftX, y: leftY },
|
|
333
|
-
visible: isLeftConnectionVisible,
|
|
334
|
-
barId,
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
store.registerConnectionHandle({
|
|
338
|
-
id: `${barId}-connection-right`,
|
|
339
|
-
rowIndex,
|
|
340
|
-
colIndex,
|
|
341
|
-
side: 'right',
|
|
342
|
-
position: { x: rightX, y: rightY },
|
|
343
|
-
visible: isRightConnectionVisible,
|
|
344
|
-
barId,
|
|
345
|
-
})
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function unregisterGanttComponents() {
|
|
350
|
-
store.unregisterGanttBar(barId)
|
|
351
|
-
// Only unregister connection handles if dependency graph is enabled
|
|
352
|
-
if (store.isDependencyGraphEnabled) {
|
|
353
|
-
store.unregisterConnectionHandle(`${barId}-connection-left`)
|
|
354
|
-
store.unregisterConnectionHandle(`${barId}-connection-right`)
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
function showConnectionHandles() {
|
|
359
|
-
// Only show connection handles if dependency graph is enabled
|
|
360
|
-
if (store.isDependencyGraphEnabled) {
|
|
361
|
-
isLeftConnectionVisible.value = true
|
|
362
|
-
isRightConnectionVisible.value = true
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function hideConnectionHandles() {
|
|
367
|
-
if (!isLeftConnectionDragging.value && !isRightConnectionDragging.value) {
|
|
368
|
-
isLeftConnectionVisible.value = false
|
|
369
|
-
isRightConnectionVisible.value = false
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
function startConnectionDrag(side: 'left' | 'right', event: MouseEvent) {
|
|
374
|
-
event.preventDefault()
|
|
375
|
-
event.stopPropagation()
|
|
376
|
-
|
|
377
|
-
showDragPreview.value = true
|
|
378
|
-
if (side === 'left') {
|
|
379
|
-
isLeftConnectionDragging.value = true
|
|
380
|
-
} else {
|
|
381
|
-
isRightConnectionDragging.value = true
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Set initial drag preview position
|
|
385
|
-
const handle = side === 'left' ? leftConnectionHandleRef.value : rightConnectionHandleRef.value
|
|
386
|
-
if (handle) {
|
|
387
|
-
const handleRect = handle.getBoundingClientRect()
|
|
388
|
-
const centerX = handleRect.left + handleRect.width / 2
|
|
389
|
-
const centerY = handleRect.top + handleRect.height / 2
|
|
390
|
-
dragPreview.value = { startX: centerX, startY: centerY, endX: centerX, endY: centerY }
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const handleMouseMove = (moveEvent: MouseEvent) => {
|
|
394
|
-
dragPreview.value.endX = moveEvent.clientX
|
|
395
|
-
dragPreview.value.endY = moveEvent.clientY
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
const handleMouseUp = (upEvent: MouseEvent) => {
|
|
399
|
-
handleConnectionDrop(upEvent, side)
|
|
400
|
-
cleanupConnectionDrag(handleMouseMove, handleMouseUp)
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
document.addEventListener('mousemove', handleMouseMove)
|
|
404
|
-
document.addEventListener('mouseup', handleMouseUp)
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function handleConnectionDrop(upEvent: MouseEvent, sourceSide: 'left' | 'right') {
|
|
408
|
-
const targetElement = document.elementFromPoint(upEvent.clientX, upEvent.clientY)
|
|
409
|
-
const targetHandle = targetElement?.closest('.connection-handle')
|
|
410
|
-
|
|
411
|
-
if (
|
|
412
|
-
targetHandle &&
|
|
413
|
-
targetHandle !== (sourceSide === 'left' ? leftConnectionHandleRef.value : rightConnectionHandleRef.value)
|
|
414
|
-
) {
|
|
415
|
-
const targetBar = targetHandle.closest('.gantt-bar')
|
|
416
|
-
|
|
417
|
-
if (targetBar) {
|
|
418
|
-
const targetRowIndex = parseInt(targetBar.getAttribute('data-rowindex') || '0')
|
|
419
|
-
const targetColIndex = parseInt(targetBar.getAttribute('data-colindex') || '0')
|
|
420
|
-
const targetSide = targetHandle.classList.contains('left-connection-handle') ? 'left' : 'right'
|
|
421
|
-
const targetBarId = `gantt-bar-row-${targetRowIndex}-col-${targetColIndex}`
|
|
422
|
-
|
|
423
|
-
const connection = store.createConnection(
|
|
424
|
-
`${barId}-connection-${sourceSide}`,
|
|
425
|
-
`${targetBarId}-connection-${targetSide}`
|
|
426
|
-
)
|
|
427
|
-
|
|
428
|
-
if (connection) {
|
|
429
|
-
emit('connection:create', connection)
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
function cleanupConnectionDrag(
|
|
436
|
-
handleMouseMove: (event: MouseEvent) => void,
|
|
437
|
-
handleMouseUp: (event: MouseEvent) => void
|
|
438
|
-
) {
|
|
439
|
-
showDragPreview.value = false
|
|
440
|
-
isLeftConnectionDragging.value = false
|
|
441
|
-
isRightConnectionDragging.value = false
|
|
442
|
-
|
|
443
|
-
document.removeEventListener('mousemove', handleMouseMove)
|
|
444
|
-
document.removeEventListener('mouseup', handleMouseUp)
|
|
445
|
-
|
|
446
|
-
if (!barRef.value?.matches(':hover')) {
|
|
447
|
-
hideConnectionHandles()
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
defineExpose({
|
|
452
|
-
barStyle,
|
|
453
|
-
cleanupConnectionDrag,
|
|
454
|
-
currentEnd,
|
|
455
|
-
handleConnectionDrop,
|
|
456
|
-
isLeftConnectionDragging,
|
|
457
|
-
isLeftConnectionVisible,
|
|
458
|
-
isRightConnectionDragging,
|
|
459
|
-
isRightConnectionVisible,
|
|
460
|
-
showDragPreview,
|
|
461
|
-
})
|
|
462
|
-
</script>
|
|
463
|
-
|
|
464
|
-
<style scoped>
|
|
465
|
-
.aganttcell {
|
|
466
|
-
background-color: #f9f9f9;
|
|
467
|
-
width: 100%;
|
|
468
|
-
padding: 0;
|
|
469
|
-
height: 100%;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
.gantt-container {
|
|
473
|
-
position: relative;
|
|
474
|
-
height: 100%;
|
|
475
|
-
background-color: #f0f0f0;
|
|
476
|
-
border-radius: 4px;
|
|
477
|
-
overflow: visible;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
.gantt-bar {
|
|
481
|
-
position: absolute;
|
|
482
|
-
border-radius: 4px;
|
|
483
|
-
display: flex;
|
|
484
|
-
align-items: center;
|
|
485
|
-
justify-content: space-between;
|
|
486
|
-
cursor: grab;
|
|
487
|
-
box-sizing: border-box;
|
|
488
|
-
border: 1px solid rgba(0, 0, 0, 0.5);
|
|
489
|
-
transition:
|
|
490
|
-
left 0.1s ease-out,
|
|
491
|
-
width 0.1s ease-out;
|
|
492
|
-
height: 80%;
|
|
493
|
-
top: 50%;
|
|
494
|
-
z-index: 0;
|
|
495
|
-
transform: translateY(-50%);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
.gantt-bar:active {
|
|
499
|
-
cursor: grabbing;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
.gantt-bar.is-dragging {
|
|
503
|
-
z-index: 10;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
.gantt-label {
|
|
507
|
-
flex: 1;
|
|
508
|
-
text-align: center;
|
|
509
|
-
font-size: 12px;
|
|
510
|
-
color: #aaaaaa;
|
|
511
|
-
white-space: nowrap;
|
|
512
|
-
overflow: hidden;
|
|
513
|
-
text-overflow: ellipsis;
|
|
514
|
-
padding: 0 8px;
|
|
515
|
-
user-select: none;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
.resize-handle {
|
|
519
|
-
position: relative;
|
|
520
|
-
width: 12px;
|
|
521
|
-
height: 100%;
|
|
522
|
-
cursor: ew-resize;
|
|
523
|
-
display: flex;
|
|
524
|
-
align-items: center;
|
|
525
|
-
justify-content: center;
|
|
526
|
-
z-index: 0;
|
|
527
|
-
background: rgba(0, 0, 0, 0.25);
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
.left-resize-handle {
|
|
531
|
-
border-right: 1px solid rgba(0, 0, 0, 0.5);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
.right-resize-handle {
|
|
535
|
-
border-left: 1px solid rgba(0, 0, 0, 0.5);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
.handle-grip {
|
|
539
|
-
width: 4px;
|
|
540
|
-
height: 12px;
|
|
541
|
-
border-radius: 2px;
|
|
542
|
-
background: rgba(0, 0, 0, 0.8);
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
.resize-handle:hover {
|
|
546
|
-
background-color: rgba(255, 255, 255, 0.5);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
.vertical-indicator {
|
|
550
|
-
position: absolute;
|
|
551
|
-
width: 2px;
|
|
552
|
-
opacity: 0;
|
|
553
|
-
pointer-events: none;
|
|
554
|
-
transition: opacity 0.2s ease;
|
|
555
|
-
top: -100vh;
|
|
556
|
-
height: 100vh;
|
|
557
|
-
z-index: 5;
|
|
558
|
-
background-color: v-bind(barColor);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
.left-indicator {
|
|
562
|
-
left: 50%;
|
|
563
|
-
transform: translateX(-50%);
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
.right-indicator {
|
|
567
|
-
right: 50%;
|
|
568
|
-
transform: translateX(50%);
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
.resize-handle.is-dragging .vertical-indicator {
|
|
572
|
-
opacity: 0.7;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
.gantt-container::after {
|
|
576
|
-
content: '';
|
|
577
|
-
position: absolute;
|
|
578
|
-
top: 0;
|
|
579
|
-
left: 0;
|
|
580
|
-
right: 0;
|
|
581
|
-
bottom: 0;
|
|
582
|
-
background-size: calc(100% / v-bind(colspan)) 100%;
|
|
583
|
-
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.1) 1px, transparent 1px);
|
|
584
|
-
pointer-events: none;
|
|
585
|
-
z-index: 1;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
.connection-handle {
|
|
589
|
-
position: absolute;
|
|
590
|
-
top: 50%;
|
|
591
|
-
transform: translateY(-50%);
|
|
592
|
-
width: 16px;
|
|
593
|
-
height: 16px;
|
|
594
|
-
opacity: 0;
|
|
595
|
-
transition: opacity 0.2s ease;
|
|
596
|
-
cursor: crosshair;
|
|
597
|
-
z-index: 2;
|
|
598
|
-
display: flex;
|
|
599
|
-
align-items: center;
|
|
600
|
-
justify-content: center;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
.connection-handle.visible {
|
|
604
|
-
opacity: 1;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
.left-connection-handle {
|
|
608
|
-
left: -16px;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
.right-connection-handle {
|
|
612
|
-
right: -16px;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
.connection-dot {
|
|
616
|
-
width: 8px;
|
|
617
|
-
height: 8px;
|
|
618
|
-
border-radius: 50%;
|
|
619
|
-
background-color: #2196f3;
|
|
620
|
-
border: 2px solid white;
|
|
621
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
.connection-handle:hover .connection-dot {
|
|
625
|
-
background-color: #1976d2;
|
|
626
|
-
transform: scale(1.2);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
.connection-handle.is-dragging {
|
|
630
|
-
opacity: 1 !important;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
.connection-handle.is-dragging .connection-dot {
|
|
634
|
-
background-color: #1976d2;
|
|
635
|
-
transform: scale(1.3);
|
|
636
|
-
box-shadow: 0 2px 8px rgba(33, 150, 243, 0.4);
|
|
637
|
-
}
|
|
638
|
-
</style>
|