UNPKG

vue-gantt-3

Version:

A gantt component for Vue 3

1 lines 8.41 kB
{"version":3,"file":"useGanttSelect.mjs","sources":["../../../src/composables/useGanttSelect.ts"],"sourcesContent":["import { ref, provide, onMounted, onBeforeUnmount, watch } from 'vue';\nimport type { Ref } from 'vue';\n\nexport const useGanttSelect = ({\n vGanttRef,\n visibleRowIds,\n rowHeight,\n rowSelection,\n rowClass,\n emitGanttMouseDown,\n emitSelectChange\n}: {\n vGanttRef: Ref<HTMLDivElement | undefined>,\n visibleRowIds: Ref<string[], string[]>,\n rowHeight: Ref<number>,\n rowSelection: Ref<'single' | 'multiple' | 'none'>,\n rowClass: string,\n emitGanttMouseDown: (event: MouseEvent, rowId: string | null) => void,\n emitSelectChange: (ids: string[]) => void\n}) => {\n const selectedRowIds = ref<Set<string>>(new Set());\n let lastMouseMoveTarget: HTMLElement | null = null;\n let lastClickedRowId = '';\n let lastClickedRowIndex = 0;\n\n provide(\n 'selectedRowIds',\n selectedRowIds\n );\n\n watch(selectedRowIds, (val) => {\n emitSelectChange([...val]);\n }, { deep: true });\n\n onMounted(() => {\n vGanttRef.value?.addEventListener('mousedown', handleGanttMouseDown);\n });\n\n onBeforeUnmount(() => {\n vGanttRef.value?.removeEventListener('mousedown', handleGanttMouseDown);\n });\n\n function handleGanttMouseDown (this: HTMLElement, event: MouseEvent) {\n if (rowSelection.value === 'none') return;\n const { target, attributeValue: rowId, rowIndex } = getTargetElementInfo(event.target as HTMLElement | null, rowClass, 'data-row-id');\n emitGanttMouseDown(event, rowId);\n if (target) {\n const isLeftMouse = event.button === 0;\n if (rowId) {\n handleRowSelect(rowId, event, rowIndex);\n } else {\n // click empty table view row to clear select\n selectedRowIds.value.clear();\n return;\n }\n if (isLeftMouse && rowSelection.value === 'multiple') {\n this.addEventListener('mousemove', handleGanttMouseMove);\n document.addEventListener('mouseup', handleGanttMouseUp);\n }\n } else {\n // click empty gantt view row to clear select\n const { target: ganttBodyRef } = getTargetElementInfo(event.target as HTMLElement | null, 'vg-body');\n if (ganttBodyRef) {\n selectedRowIds.value.clear();\n }\n\n }\n }\n\n function handleGanttMouseMove(event: MouseEvent) {\n const { target, attributeValue: rowId, rowIndex } = getTargetElementInfo(event.target as HTMLElement | null, rowClass, 'data-row-id');\n if (target && lastMouseMoveTarget !== target) {\n lastMouseMoveTarget = target;\n if (rowId) {\n handleRowSelect(rowId, event, rowIndex, true);\n }\n }\n }\n\n function handleGanttMouseUp() {\n vGanttRef.value?.removeEventListener('mousemove', handleGanttMouseMove);\n document.removeEventListener('mouseup', handleGanttMouseUp);\n }\n\n /**\n * select function core, support multi select by using ctrl and shift\n * @param rowId\n * @param event\n * @param rowIndex\n * @param onShift\n * @returns\n */\n const handleRowSelect = (rowId: string, event: MouseEvent, rowIndex:number, onShift?: boolean) => {\n const pressCtrl = event?.ctrlKey;\n const pressShift = event?.shiftKey || onShift;\n const isContextmenuClick = event?.type === 'contextmenu';\n const selectedRowIdSize = selectedRowIds.value.size;\n\n if (!pressCtrl || isContextmenuClick) {\n selectedRowIds.value.clear();\n }\n\n if (pressCtrl && !pressShift) {\n if (selectedRowIds.value.has(rowId)) {\n selectedRowIds.value.delete(rowId);\n return;\n }\n }\n\n // handle shift\n if (pressShift && !isContextmenuClick && selectedRowIdSize > 0 && lastClickedRowId !== rowId) {\n const bigRowIndex = Math.max(rowIndex, lastClickedRowIndex);\n const smallRowIndex = Math.min(rowIndex, lastClickedRowIndex);\n const willSelectedRowIds = visibleRowIds.value.slice(smallRowIndex, bigRowIndex + 1);\n for (let id of willSelectedRowIds) {\n selectedRowIds.value.add(id);\n }\n } else {\n selectedRowIds.value.add(rowId);\n lastClickedRowId = rowId;\n lastClickedRowIndex = rowIndex;\n }\n };\n\n /**\n * get target dom attribute and row index\n * @param initialTarget\n * @param targetClass\n * @param attribute\n * @returns\n */\n const getTargetElementInfo = (initialTarget: HTMLElement | null, targetClass: string, attribute?: string) => {\n let target = initialTarget;\n let attributeValue: string | null = '';\n let rowIndex = 0;\n while (target && !target.classList.contains(targetClass)) {\n target = target?.parentElement;\n }\n\n // calculate row index by transformY / rowHeight\n if (target && attribute) {\n attributeValue = target.getAttribute(attribute);\n const transform = target.style.transform;\n const transformYStr = transform.match(/translateY\\((.+)px\\)/)?.[1];\n if (transformYStr) {\n const transformY = parseFloat(transformYStr);\n // Rounding is required here to prevent the last bit of the browser's scientific count from being intercepted\n // when the value is too large, resulting in incorrect calculation of the rowIndex\n rowIndex = parseInt((transformY / rowHeight.value).toFixed(0));\n }\n }\n\n return {\n target,\n attributeValue,\n rowIndex\n };\n };\n\n const handleSetSelect = (id: string) => {\n if (rowSelection.value === 'none') return;\n selectedRowIds.value.clear();\n selectedRowIds.value.add(id);\n };\n\n const selectRows = (ids: string[]) => {\n selectedRowIds.value = new Set(ids);\n };\n\n return {\n handleSetSelect,\n selectRows,\n getTargetElementInfo,\n };\n};"],"names":[],"mappings":"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"}