@ohkit/draggable-box 0.0.3 → 0.0.4
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/README.md +173 -1
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +1 -1
- package/dist/index.modern.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/types/index.d.ts +23 -9
- package/dist/types/type.d.ts +20 -0
- package/package.json +2 -2
- package/src/index.tsx +79 -22
- package/src/type.ts +21 -0
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/utils.ts","../src/constants.ts","../src/index.tsx"],"sourcesContent":["import {findParent} from '@ohkit/dom-helper';\n\n/**\n * 检查元素是否创建了新的定位上下文(包含块)\n * @param element 要检查的元素\n * @param includePosition 是否检查position属性(absolute/relative/fixed)\n */\nexport function isPositioningContextCreator(element: HTMLElement, includePosition: boolean): boolean {\n const style = window.getComputedStyle(element);\n const position = style.getPropertyValue('position');\n const transform = style.getPropertyValue('transform');\n const filter = style.getPropertyValue('filter');\n const perspective = style.getPropertyValue('perspective');\n const contain = style.getPropertyValue('contain');\n const willChange = style.getPropertyValue('will-change');\n \n return (includePosition && position !== 'static') || \n transform !== 'none' || \n filter !== 'none' || \n perspective !== 'none' ||\n contain.includes('paint') ||\n contain.includes('layout') ||\n contain.includes('strict') ||\n willChange.includes('transform') ||\n willChange.includes('perspective') ||\n willChange.includes('filter');\n}\n\n/**\n * 查找影响 fixed 定位的父元素\n * 当父元素有 transform/filter/perspective/contain/will-change 等属性时,fixed 定位会相对于该父元素\n */\nexport function findFixedPositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.documentElement;\n }\n const fixedPositionParent = findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, false);\n }, {excludeOwn: true}); // 没有找到,返回 window(通过 document.documentElement)\n return fixedPositionParent;\n}\n\n/**\n * 查找 absolute 定位的父元素\n * 查找最近的包含块创建者,包含所有可能影响absolute定位的属性\n */\nexport function findAbsolutePositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.body;\n }\n return findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, true);\n }, {excludeOwn: true});\n}\n\n/**\n * 获取容器的缩放比例\n * 通过比较元素的实际尺寸和 getBoundingClientRect 返回的尺寸来计算缩放比例\n */\nexport function getScaleRatio(dom?: HTMLElement | null): { scaleX: number; scaleY: number } {\n if (!dom) {\n return { scaleX: 1, scaleY: 1 };\n }\n // 通过比较 offsetWidth 和 getBoundingClientRect().width 来获取缩放比例\n const rect = dom.getBoundingClientRect();\n let scaleX = 1;\n let scaleY = 1;\n // 扩大{magnification}倍进行计算, 相当于保留小数点后4位\n const magnification = 10000;\n scaleX = dom.offsetWidth > 0 ? Math.round(rect.width / dom.offsetWidth * magnification) / magnification : 1;\n scaleY = dom.offsetHeight > 0 ? Math.round(rect.height / dom.offsetHeight * magnification) / magnification : 1;\n // console.log('rect.width dom.offsetWidth', rect.width, dom.offsetWidth);\n // console.log('rect.height dom.offsetHeight', rect.height, dom.offsetHeight);\n // console.log('scaleX', scaleX, 'scaleY', scaleY);\n return { scaleX, scaleY };\n}\n\n/**\n * 限制数值在指定范围内\n * \n * @param value 要限制的数值\n * @param min 最小值\n * @param max 最大值\n * @returns 限制后的数值,确保在 [min, max] 范围内\n */\nexport function clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), max);\n}\n\n\n/**\n * 检测当前环境是否支持触摸事件\n * \n * @returns 如果环境支持触摸事件返回 true,否则返回 false\n */\nexport function supportsTouchEvents() {\n return typeof window !== 'undefined' && ('ontouchstart' in window || navigator.maxTouchPoints > 0);\n};","\nexport const ValidPlacement = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const;\n","import React from 'react';\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {addEventListener, addClass} from '@ohkit/dom-helper';\nimport {findFixedPositionParent, findAbsolutePositionParent, getScaleRatio, clamp, supportsTouchEvents} from './utils';\nimport {ValidPlacement} from './constants';\nimport {DraggableBoxProps, DraggableBoxState} from './type';\n\nimport './style.scss';\n\nexport const c = p(\"ohkit-draggable-box__\");\nexport class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {\n static defaultProps: Partial<DraggableBoxProps> = {\n zIndex: 9999,\n offsetX: 20,\n offsetY: 20,\n placement: 'bottom-right',\n disabled: false,\n lockAxis: 'none',\n showDragArea: false,\n showDragAreaOverMoveDistanse: 5,\n positionMode: 'fixed',\n };\n\n constructor(props: DraggableBoxProps) {\n super(props);\n \n const { placement = 'bottom-right', offsetY = 20, offsetX = 20 } = props;\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n \n // 简化状态初始化\n this.state = {\n top: placementY === 'top' ? offsetY : undefined,\n bottom: placementY === 'bottom' ? offsetY : undefined,\n left: placementX === 'left' ? offsetX : undefined,\n right: placementX === 'right' ? offsetX : undefined,\n };\n }\n\n private prePositionMode: DraggableBoxProps['positionMode'];\n private preDraggerRef: HTMLElement | null = null;\n private container: HTMLElement | null = null;\n /**\n * 获取定位容器\n * 根据 positionMode 返回对应的定位父元素\n */\n private getContainer(useCache = true) {\n const { positionMode = 'fixed' } = this.props;\n if (!this.container || !useCache || this.prePositionMode !== positionMode || this.preDraggerRef !== this.draggerRef) {\n this.prePositionMode = positionMode;\n this.preDraggerRef = this.draggerRef;\n this.container = positionMode === 'fixed' \n ? findFixedPositionParent(this.draggerRef) \n : findAbsolutePositionParent(this.draggerRef);\n }\n return this.container;\n }\n\n /**\n * 获取容器的尺寸和位置信息\n */\n private getContainerRect() {\n const container = this.getContainer(false);\n if (!container) {\n return {\n width: window.innerWidth,\n height: window.innerHeight,\n left: 0,\n top: 0,\n scrollLeft: 0,\n scrollTop: 0,\n scrollerScrollLeft: 0,\n scrollerScrollTop: 0,\n borderLeftWidth: 0,\n borderTopWidth: 0\n };\n }\n const containerRect = container.getBoundingClientRect();\n \n // 获取容器的border宽度(仅 top, left 对坐标计算有影响)\n const containerStyle = window.getComputedStyle(container);\n const borderLeftWidth = parseFloat(containerStyle.borderLeftWidth) || 0;\n const borderTopWidth = parseFloat(containerStyle.borderTopWidth) || 0;\n const borderRightWidth = parseFloat(containerStyle.borderRightWidth) || 0;\n const borderBottomWidth = parseFloat(containerStyle.borderBottomWidth) || 0;\n const yScrollerWidth = container.offsetWidth - container.clientWidth - borderLeftWidth - borderRightWidth;\n const xScrollerHeight = container.offsetHeight - container.clientHeight - borderTopWidth - borderBottomWidth;\n // console.log('yScrollerWidth, xScrollerHeight', yScrollerWidth, xScrollerHeight);\n\n return {\n width: containerRect.width / this.cachedScaleX - borderLeftWidth - borderRightWidth - yScrollerWidth,\n height: containerRect.height / this.cachedScaleY - borderTopWidth - borderBottomWidth - xScrollerHeight,\n left: containerRect.left / this.cachedScaleX,\n top: containerRect.top / this.cachedScaleY,\n scrollLeft: container.scrollLeft,\n scrollTop: container.scrollTop,\n borderLeftWidth: borderLeftWidth,\n borderTopWidth: borderTopWidth,\n };\n }\n\n get dragBoxSize() {\n let width = 0;\n let height = 0;\n if (this.draggerRef) {\n width = this.draggerRef.offsetWidth;\n height = this.draggerRef.offsetHeight;\n }\n return {\n height,\n width\n };\n }\n\n get dragPositionBoundaries() {\n const { boundsX, boundsY, placement = 'bottom-right' } = this.props;\n const dragSize = this.dragBoxSize;\n const {width: containerWidth, height: containerHeight} = this.getContainerRect();\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n \n const defaultBounds = {\n minX: 0,\n maxX: Math.max(containerWidth - dragSize.width, 0),\n minY: 0,\n maxY: Math.max(containerHeight- dragSize.height, 0),\n };\n // 初始化边界\n let {minX, maxX, minY, maxY} = defaultBounds\n\n // 处理X轴边界\n if (boundsX) {\n const [minBound, maxBound] = boundsX;\n if (placementX === 'left') {\n // 左边位置:boundsX=[左边最小距离, 左边最大距离]\n if (minBound !== undefined) minX = Math.max(minX, minBound);\n if (maxBound !== undefined) maxX = Math.min(maxX, maxBound);\n } else {\n // 右边位置:boundsX=[右边最小距离, 右边最大距离]\n // 直接使用边界值作为right的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n }\n }\n }\n\n // 处理Y轴边界\n if (boundsY) {\n const [minBound, maxBound] = boundsY;\n \n if (placementY === 'top') {\n // 顶部位置:boundsY=[顶边最小距离, 顶边最大距离]\n if (minBound !== undefined) minY = Math.max(minY, minBound);\n if (maxBound !== undefined) maxY = Math.min(maxY, maxBound);\n } else {\n // 底部位置:boundsY=[底边最小距离, 底边最大距离]\n // 直接使用边界值作为bottom的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n }\n }\n }\n // 确保各个边界值在默认范围内\n minX = clamp(minX, defaultBounds.minX, defaultBounds.maxX);\n maxX = clamp(maxX, minX, defaultBounds.maxX);\n minY = clamp(minY, defaultBounds.minY, defaultBounds.maxY);\n maxY = clamp(maxY, minY, defaultBounds.maxY);\n\n return { minX, maxX, minY, maxY };\n }\n\n get curPositionKey() {\n let {placement} = this.props;\n if (!placement || !ValidPlacement.includes(placement)) {\n placement = 'bottom-right';\n }\n return placement.split('-') as ['top' | 'bottom', 'left' | 'right']; // [y, x]\n }\n\n get position() {\n const [y, x] = this.curPositionKey;\n const positionStyles: Record<string, string> = {};\n \n // 确保位置值存在且是有效的数字\n if (this.state[y] !== undefined) {\n positionStyles[y] = `${this.state[y]}px`;\n }\n if (this.state[x] !== undefined) {\n positionStyles[x] = `${this.state[x]}px`;\n }\n \n return positionStyles;\n }\n\n draggerRef: HTMLDivElement | null = null;\n\n isDragging = false;\n\n axisX?: number;\n axisY?: number;\n dX = 0;\n dY = 0;\n startTop = 0;\n startLeft = 0;\n\n // 缓存缩放比例,避免在 dragging 中频繁计算\n cachedScaleX = 1;\n cachedScaleY = 1;\n\n __moveDisposer?: () => void;\n __clickDisposer?: () => void;\n __bodyClassDisposer?: () => void;\n __upDisposer?: () => void;\n __resizeDisposer?: () => void;\n __preventScrollDisposer?: () => void;\n\n dragAreaRef: HTMLDivElement | null = null;\n\n reportStartPosition() {\n if (this.draggerRef) {\n // 获取缩放比例\n const { scaleX, scaleY } = getScaleRatio(this.getContainer());\n this.cachedScaleX = scaleX;\n this.cachedScaleY = scaleY;\n const { top, left } = this.draggerRef.getBoundingClientRect();\n const containerRect = this.getContainerRect();\n // console.log(containerRect, 'containerRect');\n \n // 计算相对于容器的位置,并除以缩放比例得到未缩放的坐标\n this.startTop = top / scaleY - containerRect.top + containerRect.scrollTop - containerRect.borderTopWidth;\n this.startLeft = left / scaleY - containerRect.left + containerRect.scrollLeft - containerRect.borderLeftWidth;\n }\n }\n\n enableDrag = (isTouch = false) => {\n this.reportStartPosition();\n this.__moveDisposer?.();\n this.__moveDisposer = addEventListener(isTouch && this.draggerRef ? this.draggerRef : document, isTouch ? 'touchmove' : 'mousemove', (evt) => {\n evt.stopPropagation();\n if (isTouch) {\n evt.preventDefault();\n }\n // INFO: 移动过程中禁止click事件\n if (!this.__clickDisposer) {\n const moveDistanse = Math.sqrt(Math.pow(this.dX, 2) + Math.pow(this.dY, 2));\n // INFO: 移动超过px?? 确保用户有真实的移动意愿,而不是手抖~~\n if (moveDistanse > (this.props.showDragAreaOverMoveDistanse || 5)) {\n this.__clickDisposer = addEventListener(\n document,\n 'click',\n (evt) => {\n evt.stopPropagation();\n },\n true\n );\n this.__bodyClassDisposer = addClass([document.body, this.draggerRef], c('moving')) || undefined;\n \n // 显示拖拽区域\n if (this.props.showDragArea && this.dragAreaRef) {\n this.showDragArea();\n }\n }\n }\n this.dragging(evt as TouchEvent | MouseEvent);\n }, {\n passive: !isTouch\n });\n\n this.__upDisposer?.();\n this.__upDisposer = addEventListener(\n document,\n 'mouseup',\n () => {\n this.endDrag();\n },\n true\n );\n };\n\n startDrag = (evt: React.MouseEvent<HTMLDivElement>) => {\n // 判断鼠标非右击才继续执行\n if (evt.nativeEvent.button === 2) {\n return;\n }\n this.axisX = evt.nativeEvent.pageX;\n this.axisY = evt.nativeEvent.pageY;\n if (!this.props.disabled) {\n this.enableDrag();\n }\n };\n\n dragging = (evt: MouseEvent | TouchEvent) => {\n this.isDragging = true;\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n \n // 使用缓存的缩放比例,避免频繁计算\n const scaleX = this.cachedScaleX;\n const scaleY = this.cachedScaleY;\n \n // 获取坐标\n let pageX: number, pageY: number;\n if (evt instanceof TouchEvent) {\n const touch = evt.touches[0];\n if (!touch) return;\n pageX = touch.pageX;\n pageY = touch.pageY;\n } else {\n pageX = evt.pageX;\n pageY = evt.pageY;\n }\n \n // 计算原始偏移量(需要除以缩放比例)\n this.dX = (pageX - (this.axisX || 0)) / scaleX;\n this.dY = (pageY - (this.axisY || 0)) / scaleY;\n \n // 应用方向锁定并计算变换值\n let translateX = this.dX;\n let translateY = this.dY;\n \n if (lockAxis === 'x') {\n translateY = 0; // 锁定Y方向\n } else if (lockAxis === 'y') {\n translateX = 0; // 锁定X方向\n }\n \n // 应用边界条件到允许移动的方向\n const potentialLeft = this.startLeft + translateX;\n const potentialTop = this.startTop + translateY;\n \n // X轴边界条件(在允许X轴移动时应用)\n if (lockAxis !== 'y') {\n if (potentialLeft < minX) {\n translateX = minX - this.startLeft;\n } else if (potentialLeft > maxX) {\n translateX = maxX - this.startLeft;\n }\n }\n \n // Y轴边界条件(在允许Y轴移动时应用)\n if (lockAxis !== 'x') {\n if (potentialTop < minY) {\n translateY = minY - this.startTop;\n } else if (potentialTop > maxY) {\n translateY = maxY - this.startTop;\n }\n }\n \n if (this.draggerRef) {\n this.draggerRef.style.transform = `translate(${translateX}px, ${translateY}px)`;\n }\n };\n\n startTouchDrag = (evt: React.TouchEvent<HTMLDivElement>) => {\n const touch = evt.touches[0];\n if (!touch) return;\n this.axisX = touch.pageX;\n this.axisY = touch.pageY;\n if (!this.props.disabled) {\n this.enableDrag(true);\n }\n };\n\n endDrag = () => {\n if (this.isDragging) {\n this.calcPosition();\n if (this.draggerRef) {\n this.draggerRef.style.transform = '';\n }\n \n // 隐藏拖拽区域\n if (this.props.showDragArea) {\n this.hideDragArea();\n }\n }\n\n if (this.__moveDisposer) {\n this.__moveDisposer();\n this.__moveDisposer = undefined;\n }\n if (this.__clickDisposer) {\n requestAnimationFrame(() => {\n if (this.__clickDisposer) {\n this.__clickDisposer();\n this.__clickDisposer = undefined;\n }\n });\n }\n if (this.__upDisposer) {\n this.__upDisposer();\n this.__upDisposer = undefined;\n }\n if (this.__bodyClassDisposer) {\n this.__bodyClassDisposer();\n this.__bodyClassDisposer = undefined;\n }\n\n this.isDragging = false;\n };\n\n showDragArea = () => {\n if (!this.props.showDragArea || !this.dragAreaRef) return;\n \n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const dragSize = this.dragBoxSize;\n \n // 重置样式\n this.dragAreaRef.style.border = '1px dashed var(--ohkit-color-primary, #1890ff)';\n this.dragAreaRef.style.backgroundColor = 'rgba(173, 216, 230, 0.2)'; // 淡透蓝色\n \n if (lockAxis === 'x') {\n // 锁定Y方向,显示为水平虚线区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = '2px'; // 更细的虚线高度\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${this.startTop + dragSize.height / 2}px`;\n } else if (lockAxis === 'y') {\n // 锁定X方向,显示为垂直虚线区域\n this.dragAreaRef.style.width = '2px'; // 更细的虚线宽度\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${this.startLeft + dragSize.width / 2}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n } else {\n // 自由拖拽,显示完整区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n }\n \n this.dragAreaRef.style.display = 'block';\n };\n\n hideDragArea = () => {\n if (this.dragAreaRef) {\n this.dragAreaRef.style.display = 'none';\n }\n };\n calcPosition = () => {\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const {height, width} = this.getContainerRect();\n \n // 计算新的位置\n let newTop = this.startTop;\n let newLeft = this.startLeft;\n \n if (lockAxis !== 'y') {\n newLeft += this.dX;\n }\n if (lockAxis !== 'x') {\n newTop += this.dY;\n }\n \n // 应用边界限制\n const realTop = clamp(newTop, minY, maxY);\n const realLeft = clamp(newLeft, minX, maxX);\n const realBottom = height - realTop - this.dragBoxSize.height;\n const realRight = width - realLeft - this.dragBoxSize.width;\n if (realTop !== this.state.top || realLeft !== this.state.left || this.state.bottom !== realBottom || this.state.right !== realRight) {\n // console.log(minY, maxY, this.startTop, this.dY, newTop, realTop, 'minY, maxY, this.startTop, this.dY, newTop, realTop --- calcPosition y');\n // console.log(minX, maxX, this.startLeft, this.dX, newLeft, realLeft, 'minX, maxX, this.startLeft, this.dX, newLeft, realLeft ---calcPosition x');\n this.setState({\n top: realTop,\n left: realLeft,\n bottom: realBottom,\n right: realRight\n });\n }\n this.startTop = realTop;\n this.startLeft = realLeft;\n this.dX = this.dY = 0;\n };\n\n\n componentDidMount() {\n // 检查初始位置是否在边界范围内,如果不在则修正\n this.reportStartPosition();\n this.calcPosition();\n \n this.__resizeDisposer = addEventListener(window, 'resize', () => {\n this.calcPosition();\n });\n\n // 触屏设备时,阻止拖拽时滚动页面\n if (supportsTouchEvents() && this.draggerRef) {\n this.__preventScrollDisposer = addEventListener(this.draggerRef, 'touchmove', (evt) => {\n evt.preventDefault();\n });\n }\n }\n\n componentWillUnmount() {\n this.__resizeDisposer?.();\n this.__bodyClassDisposer?.();\n this.__moveDisposer?.();\n this.__clickDisposer?.();\n this.__upDisposer?.();\n this.__preventScrollDisposer?.();\n }\n\n render() {\n const { className, zIndex, children, showDragArea, positionMode = 'fixed' } = this.props;\n const { startDrag, startTouchDrag, endDrag } = this;\n const stl = {\n zIndex,\n ...this.position,\n position: positionMode\n };\n return (\n <>\n {showDragArea && (\n <div\n className={c('drag-area')}\n ref={(r) => {\n this.dragAreaRef = r;\n }}\n style={{\n display: 'none',\n position: positionMode,\n backgroundColor: 'rgba(173, 216, 230, 0.2)', // 淡透蓝色\n border: '1px dashed var(--ohkit-color-primary, #1890ff)',\n pointerEvents: 'none',\n zIndex: (zIndex || 9999) - 1,\n boxSizing: 'border-box',\n borderRadius: this.props.lockAxis !== 'none' ? '2px' : '0',\n }}\n />\n )}\n <div\n className={cx(c('container'), className)}\n style={stl}\n ref={(r) => {\n this.draggerRef = r;\n }}\n onMouseDownCapture={startDrag}\n onMouseUpCapture={endDrag}\n onTouchStartCapture={startTouchDrag}\n onTouchEndCapture={endDrag}\n >\n {children}\n </div>\n </>\n );\n }\n}\n\nexport default DraggableBox;"],"names":["isPositioningContextCreator","element","includePosition","style","window","getComputedStyle","position","getPropertyValue","transform","filter","perspective","contain","willChange","includes","clamp","value","min","max","Math","ValidPlacement","c","p","prefixClassname","DraggableBox","_React$Component","props","_this","call","this","prePositionMode","preDraggerRef","container","draggerRef","isDragging","axisX","axisY","dX","dY","startTop","startLeft","cachedScaleX","cachedScaleY","__moveDisposer","__clickDisposer","__bodyClassDisposer","__upDisposer","__resizeDisposer","__preventScrollDisposer","dragAreaRef","enableDrag","isTouch","reportStartPosition","addEventListener","document","evt","stopPropagation","preventDefault","sqrt","pow","showDragAreaOverMoveDistanse","addClass","body","undefined","showDragArea","dragging","passive","endDrag","startDrag","nativeEvent","button","pageX","pageY","disabled","lockAxis","_this$dragPositionBou","dragPositionBoundaries","minX","maxX","minY","maxY","scaleY","TouchEvent","touch","touches","translateX","translateY","potentialLeft","potentialTop","startTouchDrag","calcPosition","hideDragArea","requestAnimationFrame","_this$dragPositionBou2","dragSize","dragBoxSize","border","backgroundColor","width","height","left","top","display","_this$dragPositionBou3","_this$getContainerRec","getContainerRect","newTop","newLeft","realTop","realLeft","realBottom","realRight","state","bottom","right","setState","_props$placement","placement","_props$offsetY","offsetY","_props$offsetX","offsetX","_placement$split","split","placementY","placementX","_proto","prototype","getContainer","useCache","dom","_this$props$positionM","positionMode","findParent","parent","excludeOwn","documentElement","findAbsolutePositionParent","innerWidth","innerHeight","scrollLeft","scrollTop","scrollerScrollLeft","scrollerScrollTop","borderLeftWidth","borderTopWidth","containerRect","getBoundingClientRect","containerStyle","parseFloat","borderRightWidth","borderBottomWidth","offsetWidth","clientWidth","offsetHeight","clientHeight","_getScaleRatio","scaleX","rect","magnification","round","getScaleRatio","_this$draggerRef$getB","componentDidMount","_this2","navigator","maxTouchPoints","componentWillUnmount","_this$__resizeDispose","_this$__bodyClassDisp","_this$__moveDisposer","_this$__clickDisposer","_this$__upDisposer","_this$__preventScroll","render","_this3","_this$props","className","zIndex","children","_this$props$positionM2","stl","_extends","React","createElement","Fragment","ref","r","pointerEvents","boxSizing","borderRadius","cx","onMouseDownCapture","onMouseUpCapture","onTouchStartCapture","onTouchEndCapture","key","get","_this$props2","boundsX","boundsY","_this$props2$placemen","_this$getContainerRec2","containerWidth","containerHeight","_placement$split2","defaultBounds","minBound","maxBound","_this$curPositionKey","curPositionKey","y","x","positionStyles","Component","defaultProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/utils.ts","../src/constants.ts","../src/index.tsx"],"sourcesContent":["import {findParent} from '@ohkit/dom-helper';\n\n/**\n * 检查元素是否创建了新的定位上下文(包含块)\n * @param element 要检查的元素\n * @param includePosition 是否检查position属性(absolute/relative/fixed)\n */\nexport function isPositioningContextCreator(element: HTMLElement, includePosition: boolean): boolean {\n const style = window.getComputedStyle(element);\n const position = style.getPropertyValue('position');\n const transform = style.getPropertyValue('transform');\n const filter = style.getPropertyValue('filter');\n const perspective = style.getPropertyValue('perspective');\n const contain = style.getPropertyValue('contain');\n const willChange = style.getPropertyValue('will-change');\n \n return (includePosition && position !== 'static') || \n transform !== 'none' || \n filter !== 'none' || \n perspective !== 'none' ||\n contain.includes('paint') ||\n contain.includes('layout') ||\n contain.includes('strict') ||\n willChange.includes('transform') ||\n willChange.includes('perspective') ||\n willChange.includes('filter');\n}\n\n/**\n * 查找影响 fixed 定位的父元素\n * 当父元素有 transform/filter/perspective/contain/will-change 等属性时,fixed 定位会相对于该父元素\n */\nexport function findFixedPositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.documentElement;\n }\n const fixedPositionParent = findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, false);\n }, {excludeOwn: true}); // 没有找到,返回 window(通过 document.documentElement)\n return fixedPositionParent;\n}\n\n/**\n * 查找 absolute 定位的父元素\n * 查找最近的包含块创建者,包含所有可能影响absolute定位的属性\n */\nexport function findAbsolutePositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.body;\n }\n return findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, true);\n }, {excludeOwn: true});\n}\n\n/**\n * 获取容器的缩放比例\n * 通过比较元素的实际尺寸和 getBoundingClientRect 返回的尺寸来计算缩放比例\n */\nexport function getScaleRatio(dom?: HTMLElement | null): { scaleX: number; scaleY: number } {\n if (!dom) {\n return { scaleX: 1, scaleY: 1 };\n }\n // 通过比较 offsetWidth 和 getBoundingClientRect().width 来获取缩放比例\n const rect = dom.getBoundingClientRect();\n let scaleX = 1;\n let scaleY = 1;\n // 扩大{magnification}倍进行计算, 相当于保留小数点后4位\n const magnification = 10000;\n scaleX = dom.offsetWidth > 0 ? Math.round(rect.width / dom.offsetWidth * magnification) / magnification : 1;\n scaleY = dom.offsetHeight > 0 ? Math.round(rect.height / dom.offsetHeight * magnification) / magnification : 1;\n // console.log('rect.width dom.offsetWidth', rect.width, dom.offsetWidth);\n // console.log('rect.height dom.offsetHeight', rect.height, dom.offsetHeight);\n // console.log('scaleX', scaleX, 'scaleY', scaleY);\n return { scaleX, scaleY };\n}\n\n/**\n * 限制数值在指定范围内\n * \n * @param value 要限制的数值\n * @param min 最小值\n * @param max 最大值\n * @returns 限制后的数值,确保在 [min, max] 范围内\n */\nexport function clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), max);\n}\n\n\n/**\n * 检测当前环境是否支持触摸事件\n * \n * @returns 如果环境支持触摸事件返回 true,否则返回 false\n */\nexport function supportsTouchEvents() {\n return typeof window !== 'undefined' && ('ontouchstart' in window || navigator.maxTouchPoints > 0);\n};","\nexport const ValidPlacement = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const;\n","import React from 'react';\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {addEventListener, addClass} from '@ohkit/dom-helper';\nimport {findFixedPositionParent, findAbsolutePositionParent, getScaleRatio, clamp, supportsTouchEvents} from './utils';\nimport {ValidPlacement} from './constants';\nimport {DraggableBoxProps, DraggableBoxState} from './type';\n\nimport './style.scss';\n\nexport * from './utils';\nexport * from './type';\nexport const c = p(\"ohkit-draggable-box__\");\nexport class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {\n static defaultProps: Partial<DraggableBoxProps> = {\n zIndex: 9999,\n offsetX: 20,\n offsetY: 20,\n placement: 'bottom-right',\n disabled: false,\n lockAxis: 'none',\n showDragArea: false,\n showDragAreaOverMoveDistanse: 5,\n positionMode: 'fixed',\n };\n\n constructor(props: DraggableBoxProps) {\n super(props);\n const { offsetX, offsetY } = this.props;\n this.state = this.formatState({offsetX, offsetY});\n }\n\n private formatState({offsetX = DraggableBox.defaultProps.offsetX, offsetY = DraggableBox.defaultProps.offsetY} = {}) {\n const { placement = 'bottom-right' } = this.props;\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n const newState = {\n top: placementY === 'top' ? offsetY : undefined,\n bottom: placementY === 'bottom' ? offsetY : undefined,\n left: placementX === 'left' ? offsetX : undefined,\n right: placementX === 'right' ? offsetX : undefined,\n }\n return newState;\n }\n\n private prePositionMode: DraggableBoxProps['positionMode'];\n private preDraggerRef: HTMLElement | null = null;\n private container: HTMLElement | null = null;\n /**\n * 获取定位容器\n * 根据 positionMode 返回对应的定位父元素\n */\n private getContainer(useCache = true) {\n const { positionMode = 'fixed' } = this.props;\n if (!this.container || !useCache || this.prePositionMode !== positionMode || this.preDraggerRef !== this.draggerRef) {\n this.prePositionMode = positionMode;\n this.preDraggerRef = this.draggerRef;\n this.container = positionMode === 'fixed' \n ? findFixedPositionParent(this.draggerRef) \n : findAbsolutePositionParent(this.draggerRef);\n }\n return this.container;\n }\n\n /**\n * 获取容器的尺寸和位置信息\n */\n private getContainerRect() {\n const container = this.getContainer(false);\n if (!container) {\n return {\n width: document.documentElement.clientWidth, // window.innerWidth, 避免滚动条影响计算\n height: document.documentElement.clientHeight, // window.innerHeight, 避免滚动条影响计算\n left: 0,\n top: 0,\n scrollLeft: 0,\n scrollTop: 0,\n scrollerScrollLeft: 0,\n scrollerScrollTop: 0,\n borderLeftWidth: 0,\n borderTopWidth: 0\n };\n }\n const containerRect = container.getBoundingClientRect();\n \n // 获取容器的border宽度(仅 top, left 对坐标计算有影响)\n const containerStyle = window.getComputedStyle(container);\n const borderLeftWidth = parseFloat(containerStyle.borderLeftWidth) || 0;\n const borderTopWidth = parseFloat(containerStyle.borderTopWidth) || 0;\n const borderRightWidth = parseFloat(containerStyle.borderRightWidth) || 0;\n const borderBottomWidth = parseFloat(containerStyle.borderBottomWidth) || 0;\n const yScrollerWidth = container.offsetWidth - container.clientWidth - borderLeftWidth - borderRightWidth;\n const xScrollerHeight = container.offsetHeight - container.clientHeight - borderTopWidth - borderBottomWidth;\n // console.log('yScrollerWidth, xScrollerHeight', yScrollerWidth, xScrollerHeight);\n\n return {\n width: containerRect.width / this.cachedScaleX - borderLeftWidth - borderRightWidth - yScrollerWidth,\n height: containerRect.height / this.cachedScaleY - borderTopWidth - borderBottomWidth - xScrollerHeight,\n left: containerRect.left / this.cachedScaleX,\n top: containerRect.top / this.cachedScaleY,\n scrollLeft: container.scrollLeft,\n scrollTop: container.scrollTop,\n borderLeftWidth: borderLeftWidth,\n borderTopWidth: borderTopWidth,\n };\n }\n\n get dragBoxSize() {\n let width = 0;\n let height = 0;\n if (this.draggerRef) {\n width = this.draggerRef.offsetWidth;\n height = this.draggerRef.offsetHeight;\n }\n return {\n height,\n width\n };\n }\n\n get dragPositionBoundaries() {\n const { boundsX, boundsY, placement = 'bottom-right' } = this.props;\n const dragSize = this.dragBoxSize;\n const {width: containerWidth, height: containerHeight} = this.getContainerRect();\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n \n const defaultBounds = {\n minX: 0,\n maxX: Math.max(containerWidth - dragSize.width, 0),\n minY: 0,\n maxY: Math.max(containerHeight- dragSize.height, 0),\n };\n // 初始化边界\n let {minX, maxX, minY, maxY} = defaultBounds\n\n // 处理X轴边界\n if (boundsX) {\n const [minBound, maxBound] = boundsX;\n if (placementX === 'left') {\n // 左边位置:boundsX=[左边最小距离, 左边最大距离]\n if (minBound !== undefined) minX = Math.max(minX, minBound);\n if (maxBound !== undefined) maxX = Math.min(maxX, maxBound);\n } else {\n // 右边位置:boundsX=[右边最小距离, 右边最大距离]\n // 直接使用边界值作为right的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n }\n }\n }\n\n // 处理Y轴边界\n if (boundsY) {\n const [minBound, maxBound] = boundsY;\n \n if (placementY === 'top') {\n // 顶部位置:boundsY=[顶边最小距离, 顶边最大距离]\n if (minBound !== undefined) minY = Math.max(minY, minBound);\n if (maxBound !== undefined) maxY = Math.min(maxY, maxBound);\n } else {\n // 底部位置:boundsY=[底边最小距离, 底边最大距离]\n // 直接使用边界值作为bottom的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n }\n }\n }\n // 确保各个边界值在默认范围内\n minX = clamp(minX, defaultBounds.minX, defaultBounds.maxX);\n maxX = clamp(maxX, minX, defaultBounds.maxX);\n minY = clamp(minY, defaultBounds.minY, defaultBounds.maxY);\n maxY = clamp(maxY, minY, defaultBounds.maxY);\n\n return { minX, maxX, minY, maxY };\n }\n\n get curPositionKey() {\n let {placement} = this.props;\n if (!placement || !ValidPlacement.includes(placement)) {\n placement = 'bottom-right';\n }\n return placement.split('-') as ['top' | 'bottom', 'left' | 'right']; // [y, x]\n }\n\n get position() {\n const [y, x] = this.curPositionKey;\n const positionStyles: Record<string, string> = {};\n \n // 确保位置值存在且是有效的数字\n if (this.state[y] !== undefined) {\n positionStyles[y] = `${this.state[y]}px`;\n }\n if (this.state[x] !== undefined) {\n positionStyles[x] = `${this.state[x]}px`;\n }\n \n return positionStyles;\n }\n\n draggerRef: HTMLDivElement | null = null;\n\n isDragging = false;\n\n axisX?: number;\n axisY?: number;\n dX = 0;\n dY = 0;\n startTop = 0;\n startLeft = 0;\n startBottom = 0;\n startRight = 0;\n translateX = 0;\n translateY = 0;\n\n // 缓存缩放比例,避免在 dragging 中频繁计算\n cachedScaleX = 1;\n cachedScaleY = 1;\n\n private __moveDisposer?: () => void;\n private __clickDisposer?: () => void;\n private __bodyClassDisposer?: () => void;\n private __upDisposer?: () => void;\n private __resizeDisposer?: () => void;\n private __preventScrollDisposer?: () => void;\n\n dragAreaRef: HTMLDivElement | null = null;\n\n private reportStartPosition() {\n if (this.draggerRef) {\n // 获取缩放比例\n const { scaleX, scaleY } = getScaleRatio(this.getContainer());\n this.cachedScaleX = scaleX;\n this.cachedScaleY = scaleY;\n const { top, left } = this.draggerRef.getBoundingClientRect();\n const containerRect = this.getContainerRect();\n // console.log(containerRect, 'containerRect');\n \n // 计算相对于容器的位置,并除以缩放比例得到未缩放的坐标\n this.startTop = top / scaleY - containerRect.top + containerRect.scrollTop - containerRect.borderTopWidth;\n this.startLeft = left / scaleY - containerRect.left + containerRect.scrollLeft - containerRect.borderLeftWidth;\n this.startBottom = containerRect.height - this.startTop - this.dragBoxSize.height;\n this.startRight = containerRect.width - this.startLeft - this.dragBoxSize.width;\n }\n }\n\n enableDrag = (isTouch = false) => {\n this.reportStartPosition();\n this.__moveDisposer?.();\n this.__moveDisposer = addEventListener(isTouch && this.draggerRef ? this.draggerRef : document, isTouch ? 'touchmove' : 'mousemove', (evt) => {\n evt.stopPropagation();\n if (isTouch) {\n evt.preventDefault();\n }\n // INFO: 移动过程中禁止click事件\n if (!this.__clickDisposer) {\n const moveDistanse = Math.sqrt(Math.pow(this.dX, 2) + Math.pow(this.dY, 2));\n // INFO: 移动超过px?? 确保用户有真实的移动意愿,而不是手抖~~\n if (moveDistanse > (this.props.showDragAreaOverMoveDistanse || 5)) {\n this.__clickDisposer = addEventListener(\n document,\n 'click',\n (evt) => {\n evt.stopPropagation();\n },\n true\n );\n this.__bodyClassDisposer = addClass([document.body, this.draggerRef], c('moving')) || undefined;\n \n // 显示拖拽区域\n if (this.props.showDragArea && this.dragAreaRef) {\n this.showDragArea();\n }\n }\n }\n // 调用拖拽开始回调\n if (!this.isDragging && this.props.onDragStart) {\n const positionChange = {\n top: this.startTop,\n left: this.startLeft,\n bottom: this.startBottom,\n right: this.startRight,\n diffX: 0,\n diffY: 0\n };\n this.props.onDragStart(positionChange);\n }\n this.dragging(evt as TouchEvent | MouseEvent);\n }, {\n passive: !isTouch\n });\n\n this.__upDisposer?.();\n this.__upDisposer = addEventListener(\n document,\n 'mouseup',\n () => {\n this.endDrag();\n },\n true\n );\n };\n\n startDrag = (evt: React.MouseEvent<HTMLDivElement>) => {\n // 判断鼠标非右击才继续执行\n if (evt.nativeEvent.button === 2) {\n return;\n }\n this.axisX = evt.nativeEvent.pageX;\n this.axisY = evt.nativeEvent.pageY;\n if (!this.props.disabled) {\n this.enableDrag();\n }\n };\n\n dragging = (evt: MouseEvent | TouchEvent) => {\n this.isDragging = true;\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n \n // 使用缓存的缩放比例,避免频繁计算\n const scaleX = this.cachedScaleX;\n const scaleY = this.cachedScaleY;\n \n // 获取坐标\n let pageX: number, pageY: number;\n if (evt instanceof TouchEvent) {\n const touch = evt.touches[0];\n if (!touch) return;\n pageX = touch.pageX;\n pageY = touch.pageY;\n } else {\n pageX = evt.pageX;\n pageY = evt.pageY;\n }\n \n // 计算原始偏移量(需要除以缩放比例)\n this.dX = (pageX - (this.axisX || 0)) / scaleX;\n this.dY = (pageY - (this.axisY || 0)) / scaleY;\n \n // 应用方向锁定并计算变换值\n let translateX = this.dX;\n let translateY = this.dY;\n \n if (lockAxis === 'x') {\n translateY = 0; // 锁定Y方向\n } else if (lockAxis === 'y') {\n translateX = 0; // 锁定X方向\n }\n \n // 应用边界条件到允许移动的方向\n const potentialLeft = this.startLeft + translateX;\n const potentialTop = this.startTop + translateY;\n \n // X轴边界条件(在允许X轴移动时应用)\n if (lockAxis !== 'y') {\n if (potentialLeft < minX) {\n translateX = minX - this.startLeft;\n } else if (potentialLeft > maxX) {\n translateX = maxX - this.startLeft;\n }\n }\n \n // Y轴边界条件(在允许Y轴移动时应用)\n if (lockAxis !== 'x') {\n if (potentialTop < minY) {\n translateY = minY - this.startTop;\n } else if (potentialTop > maxY) {\n translateY = maxY - this.startTop;\n }\n }\n if (this.translateX === translateX && this.translateY === translateY) {\n return;\n }\n\n // 调用拖拽中回调\n if (this.props.onDrag) {\n const positionChange = {\n top: this.startTop + translateY,\n left: this.startLeft + translateX,\n bottom: this.startBottom - translateY,\n right: this.startRight - translateX,\n diffX: translateX,\n diffY: translateY\n };\n this.props.onDrag(positionChange);\n }\n \n if (this.draggerRef) {\n this.draggerRef.style.transform = `translate(${translateX}px, ${translateY}px)`;\n }\n this.translateX = translateX;\n this.translateY = translateY;\n };\n\n startTouchDrag = (evt: React.TouchEvent<HTMLDivElement>) => {\n const touch = evt.touches[0];\n if (!touch) return;\n this.axisX = touch.pageX;\n this.axisY = touch.pageY;\n if (!this.props.disabled) {\n this.enableDrag(true);\n }\n };\n\n endDrag = () => {\n if (this.isDragging) {\n const positionChange = this.calcPosition();\n // 调用拖拽结束回调\n this.props.onDragEnd?.(positionChange);\n if (this.draggerRef) {\n this.draggerRef.style.transform = '';\n }\n \n // 隐藏拖拽区域\n if (this.props.showDragArea) {\n this.hideDragArea();\n }\n }\n\n if (this.__moveDisposer) {\n this.__moveDisposer();\n this.__moveDisposer = undefined;\n }\n if (this.__clickDisposer) {\n requestAnimationFrame(() => {\n if (this.__clickDisposer) {\n this.__clickDisposer();\n this.__clickDisposer = undefined;\n }\n });\n }\n if (this.__upDisposer) {\n this.__upDisposer();\n this.__upDisposer = undefined;\n }\n if (this.__bodyClassDisposer) {\n this.__bodyClassDisposer();\n this.__bodyClassDisposer = undefined;\n }\n\n this.isDragging = false;\n };\n\n showDragArea = () => {\n if (!this.props.showDragArea || !this.dragAreaRef) return;\n \n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const dragSize = this.dragBoxSize;\n \n // 重置样式\n this.dragAreaRef.style.border = '1px dashed var(--ohkit-color-primary, #1890ff)';\n this.dragAreaRef.style.backgroundColor = 'rgba(173, 216, 230, 0.2)'; // 淡透蓝色\n \n if (lockAxis === 'x') {\n // 锁定Y方向,显示为水平虚线区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = '2px'; // 更细的虚线高度\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${this.startTop + dragSize.height / 2}px`;\n } else if (lockAxis === 'y') {\n // 锁定X方向,显示为垂直虚线区域\n this.dragAreaRef.style.width = '2px'; // 更细的虚线宽度\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${this.startLeft + dragSize.width / 2}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n } else {\n // 自由拖拽,显示完整区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n }\n \n this.dragAreaRef.style.display = 'block';\n };\n\n hideDragArea = () => {\n if (this.dragAreaRef) {\n this.dragAreaRef.style.display = 'none';\n }\n };\n calcPosition = () => {\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const {height, width} = this.getContainerRect();\n \n // 计算新的位置\n let newTop = this.startTop;\n let newLeft = this.startLeft;\n \n if (lockAxis !== 'y') {\n newLeft += this.dX;\n }\n if (lockAxis !== 'x') {\n newTop += this.dY;\n }\n \n // 应用边界限制\n const realTop = clamp(newTop, minY, maxY);\n const realLeft = clamp(newLeft, minX, maxX);\n const realBottom = height - realTop - this.dragBoxSize.height;\n const realRight = width - realLeft - this.dragBoxSize.width;\n if (realTop !== this.state.top || realLeft !== this.state.left || this.state.bottom !== realBottom || this.state.right !== realRight) {\n this.setState({\n top: realTop,\n left: realLeft,\n bottom: realBottom,\n right: realRight\n });\n }\n const positionChange = {\n top: realTop,\n left: realLeft,\n bottom: realBottom,\n right: realRight,\n diffX: realLeft - this.startLeft,\n diffY: realTop - this.startTop\n };\n this.startTop = realTop;\n this.startLeft = realLeft;\n this.startBottom = realBottom;\n this.startRight = realRight;\n this.dX = this.dY = 0;\n return positionChange;\n };\n\n // 更新状态并计算位置 (外部可以调用)\n updateState = ({offsetX, offsetY}: Pick<DraggableBoxProps, 'offsetX' | 'offsetY'> = {}) => {\n this.setState(this.formatState({offsetX, offsetY}), () => {\n this.reportStartPosition();\n this.calcPosition();\n });\n }\n\n componentDidMount() {\n // 检查初始位置是否在边界范围内,如果不在则修正\n this.reportStartPosition();\n this.calcPosition();\n \n this.__resizeDisposer = addEventListener(window, 'resize', () => {\n this.calcPosition();\n });\n\n // 触屏设备时,阻止拖拽时滚动页面\n if (supportsTouchEvents() && this.draggerRef) {\n this.__preventScrollDisposer = addEventListener(this.draggerRef, 'touchmove', (evt) => {\n evt.preventDefault();\n });\n }\n }\n\n componentWillUnmount() {\n this.__resizeDisposer?.();\n this.__bodyClassDisposer?.();\n this.__moveDisposer?.();\n this.__clickDisposer?.();\n this.__upDisposer?.();\n this.__preventScrollDisposer?.();\n }\n\n render() {\n const { className, zIndex, children, showDragArea, positionMode = 'fixed' } = this.props;\n const { startDrag, startTouchDrag, endDrag } = this;\n const stl = {\n zIndex,\n ...this.position,\n position: positionMode\n };\n return (\n <React.Fragment>\n {showDragArea && (\n <div\n className={c('drag-area')}\n ref={(r) => {\n this.dragAreaRef = r;\n }}\n style={{\n display: 'none',\n position: positionMode,\n backgroundColor: 'rgba(173, 216, 230, 0.2)', // 淡透蓝色\n border: '1px dashed var(--ohkit-color-primary, #1890ff)',\n pointerEvents: 'none',\n zIndex: (zIndex || 9999) - 1,\n boxSizing: 'border-box',\n borderRadius: this.props.lockAxis !== 'none' ? '2px' : '0',\n }}\n />\n )}\n <div\n className={cx(c('container'), className)}\n style={stl}\n ref={(r) => {\n this.draggerRef = r;\n }}\n onMouseDownCapture={startDrag}\n onMouseUpCapture={endDrag}\n onTouchStartCapture={startTouchDrag}\n onTouchEndCapture={endDrag}\n >\n {children}\n </div>\n </React.Fragment>\n );\n }\n}\n"],"names":["isPositioningContextCreator","element","includePosition","style","window","getComputedStyle","position","getPropertyValue","transform","filter","perspective","contain","willChange","includes","findFixedPositionParent","dom","findParent","parent","excludeOwn","document","documentElement","findAbsolutePositionParent","body","getScaleRatio","scaleX","scaleY","rect","getBoundingClientRect","magnification","offsetWidth","Math","round","width","offsetHeight","height","clamp","value","min","max","supportsTouchEvents","navigator","maxTouchPoints","ValidPlacement","c","p","DraggableBox","_React$Component","props","_this","call","this","prePositionMode","preDraggerRef","container","draggerRef","isDragging","axisX","axisY","dX","dY","startTop","startLeft","startBottom","startRight","translateX","translateY","cachedScaleX","cachedScaleY","__moveDisposer","__clickDisposer","__bodyClassDisposer","__upDisposer","__resizeDisposer","__preventScrollDisposer","dragAreaRef","enableDrag","isTouch","reportStartPosition","addEventListener","evt","stopPropagation","preventDefault","sqrt","pow","showDragAreaOverMoveDistanse","addClass","undefined","showDragArea","onDragStart","top","left","bottom","right","diffX","diffY","dragging","passive","endDrag","startDrag","nativeEvent","button","pageX","pageY","disabled","lockAxis","_this$dragPositionBou","dragPositionBoundaries","minX","maxX","minY","maxY","TouchEvent","touch","touches","potentialLeft","potentialTop","onDrag","startTouchDrag","positionChange","calcPosition","onDragEnd","hideDragArea","requestAnimationFrame","_this$dragPositionBou2","dragSize","dragBoxSize","border","backgroundColor","display","_this$dragPositionBou3","_this$getContainerRec","getContainerRect","newTop","newLeft","realTop","realLeft","realBottom","realRight","state","setState","updateState","_temp","_ref","formatState","offsetX","offsetY","_this$props","_proto","prototype","_temp2","_ref2","_ref2$offsetX","defaultProps","_ref2$offsetY","_this$props$placement","placement","_placement$split","split","placementY","placementX","getContainer","useCache","_this$props$positionM","positionMode","clientWidth","clientHeight","scrollLeft","scrollTop","scrollerScrollLeft","scrollerScrollTop","borderLeftWidth","borderTopWidth","containerRect","containerStyle","parseFloat","borderRightWidth","borderBottomWidth","_getScaleRatio","_this$draggerRef$getB","componentDidMount","_this2","componentWillUnmount","_this$__resizeDispose","_this$__bodyClassDisp","_this$__moveDisposer","_this$__clickDisposer","_this$__upDisposer","_this$__preventScroll","render","_this3","_this$props2","className","zIndex","children","_this$props2$position","stl","_extends","React","createElement","Fragment","ref","r","pointerEvents","boxSizing","borderRadius","cx","onMouseDownCapture","onMouseUpCapture","onTouchStartCapture","onTouchEndCapture","key","get","_this$props3","boundsX","boundsY","_this$props3$placemen","_this$getContainerRec2","containerWidth","containerHeight","_placement$split2","defaultBounds","minBound","maxBound","_this$curPositionKey","curPositionKey","y","x","positionStyles","Component"],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,10 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import { classNames as cx } from "@ohkit/prefix-classname";
|
|
3
3
|
import { DraggableBoxProps, DraggableBoxState } from './type';
|
|
4
4
|
import './style.scss';
|
|
5
|
+
export * from './utils';
|
|
6
|
+
export * from './type';
|
|
5
7
|
export declare const c: (...arg: cx.ArgumentArray) => string;
|
|
6
8
|
export declare class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {
|
|
7
9
|
static defaultProps: Partial<DraggableBoxProps>;
|
|
8
10
|
constructor(props: DraggableBoxProps);
|
|
11
|
+
private formatState;
|
|
9
12
|
private prePositionMode;
|
|
10
13
|
private preDraggerRef;
|
|
11
14
|
private container;
|
|
@@ -38,16 +41,20 @@ export declare class DraggableBox extends React.Component<DraggableBoxProps, Dra
|
|
|
38
41
|
dY: number;
|
|
39
42
|
startTop: number;
|
|
40
43
|
startLeft: number;
|
|
44
|
+
startBottom: number;
|
|
45
|
+
startRight: number;
|
|
46
|
+
translateX: number;
|
|
47
|
+
translateY: number;
|
|
41
48
|
cachedScaleX: number;
|
|
42
49
|
cachedScaleY: number;
|
|
43
|
-
__moveDisposer
|
|
44
|
-
__clickDisposer
|
|
45
|
-
__bodyClassDisposer
|
|
46
|
-
__upDisposer
|
|
47
|
-
__resizeDisposer
|
|
48
|
-
__preventScrollDisposer
|
|
50
|
+
private __moveDisposer?;
|
|
51
|
+
private __clickDisposer?;
|
|
52
|
+
private __bodyClassDisposer?;
|
|
53
|
+
private __upDisposer?;
|
|
54
|
+
private __resizeDisposer?;
|
|
55
|
+
private __preventScrollDisposer?;
|
|
49
56
|
dragAreaRef: HTMLDivElement | null;
|
|
50
|
-
reportStartPosition
|
|
57
|
+
private reportStartPosition;
|
|
51
58
|
enableDrag: (isTouch?: boolean) => void;
|
|
52
59
|
startDrag: (evt: React.MouseEvent<HTMLDivElement>) => void;
|
|
53
60
|
dragging: (evt: MouseEvent | TouchEvent) => void;
|
|
@@ -55,9 +62,16 @@ export declare class DraggableBox extends React.Component<DraggableBoxProps, Dra
|
|
|
55
62
|
endDrag: () => void;
|
|
56
63
|
showDragArea: () => void;
|
|
57
64
|
hideDragArea: () => void;
|
|
58
|
-
calcPosition: () =>
|
|
65
|
+
calcPosition: () => {
|
|
66
|
+
top: number;
|
|
67
|
+
left: number;
|
|
68
|
+
bottom: number;
|
|
69
|
+
right: number;
|
|
70
|
+
diffX: number;
|
|
71
|
+
diffY: number;
|
|
72
|
+
};
|
|
73
|
+
updateState: ({ offsetX, offsetY }?: Pick<DraggableBoxProps, 'offsetX' | 'offsetY'>) => void;
|
|
59
74
|
componentDidMount(): void;
|
|
60
75
|
componentWillUnmount(): void;
|
|
61
76
|
render(): React.JSX.Element;
|
|
62
77
|
}
|
|
63
|
-
export default DraggableBox;
|
package/dist/types/type.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { ValidPlacement } from './constants';
|
|
3
|
+
export interface IPositionChange {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
right: number;
|
|
7
|
+
bottom: number;
|
|
8
|
+
diffX: number;
|
|
9
|
+
diffY: number;
|
|
10
|
+
}
|
|
3
11
|
export interface DraggableBoxProps {
|
|
4
12
|
className?: string;
|
|
5
13
|
children?: React.ReactNode;
|
|
@@ -63,6 +71,18 @@ export interface DraggableBoxProps {
|
|
|
63
71
|
* @default 'fixed'
|
|
64
72
|
*/
|
|
65
73
|
positionMode?: 'fixed' | 'absolute';
|
|
74
|
+
/**
|
|
75
|
+
* 拖拽开始回调函数
|
|
76
|
+
*/
|
|
77
|
+
onDragStart?: (positionChange: IPositionChange) => void;
|
|
78
|
+
/**
|
|
79
|
+
* 拖拽中回调函数
|
|
80
|
+
*/
|
|
81
|
+
onDrag?: (positionChange: IPositionChange) => void;
|
|
82
|
+
/**
|
|
83
|
+
* 拖拽结束回调函数
|
|
84
|
+
*/
|
|
85
|
+
onDragEnd?: (positionChange: IPositionChange) => void;
|
|
66
86
|
}
|
|
67
87
|
export interface DraggableBoxState {
|
|
68
88
|
top?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ohkit/draggable-box",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "可拖拽容器",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"draggable-box"
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"react": ">=17",
|
|
35
35
|
"react-dom": ">=17"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "683241023c87579029f45b5edd7170daba12337e"
|
|
38
38
|
}
|
package/src/index.tsx
CHANGED
|
@@ -10,6 +10,8 @@ import {DraggableBoxProps, DraggableBoxState} from './type';
|
|
|
10
10
|
|
|
11
11
|
import './style.scss';
|
|
12
12
|
|
|
13
|
+
export * from './utils';
|
|
14
|
+
export * from './type';
|
|
13
15
|
export const c = p("ohkit-draggable-box__");
|
|
14
16
|
export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {
|
|
15
17
|
static defaultProps: Partial<DraggableBoxProps> = {
|
|
@@ -26,17 +28,20 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
26
28
|
|
|
27
29
|
constructor(props: DraggableBoxProps) {
|
|
28
30
|
super(props);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const { offsetX, offsetY } = this.props;
|
|
32
|
+
this.state = this.formatState({offsetX, offsetY});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private formatState({offsetX = DraggableBox.defaultProps.offsetX, offsetY = DraggableBox.defaultProps.offsetY} = {}) {
|
|
36
|
+
const { placement = 'bottom-right' } = this.props;
|
|
31
37
|
const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];
|
|
32
|
-
|
|
33
|
-
// 简化状态初始化
|
|
34
|
-
this.state = {
|
|
38
|
+
const newState = {
|
|
35
39
|
top: placementY === 'top' ? offsetY : undefined,
|
|
36
40
|
bottom: placementY === 'bottom' ? offsetY : undefined,
|
|
37
41
|
left: placementX === 'left' ? offsetX : undefined,
|
|
38
42
|
right: placementX === 'right' ? offsetX : undefined,
|
|
39
|
-
}
|
|
43
|
+
}
|
|
44
|
+
return newState;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
private prePositionMode: DraggableBoxProps['positionMode'];
|
|
@@ -65,8 +70,8 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
65
70
|
const container = this.getContainer(false);
|
|
66
71
|
if (!container) {
|
|
67
72
|
return {
|
|
68
|
-
width: window.innerWidth,
|
|
69
|
-
height: window.innerHeight,
|
|
73
|
+
width: document.documentElement.clientWidth, // window.innerWidth, 避免滚动条影响计算
|
|
74
|
+
height: document.documentElement.clientHeight, // window.innerHeight, 避免滚动条影响计算
|
|
70
75
|
left: 0,
|
|
71
76
|
top: 0,
|
|
72
77
|
scrollLeft: 0,
|
|
@@ -217,21 +222,25 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
217
222
|
dY = 0;
|
|
218
223
|
startTop = 0;
|
|
219
224
|
startLeft = 0;
|
|
225
|
+
startBottom = 0;
|
|
226
|
+
startRight = 0;
|
|
227
|
+
translateX = 0;
|
|
228
|
+
translateY = 0;
|
|
220
229
|
|
|
221
230
|
// 缓存缩放比例,避免在 dragging 中频繁计算
|
|
222
231
|
cachedScaleX = 1;
|
|
223
232
|
cachedScaleY = 1;
|
|
224
233
|
|
|
225
|
-
__moveDisposer?: () => void;
|
|
226
|
-
__clickDisposer?: () => void;
|
|
227
|
-
__bodyClassDisposer?: () => void;
|
|
228
|
-
__upDisposer?: () => void;
|
|
229
|
-
__resizeDisposer?: () => void;
|
|
230
|
-
__preventScrollDisposer?: () => void;
|
|
234
|
+
private __moveDisposer?: () => void;
|
|
235
|
+
private __clickDisposer?: () => void;
|
|
236
|
+
private __bodyClassDisposer?: () => void;
|
|
237
|
+
private __upDisposer?: () => void;
|
|
238
|
+
private __resizeDisposer?: () => void;
|
|
239
|
+
private __preventScrollDisposer?: () => void;
|
|
231
240
|
|
|
232
241
|
dragAreaRef: HTMLDivElement | null = null;
|
|
233
242
|
|
|
234
|
-
reportStartPosition() {
|
|
243
|
+
private reportStartPosition() {
|
|
235
244
|
if (this.draggerRef) {
|
|
236
245
|
// 获取缩放比例
|
|
237
246
|
const { scaleX, scaleY } = getScaleRatio(this.getContainer());
|
|
@@ -244,6 +253,8 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
244
253
|
// 计算相对于容器的位置,并除以缩放比例得到未缩放的坐标
|
|
245
254
|
this.startTop = top / scaleY - containerRect.top + containerRect.scrollTop - containerRect.borderTopWidth;
|
|
246
255
|
this.startLeft = left / scaleY - containerRect.left + containerRect.scrollLeft - containerRect.borderLeftWidth;
|
|
256
|
+
this.startBottom = containerRect.height - this.startTop - this.dragBoxSize.height;
|
|
257
|
+
this.startRight = containerRect.width - this.startLeft - this.dragBoxSize.width;
|
|
247
258
|
}
|
|
248
259
|
}
|
|
249
260
|
|
|
@@ -276,6 +287,18 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
276
287
|
}
|
|
277
288
|
}
|
|
278
289
|
}
|
|
290
|
+
// 调用拖拽开始回调
|
|
291
|
+
if (!this.isDragging && this.props.onDragStart) {
|
|
292
|
+
const positionChange = {
|
|
293
|
+
top: this.startTop,
|
|
294
|
+
left: this.startLeft,
|
|
295
|
+
bottom: this.startBottom,
|
|
296
|
+
right: this.startRight,
|
|
297
|
+
diffX: 0,
|
|
298
|
+
diffY: 0
|
|
299
|
+
};
|
|
300
|
+
this.props.onDragStart(positionChange);
|
|
301
|
+
}
|
|
279
302
|
this.dragging(evt as TouchEvent | MouseEvent);
|
|
280
303
|
}, {
|
|
281
304
|
passive: !isTouch
|
|
@@ -360,10 +383,28 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
360
383
|
translateY = maxY - this.startTop;
|
|
361
384
|
}
|
|
362
385
|
}
|
|
386
|
+
if (this.translateX === translateX && this.translateY === translateY) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// 调用拖拽中回调
|
|
391
|
+
if (this.props.onDrag) {
|
|
392
|
+
const positionChange = {
|
|
393
|
+
top: this.startTop + translateY,
|
|
394
|
+
left: this.startLeft + translateX,
|
|
395
|
+
bottom: this.startBottom - translateY,
|
|
396
|
+
right: this.startRight - translateX,
|
|
397
|
+
diffX: translateX,
|
|
398
|
+
diffY: translateY
|
|
399
|
+
};
|
|
400
|
+
this.props.onDrag(positionChange);
|
|
401
|
+
}
|
|
363
402
|
|
|
364
403
|
if (this.draggerRef) {
|
|
365
404
|
this.draggerRef.style.transform = `translate(${translateX}px, ${translateY}px)`;
|
|
366
405
|
}
|
|
406
|
+
this.translateX = translateX;
|
|
407
|
+
this.translateY = translateY;
|
|
367
408
|
};
|
|
368
409
|
|
|
369
410
|
startTouchDrag = (evt: React.TouchEvent<HTMLDivElement>) => {
|
|
@@ -378,7 +419,9 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
378
419
|
|
|
379
420
|
endDrag = () => {
|
|
380
421
|
if (this.isDragging) {
|
|
381
|
-
this.calcPosition();
|
|
422
|
+
const positionChange = this.calcPosition();
|
|
423
|
+
// 调用拖拽结束回调
|
|
424
|
+
this.props.onDragEnd?.(positionChange);
|
|
382
425
|
if (this.draggerRef) {
|
|
383
426
|
this.draggerRef.style.transform = '';
|
|
384
427
|
}
|
|
@@ -474,8 +517,6 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
474
517
|
const realBottom = height - realTop - this.dragBoxSize.height;
|
|
475
518
|
const realRight = width - realLeft - this.dragBoxSize.width;
|
|
476
519
|
if (realTop !== this.state.top || realLeft !== this.state.left || this.state.bottom !== realBottom || this.state.right !== realRight) {
|
|
477
|
-
// console.log(minY, maxY, this.startTop, this.dY, newTop, realTop, 'minY, maxY, this.startTop, this.dY, newTop, realTop --- calcPosition y');
|
|
478
|
-
// console.log(minX, maxX, this.startLeft, this.dX, newLeft, realLeft, 'minX, maxX, this.startLeft, this.dX, newLeft, realLeft ---calcPosition x');
|
|
479
520
|
this.setState({
|
|
480
521
|
top: realTop,
|
|
481
522
|
left: realLeft,
|
|
@@ -483,11 +524,29 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
483
524
|
right: realRight
|
|
484
525
|
});
|
|
485
526
|
}
|
|
527
|
+
const positionChange = {
|
|
528
|
+
top: realTop,
|
|
529
|
+
left: realLeft,
|
|
530
|
+
bottom: realBottom,
|
|
531
|
+
right: realRight,
|
|
532
|
+
diffX: realLeft - this.startLeft,
|
|
533
|
+
diffY: realTop - this.startTop
|
|
534
|
+
};
|
|
486
535
|
this.startTop = realTop;
|
|
487
536
|
this.startLeft = realLeft;
|
|
537
|
+
this.startBottom = realBottom;
|
|
538
|
+
this.startRight = realRight;
|
|
488
539
|
this.dX = this.dY = 0;
|
|
540
|
+
return positionChange;
|
|
489
541
|
};
|
|
490
542
|
|
|
543
|
+
// 更新状态并计算位置 (外部可以调用)
|
|
544
|
+
updateState = ({offsetX, offsetY}: Pick<DraggableBoxProps, 'offsetX' | 'offsetY'> = {}) => {
|
|
545
|
+
this.setState(this.formatState({offsetX, offsetY}), () => {
|
|
546
|
+
this.reportStartPosition();
|
|
547
|
+
this.calcPosition();
|
|
548
|
+
});
|
|
549
|
+
}
|
|
491
550
|
|
|
492
551
|
componentDidMount() {
|
|
493
552
|
// 检查初始位置是否在边界范围内,如果不在则修正
|
|
@@ -524,7 +583,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
524
583
|
position: positionMode
|
|
525
584
|
};
|
|
526
585
|
return (
|
|
527
|
-
|
|
586
|
+
<React.Fragment>
|
|
528
587
|
{showDragArea && (
|
|
529
588
|
<div
|
|
530
589
|
className={c('drag-area')}
|
|
@@ -556,9 +615,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
556
615
|
>
|
|
557
616
|
{children}
|
|
558
617
|
</div>
|
|
559
|
-
|
|
618
|
+
</React.Fragment>
|
|
560
619
|
);
|
|
561
620
|
}
|
|
562
621
|
}
|
|
563
|
-
|
|
564
|
-
export default DraggableBox;
|
package/src/type.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type {ValidPlacement} from './constants';
|
|
2
2
|
|
|
3
|
+
export interface IPositionChange {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
right: number;
|
|
7
|
+
bottom: number;
|
|
8
|
+
diffX: number;
|
|
9
|
+
diffY: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
3
12
|
export interface DraggableBoxProps {
|
|
4
13
|
className?: string;
|
|
5
14
|
children?: React.ReactNode;
|
|
@@ -63,6 +72,18 @@ export interface DraggableBoxProps {
|
|
|
63
72
|
* @default 'fixed'
|
|
64
73
|
*/
|
|
65
74
|
positionMode?: 'fixed' | 'absolute';
|
|
75
|
+
/**
|
|
76
|
+
* 拖拽开始回调函数
|
|
77
|
+
*/
|
|
78
|
+
onDragStart?: (positionChange: IPositionChange) => void;
|
|
79
|
+
/**
|
|
80
|
+
* 拖拽中回调函数
|
|
81
|
+
*/
|
|
82
|
+
onDrag?: (positionChange: IPositionChange) => void;
|
|
83
|
+
/**
|
|
84
|
+
* 拖拽结束回调函数
|
|
85
|
+
*/
|
|
86
|
+
onDragEnd?: (positionChange: IPositionChange) => void;
|
|
66
87
|
}
|
|
67
88
|
|
|
68
89
|
export interface DraggableBoxState {
|