{"version":3,"file":"useTimeLineStretch.mjs","sources":["../../../../../../src/components/ganttView/ganttBody/ganttTimeLineView/useTimeLineStretch.ts"],"sourcesContent":["import { inject, triggerRef } from 'vue';\nimport type { Ref, ShallowRef, ComputedRef } from 'vue';\nimport type { GanttRowNode, VisibleTimeLine, TimeLineNode } from '@/types';\nimport dayjs from 'dayjs';\nimport { getRound } from '@/utils/common';\n\nexport const useTimeLineStretch = ({\n  edgeSpacing,\n  ganttViewWidth,\n  rowNodeMap,\n  movingTimeLineRowId,\n  movingTimeLine,\n  timeLineMoving,\n  visibleTimeLineMap,\n  disableStretch,\n  closeEdgeScroll,\n  sortTimeLineNodes,\n  mergeOverlapTimeLine,\n  freshVisibleTimeLines,\n  getDiffSecondByDistance,\n  getDistanceByDiffDate,\n  emitUpdateMinDate,\n  emitUpdateMaxDate,\n  updateParentTimeLine\n}: {\n  edgeSpacing: number,\n  ganttViewWidth: Ref<number>,\n  rowNodeMap: Ref<Map<string, GanttRowNode>, Map<string, GanttRowNode>>,\n  movingTimeLineRowId: Ref<string>,\n  movingTimeLine: Ref<VisibleTimeLine | null>,\n  timeLineMoving: Ref<boolean>,\n  visibleTimeLineMap: ShallowRef<Map<string, VisibleTimeLine[]>, Map<string, VisibleTimeLine[]>>,\n  disableStretch: ComputedRef<boolean | undefined>,\n  closeEdgeScroll: (perMoveSpacing: number, callBack: (moveSpacing: number) => any) => void\n  sortTimeLineNodes: (timeLineNodes: TimeLineNode[]) => void,\n  mergeOverlapTimeLine: (timeLineNodes: TimeLineNode[]) => TimeLineNode[],\n  freshVisibleTimeLines: (freshAll?: boolean) => void\n  getDiffSecondByDistance: (distance: number, startDate: dayjs.Dayjs) => dayjs.Dayjs,\n  getDistanceByDiffDate: (startDate: dayjs.Dayjs, endDate: dayjs.Dayjs) => number,\n  emitUpdateMinDate: (date: dayjs.Dayjs) => void,\n  emitUpdateMaxDate: (date: dayjs.Dayjs) => void,\n  updateParentTimeLine: (rowId: string) => void\n}) => {\n  const wrapRef = inject('wrapRef') as Ref<HTMLDivElement | undefined>;\n  const freshRowNodeDateByTimeLine = inject('freshRowNodeDateByTimeLine') as (rowId: string) => void;\n  const getGanttMinAndMaxDate = inject('getGanttMinAndMaxDate') as (excludeRowIds?: string[], freshStartDate?: boolean, freshEndDate?: boolean)\n  => { minStartDate: dayjs.Dayjs | null, maxEndDate: dayjs.Dayjs | null };\n  const timeLineStretchChange = inject('timeLineStretchChange') as (rowId: string, timeLineIds: string[], startDate: dayjs.Dayjs | null, endDate: dayjs.Dayjs | null) => void;\n  const clearDateCache = inject('clearDateCache') as () => void;\n\n  /**\n   * handle time line stretch\n   * @param e\n   * @param timeLine\n   * @param rowId\n   * @param direction\n   */\n  const startTimeLineStretch = (e: MouseEvent, timeLine: VisibleTimeLine, rowId: string, direction: 'left' | 'right') => {\n    if (disableStretch.value || timeLine.disableStretch) return;\n    let lastX = e.clientX;\n    const oldWidth = timeLine.width;\n    const minWidth = 4;\n    const wrapWidth = wrapRef.value!.offsetWidth;\n    const currentRowNode = rowNodeMap.value.get(rowId);\n    let invalidDistance = 0;\n    let startScrollX = 0;\n    movingTimeLine.value = timeLine;\n    movingTimeLineRowId.value = rowId;\n    e.stopPropagation();\n    const onMouseMove = (event: MouseEvent) => {\n      let currentX = event.clientX;\n      const diffX = currentX - lastX;\n\n      // keep stretch if timeline width is less than minWidth, it will produce invalid distance,\n      // then stretch on reverse direction, it will reduce invalid distance, stretch will be effected until invalid distance is 0\n      const perInvalidDistance = calcPerInvalidDistance(timeLine.width, diffX, minWidth, direction);\n      if (invalidDistance === 0) {\n        timeLineStretch(timeLine, rowId, diffX, minWidth, direction);\n      }\n      const nextInvalidDistance = invalidDistance + perInvalidDistance;\n      if ((nextInvalidDistance >= 0 && direction === 'left')\n      || (nextInvalidDistance <= 0 && direction === 'right')) {\n        invalidDistance += perInvalidDistance;\n      } else if ((invalidDistance > 0 && nextInvalidDistance < 0 && direction === 'left')\n      || (invalidDistance < 0 && nextInvalidDistance > 0 && direction === 'right')) {\n        timeLineStretch(timeLine, rowId, nextInvalidDistance, minWidth, direction);\n        invalidDistance = 0;\n      }\n\n      const scrollLeft = wrapRef.value!.scrollLeft;\n      const scrollDistance = 10;\n      if ((direction === 'left' && timeLine.translateX - scrollLeft <= edgeSpacing)\n      || (direction === 'right' && timeLine.translateX + timeLine.width - scrollLeft <= edgeSpacing)) {\n        if (diffX < 0) {\n          if (!timeLineMoving.value) {\n            timeLineMoving.value = true;\n            startScrollX = lastX;\n            closeEdgeScroll(-scrollDistance, (moveSpacing) => {\n              if (direction === 'right' && timeLine.width - scrollDistance < minWidth) {\n                timeLineMoving.value = false;\n                invalidDistance -= minWidth - timeLine.width + scrollDistance;\n              }\n              timeLineStretch(timeLine, rowId, moveSpacing, minWidth, direction);\n            });\n          }\n        } else if (currentX >= startScrollX) {\n          timeLineMoving.value = false;\n        }\n\n      } else if ((direction === 'right' && scrollLeft + wrapWidth <= timeLine.translateX + timeLine.width + edgeSpacing)\n       || (direction === 'left' && scrollLeft + wrapWidth <= timeLine.translateX + edgeSpacing)) {\n        if (diffX > 0) {\n          if (!timeLineMoving.value) {\n            timeLineMoving.value = true;\n            startScrollX = lastX;\n            closeEdgeScroll(scrollDistance, (moveSpacing) => {\n              if (direction === 'left' && timeLine.width - scrollDistance < minWidth) {\n                timeLineMoving.value = false;\n                invalidDistance += minWidth - timeLine.width + scrollDistance;\n              }\n              timeLineStretch(timeLine, rowId, moveSpacing, minWidth, direction);\n            });\n          }\n        } else if (currentX <= startScrollX) {\n          timeLineMoving.value = false;\n        }\n\n      } else {\n        timeLineMoving.value = false;\n      }\n      lastX = currentX;\n\n    };\n    const onMouseUp = () => {\n      timeLineMoving.value = false;\n      movingTimeLine.value = null;\n      movingTimeLineRowId.value = '';\n      clearDateCache();\n      if (timeLine.width !== oldWidth) {\n        // update row node date\n        freshRowNodeDateByTimeLine(rowId);\n        if (currentRowNode?.timeLineNodes) {\n          // if time line overlap, merge them\n          sortTimeLineNodes(currentRowNode.timeLineNodes);\n          currentRowNode.timeLineNodes = mergeOverlapTimeLine(currentRowNode.timeLineNodes);\n\n          // if timeline is a merge node, update all merged nodes' date\n          onTimeLineStretchChange(rowId, timeLine, direction);\n\n          // fresh visible time lines\n          visibleTimeLineMap.value.delete(rowId);\n          freshVisibleTimeLines(false);\n        }\n      }\n      window.removeEventListener('mousemove', onMouseMove);\n      window.removeEventListener('mouseup', onMouseUp);\n    };\n\n    window.addEventListener('mousemove', onMouseMove);\n    window.addEventListener('mouseup', onMouseUp);\n  };\n\n  /**\n   * calculate time line position, date and gantt min and max date\n   * @param timeLine\n   * @param rowId\n   * @param distance\n   * @param minWidth\n   * @param direction\n   * @returns\n   */\n  const timeLineStretch = (timeLine: VisibleTimeLine, rowId: string, distance: number, minWidth: number, direction: 'left' | 'right') => {\n    const oldWidth = timeLine.width;\n    if (direction === 'left') {\n      timeLine.width -= distance;\n    } else {\n      timeLine.width += distance;\n    }\n    if (timeLine.width < minWidth) {\n      timeLine.width = minWidth;\n    }\n    const diffWidth = oldWidth - timeLine.width;\n    if (direction === 'left') {\n      const nextStartDate = getDiffSecondByDistance(diffWidth, timeLine.startDate);\n      timeLine.timeLineNode.startDate = nextStartDate;\n      timeLine.startDate = nextStartDate;\n      if (getRound(timeLine.translateX) === edgeSpacing && diffWidth > 0) {\n        const { minStartDate } = getGanttMinAndMaxDate([rowId], true, false);\n        if (!minStartDate || nextStartDate.isBefore(minStartDate)) {\n          emitUpdateMinDate(nextStartDate);\n          timeLine.translateX = edgeSpacing;\n          updateParentTimeLine(rowId);\n          return;\n        } else if (nextStartDate.isAfter(minStartDate) || nextStartDate.isSame(minStartDate)) {\n          timeLine.translateX += getDistanceByDiffDate(minStartDate, nextStartDate);\n          emitUpdateMinDate(minStartDate);\n          updateParentTimeLine(rowId);\n          return;\n        }\n      }\n      timeLine.translateX += diffWidth;\n    } else {\n      const nextEndDate = getDiffSecondByDistance(-diffWidth, timeLine.endDate);\n      timeLine.timeLineNode.endDate = nextEndDate;\n      timeLine.endDate = nextEndDate;\n      if (getRound(timeLine.translateX + oldWidth + edgeSpacing) === getRound(ganttViewWidth.value) && diffWidth > 0) {\n        const { maxEndDate } = getGanttMinAndMaxDate([rowId], false, true);\n        if (!maxEndDate || nextEndDate.isAfter(maxEndDate)) {\n          emitUpdateMaxDate(nextEndDate);\n          updateParentTimeLine(rowId);\n          return;\n        } else if (nextEndDate.isBefore(maxEndDate) || nextEndDate.isSame(maxEndDate)) {\n          emitUpdateMaxDate(maxEndDate);\n        }\n      }\n    }\n    if (timeLine.translateX < edgeSpacing) {\n      emitUpdateMinDate(timeLine.startDate);\n      timeLine.translateX = edgeSpacing;\n    } else if (timeLine.translateX + timeLine.width + edgeSpacing > ganttViewWidth.value) {\n      emitUpdateMaxDate(timeLine.endDate);\n    }\n    updateParentTimeLine(rowId);\n    triggerRef(visibleTimeLineMap);\n  };\n\n  const calcPerInvalidDistance = (timeLineWidth: number, distance: number, minWidth: number, direction: 'left' | 'right') => {\n    if (direction === 'left') {\n      return minWidth - timeLineWidth + distance;\n    } else {\n      return timeLineWidth + distance - minWidth;\n    }\n  };\n\n  /**\n   * update merged time line nodes' date, and notice user\n   * @param rowId\n   * @param timeLine\n   * @param direction\n   */\n  const onTimeLineStretchChange = (rowId: string, timeLine: VisibleTimeLine, direction: 'left' | 'right') => {\n    const timeLineNode = timeLine.timeLineNode;\n    const timeLineIds: string[] = [timeLineNode.id];\n    const finalStartDate = direction === 'left' ? timeLineNode.startDate : null;\n    const finalEndDate = direction === 'right' ? timeLineNode.endDate : null;\n\n    if (timeLineNode.isMerge) {\n      const mergedTimeLineNodes = timeLineNode.mergedTimeLineNodes;\n      for (let mergedTimeLineNode of mergedTimeLineNodes!) {\n        if (direction === 'left') {\n          if (mergedTimeLineNode.startDate.isBefore(timeLineNode.startDate)) {\n            timeLineIds.push(mergedTimeLineNode.id);\n            mergedTimeLineNode.startDate = timeLineNode.startDate;\n          }\n        } else {\n          if (mergedTimeLineNode.endDate.isAfter(timeLineNode.endDate)) {\n            timeLineIds.push(mergedTimeLineNode.id);\n            mergedTimeLineNode.endDate = timeLineNode.endDate;\n          }\n        }\n      }\n    }\n    timeLineStretchChange(rowId, timeLineIds, finalStartDate, finalEndDate);\n  };\n  return {\n    startTimeLineStretch\n  };\n};"],"names":[],"mappings":"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"}