diff --git a/client/package-lock.json b/client/package-lock.json index 5f59dd6e1..52be159a3 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -65,6 +65,7 @@ "react-router-dom": "^6.23.1", "react-sticky": "^6.0.3", "react-virtualized": "^9.22.5", + "react-virtuoso": "^4.7.11", "recharts": "^2.12.7", "redux": "^5.0.1", "redux-actions": "^3.0.0", @@ -15888,6 +15889,18 @@ "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-virtuoso": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.7.11.tgz", + "integrity": "sha512-Kdn9qEtQI2ulEuBMzW2BTkDsfijB05QUd6lpZ1K36oyA3k65Cz4lG4EKrh2pCfUafX4C2uMSZOwzMOhbrMOTFA==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16 || >=17 || >= 18", + "react-dom": ">=16 || >=17 || >= 18" + } + }, "node_modules/reactcss": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", diff --git a/client/package.json b/client/package.json index 7d7de9475..2e1703437 100644 --- a/client/package.json +++ b/client/package.json @@ -65,6 +65,7 @@ "react-router-dom": "^6.23.1", "react-sticky": "^6.0.3", "react-virtualized": "^9.22.5", + "react-virtuoso": "^4.7.11", "recharts": "^2.12.7", "redux": "^5.0.1", "redux-actions": "^3.0.0", diff --git a/client/src/components/production-board-kanban/production-board-kanban.utils.js b/client/src/components/production-board-kanban/production-board-kanban.utils.js index 565019db0..61519d007 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.utils.js +++ b/client/src/components/production-board-kanban/production-board-kanban.utils.js @@ -1,5 +1,5 @@ import { groupBy } from "lodash"; -import fakeData from "./testData/board300.json"; +import fakeData from "./testData/board1200.json"; const sortByParentId = (arr) => { // return arr.reduce((accumulator, currentValue) => { diff --git a/client/src/components/trello-board/controllers/BoardContainer.jsx b/client/src/components/trello-board/controllers/BoardContainer.jsx index 6c70e6945..bd976efdd 100644 --- a/client/src/components/trello-board/controllers/BoardContainer.jsx +++ b/client/src/components/trello-board/controllers/BoardContainer.jsx @@ -1,7 +1,11 @@ import React, { useCallback, useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; -import Container from "../dnd/Container"; -import Draggable from "../dnd/Draggable"; + +// import Container from "../dnd/Container"; +// import Draggable from "../dnd/Draggable"; + +import { DragDropContext } from "../dnd/lib"; + import PropTypes from "prop-types"; import pick from "lodash/pick"; import isEqual from "lodash/isEqual"; @@ -151,6 +155,10 @@ const BoardContainer = ({ [dispatch, handleLaneDragEnd] ); + const onDragEnd = (...params) => { + console.dir(params); + }; + const getCardDetails = useCallback( (laneId, cardIndex) => { return currentReducerData.lanes.find((lane) => lane.id === laneId).cards[cardIndex]; @@ -239,22 +247,25 @@ const BoardContainer = ({ ] ); + let cardIndex = 0; + return ( - getLaneDetails(index)} - groupName={groupName} + getLaneDetails(index)} + // groupName={groupName} > {currentReducerData.lanes.map((lane, index) => { const { id, droppable, ...laneOtherProps } = lane; - const laneToRender = ( + return ( ({ ...card, idx: cardIndex++ }))} /> ); - return draggable || laneDraggable ? {laneToRender} : laneToRender; })} - + - {canAddLanes && ( - - {editable && !addLaneMode ? ( - - ) : ( - addLaneMode && - )} - - )} + {/*{canAddLanes && (*/} + {/* */} + {/* {editable && !addLaneMode ? (*/} + {/* */} + {/* ) : (*/} + {/* addLaneMode && */} + {/* )}*/} + {/* */} + {/*)}*/} ); }; diff --git a/client/src/components/trello-board/controllers/Lane.jsx b/client/src/components/trello-board/controllers/Lane.jsx index 27a657f39..99db10945 100644 --- a/client/src/components/trello-board/controllers/Lane.jsx +++ b/client/src/components/trello-board/controllers/Lane.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import classNames from "classnames"; import PropTypes from "prop-types"; import { bindActionCreators } from "redux"; @@ -7,10 +7,8 @@ import isEqual from "lodash/isEqual"; import cloneDeep from "lodash/cloneDeep"; import { v1 } from "uuid"; -import Container from "../dnd/Container.jsx"; -import Draggable from "../dnd/Draggable.jsx"; - import * as actions from "../../../redux/trello/trello.actions.js"; +import { Droppable, Draggable } from "../dnd/lib/index.js"; /** * Lane is a React component that represents a lane in a Trello-like board. @@ -112,6 +110,15 @@ function Lane({ const laneRef = useRef(null); + const flexStyle = useMemo(() => { + return orientation === "vertical" + ? { + display: "flex", + flexWrap: "wrap" + } + : {}; + }, [orientation]); + useEffect(() => { if (!isEqual(cards, currentPageFinal)) { setCurrentPageFinal(currentPage); @@ -171,6 +178,7 @@ function Lane({ }; const handleCardClick = (e, card) => { + console.log("hit"); onCardClick && onCardClick(card.id, card.metadata, card.laneId); e.stopPropagation(); }; @@ -265,32 +273,58 @@ function Lane({ {...card} /> ); + return cardDraggable && (!card.hasOwnProperty("draggable") || card.draggable) ? ( - {cardToRender} + + {(provided, snapshot) => { + return ( +
+ {cardToRender} +
+ ); + }} +
) : ( {cardToRender} ); }); return ( - - onDragEnd(id, e)} - onDragEnter={() => setIsDraggingOver(true)} - onDragLeave={() => setIsDraggingOver(false)} - shouldAcceptDrop={shouldAcceptDrop} - getChildPayload={(index) => getCardDetails(id, index)} - > - {cardList} - - {editable && !addCardMode && } - {addCardMode && } - + onDragEnd(id, e)} + // onDragEnter={() => setIsDraggingOver(true)} + // onDragLeave={() => setIsDraggingOver(false)} + // shouldAcceptDrop={shouldAcceptDrop} + // getChildPayload={(index) => getCardDetails(id, index)} + > + {(provided, snapshot) => ( +
+ {cardList} + {editable && !addCardMode && } + {addCardMode && } + {provided.placeholder} +
+ )} +
); }; diff --git a/client/src/components/trello-board/dnd/Container.jsx b/client/src/components/trello-board/dnd/Container.jsx deleted file mode 100644 index 51b01ce6f..000000000 --- a/client/src/components/trello-board/dnd/Container.jsx +++ /dev/null @@ -1,111 +0,0 @@ -import React, { Component } from "react"; -import PropTypes from "prop-types"; -import container, { dropHandlers } from "../smooth-dnd"; - -container.dropHandler = dropHandlers.reactDropHandler().handler; -container.wrapChild = (p) => p; // don't wrap children they will already be wrapped - -class Container extends Component { - constructor(props) { - super(props); - this.getContainerOptions = this.getContainerOptions.bind(this); - this.setRef = this.setRef.bind(this); - this.prevContainer = null; - } - - componentDidMount() { - this.prevContainer = this.containerDiv; - this.container = container(this.containerDiv, this.getContainerOptions()); - } - - componentWillUnmount() { - this.container.dispose(); - this.container = null; - } - - componentDidUpdate() { - if (this.containerDiv) { - if (this.prevContainer && this.prevContainer !== this.containerDiv) { - this.container.dispose(); - this.container = container(this.containerDiv, this.getContainerOptions()); - this.prevContainer = this.containerDiv; - } - } - } - - render() { - if (this.props.render) { - return this.props.render(this.setRef); - } else { - return ( -
- {this.props.children} -
- ); - } - } - - setRef(element) { - this.containerDiv = element; - } - - getContainerOptions() { - const functionProps = {}; - const propKeys = [ - "onDragStart", - "onDragEnd", - "onDrop", - "getChildPayload", - "shouldAnimateDrop", - "shouldAcceptDrop", - "onDragEnter", - "onDragLeave", - "render", - "onDropReady", - "getGhostParent" - ]; - - propKeys.forEach((key) => { - if (this.props[key]) { - functionProps[key] = (...p) => this.props[key](...p); - } - }); - - return { ...this.props, ...functionProps }; - } -} - -Container.propTypes = { - behaviour: PropTypes.oneOf(["move", "copy", "drag-zone"]), - groupName: PropTypes.string, - orientation: PropTypes.oneOf(["horizontal", "vertical"]), - style: PropTypes.object, - dragHandleSelector: PropTypes.string, - className: PropTypes.string, - nonDragAreaSelector: PropTypes.string, - dragBeginDelay: PropTypes.number, - animationDuration: PropTypes.number, - autoScrollEnabled: PropTypes.string, - lockAxis: PropTypes.string, - dragClass: PropTypes.string, - dropClass: PropTypes.string, - onDragStart: PropTypes.func, - onDragEnd: PropTypes.func, - onDrop: PropTypes.func, - getChildPayload: PropTypes.func, - shouldAnimateDrop: PropTypes.func, - shouldAcceptDrop: PropTypes.func, - onDragEnter: PropTypes.func, - onDragLeave: PropTypes.func, - render: PropTypes.func, - getGhostParent: PropTypes.func, - removeOnDropOut: PropTypes.bool -}; - -Container.defaultProps = { - behaviour: "move", - orientation: "vertical", - className: "reactTrelloBoard" -}; - -export default Container; diff --git a/client/src/components/trello-board/dnd/Draggable.jsx b/client/src/components/trello-board/dnd/Draggable.jsx deleted file mode 100644 index 643764deb..000000000 --- a/client/src/components/trello-board/dnd/Draggable.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { Component } from "react"; -import PropTypes from "prop-types"; -import { constants } from "../smooth-dnd"; -const { wrapperClass } = constants; - -class Draggable extends Component { - render() { - const { render, className, children, ...restProps } = this.props; - - try { - if (render) { - return React.cloneElement(render(), { className: wrapperClass }); - } - - const clsName = className ? `${className} ` : ""; - return ( -
- {children} -
- ); - } catch (error) { - console.error("Error rendering Draggable component:", error); - return null; // Return null if an error occurs to prevent crashing - } - } -} - -Draggable.propTypes = { - render: PropTypes.func, - className: PropTypes.string, - children: PropTypes.node -}; - -export default Draggable; diff --git a/client/src/components/trello-board/dnd/lib/state/droppable/get-droppable.js b/client/src/components/trello-board/dnd/lib/state/droppable/get-droppable.js index 44cc3ebd2..da79f57ad 100644 --- a/client/src/components/trello-board/dnd/lib/state/droppable/get-droppable.js +++ b/client/src/components/trello-board/dnd/lib/state/droppable/get-droppable.js @@ -3,7 +3,7 @@ import { origin } from "../position"; import getMaxScroll from "../get-max-scroll"; import getSubject from "./util/get-subject"; -export default ({ descriptor, isEnabled, isCombineEnabled, isFixedOnPage, direction, client, page, closest }) => { +const getDroppable = ({ descriptor, isEnabled, isCombineEnabled, isFixedOnPage, direction, client, page, closest }) => { const frame = (() => { if (!closest) { return null; @@ -54,3 +54,5 @@ export default ({ descriptor, isEnabled, isCombineEnabled, isFixedOnPage, direct }; return dimension; }; + +export default getDroppable; diff --git a/client/src/components/trello-board/dnd/lib/view/draggable/connected-draggable.js b/client/src/components/trello-board/dnd/lib/view/draggable/connected-draggable.js index 95697a828..71d02ab6a 100644 --- a/client/src/components/trello-board/dnd/lib/view/draggable/connected-draggable.js +++ b/client/src/components/trello-board/dnd/lib/view/draggable/connected-draggable.js @@ -306,7 +306,6 @@ const ConnectedDraggable = connect( // Using our own context for the store to avoid clashing with consumers context: StoreContext, // Default value, but being really clear - pure: true, // When pure, compares the result of mapStateToProps to its previous value. // Default value: shallowEqual // Switching to a strictEqual as we return a memoized object on changes diff --git a/client/src/components/trello-board/dnd/lib/view/droppable/connected-droppable.js b/client/src/components/trello-board/dnd/lib/view/droppable/connected-droppable.js index 07bb341dd..e4032f298 100644 --- a/client/src/components/trello-board/dnd/lib/view/droppable/connected-droppable.js +++ b/client/src/components/trello-board/dnd/lib/view/droppable/connected-droppable.js @@ -192,13 +192,13 @@ const ConnectedDroppable = connect( { // Ensuring our context does not clash with consumers context: StoreContext, - // pure: true is default value, but being really clear - pure: true, + // When pure, compares the result of mapStateToProps to its previous value. // Default value: shallowEqual // Switching to a strictEqual as we return a memoized object on changes areStatePropsEqual: isStrictEqual } )(Droppable); + ConnectedDroppable.defaultProps = defaultProps; export default ConnectedDroppable; diff --git a/client/src/components/trello-board/index.jsx b/client/src/components/trello-board/index.jsx index d00834e87..3d3edc22e 100644 --- a/client/src/components/trello-board/index.jsx +++ b/client/src/components/trello-board/index.jsx @@ -1,7 +1,5 @@ import React from "react"; -import Draggable from "./dnd/Draggable.jsx"; -import Container from "./dnd/Container.jsx"; import BoardContainer from "./controllers/BoardContainer.jsx"; import Board from "./controllers/Board.jsx"; import Lane from "./controllers/Lane.jsx"; @@ -12,7 +10,7 @@ import widgets from "./widgets/index"; import { StyleSheetManager } from "styled-components"; import isPropValid from "@emotion/is-prop-valid"; -export { Draggable, Container, BoardContainer, Lane, widgets }; +export { BoardContainer, Lane, widgets }; export { DefaultComponents as components }; diff --git a/client/src/components/trello-board/smooth-dnd/index.js b/client/src/components/trello-board/smooth-dnd/index.js deleted file mode 100644 index bc0bafe75..000000000 --- a/client/src/components/trello-board/smooth-dnd/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import container from './src/container'; -import * as constants from './src/constants'; -import * as dropHandlers from './src/dropHandlers'; -export default container; -export { - constants, - dropHandlers, -}; \ No newline at end of file diff --git a/client/src/components/trello-board/smooth-dnd/src/constants.js b/client/src/components/trello-board/smooth-dnd/src/constants.js deleted file mode 100644 index 4030ab181..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/constants.js +++ /dev/null @@ -1,21 +0,0 @@ -export const containerInstance = 'smooth-dnd-container-instance'; -export const containersInDraggable = 'smooth-dnd-containers-in-draggable'; - -export const defaultGroupName = '@@smooth-dnd-default-group@@'; -export const wrapperClass = 'smooth-dnd-draggable-wrapper'; -export const defaultGrabHandleClass = 'smooth-dnd-default-grap-handle'; -export const animationClass = 'animated'; -export const translationValue = '__smooth_dnd_draggable_translation_value'; -export const visibilityValue = '__smooth_dnd_draggable_visibility_value'; -export const ghostClass = 'smooth-dnd-ghost'; - -export const containerClass = 'smooth-dnd-container'; - -export const extraSizeForInsertion = 'smooth-dnd-extra-size-for-insertion'; -export const stretcherElementClass = 'smooth-dnd-stretcher-element'; -export const stretcherElementInstance = 'smooth-dnd-stretcher-instance'; - -export const isDraggableDetached = 'smoth-dnd-is-draggable-detached'; - -export const disbaleTouchActions = 'smooth-dnd-disable-touch-action'; -export const noUserSelectClass = 'smooth-dnd-no-user-select'; diff --git a/client/src/components/trello-board/smooth-dnd/src/container.css b/client/src/components/trello-board/smooth-dnd/src/container.css deleted file mode 100644 index ada5d2a1f..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/container.css +++ /dev/null @@ -1,61 +0,0 @@ -.smooth-dnd-container *{ - box-sizing: border-box; -} - -.smooth-dnd-disable-touch-action{ - touch-action: none; -} - -.smooth-dnd-container{ - position: relative; -} - -.smooth-dnd-container.vertical{ -} - -.smooth-dnd-container.horizontal{ - white-space: nowrap; -} - -.smooth-dnd-container.horizontal .smooth-dnd-draggable-wrapper{ - height: 100%; - display: inline-block; -} - - -.smooth-dnd-draggable-wrapper { - overflow: hidden; -} - -.smooth-dnd-draggable-wrapper.animated{ - transition: transform ease; -} - -.smooth-dnd-ghost { - -} - -.smooth-dnd-ghost *{ - box-sizing: border-box; -} - -.smooth-dnd-ghost.animated{ - transition: all ease-in-out; -} - -/* .smooth-dnd-no-user-select{ - user-select: none; -} - -.smooth-dnd-stretcher-element{ - background-color: transparent; -} - -.smooth-dnd-stretcher-element.vertical{ - height: 1px; -} - -.smooth-dnd-stretcher-element.horizontal{ - height: 100%; - display: inline-block; -} */ diff --git a/client/src/components/trello-board/smooth-dnd/src/container.js b/client/src/components/trello-board/smooth-dnd/src/container.js deleted file mode 100644 index 3e60f171c..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/container.js +++ /dev/null @@ -1,777 +0,0 @@ -import Mediator from './mediator'; -import layoutManager from './layoutManager'; -import { hasClass, addClass, removeClass, getParent } from './utils'; -import { domDropHandler } from './dropHandlers'; -import { - defaultGroupName, - wrapperClass, - animationClass, - stretcherElementClass, - stretcherElementInstance, - translationValue, - containerClass, - containerInstance, - containersInDraggable -} from './constants'; - -const defaultOptions = { - groupName: null, - behaviour: 'move', // move | copy - orientation: 'vertical', // vertical | horizontal - getChildPayload: null, - animationDuration: 250, - autoScrollEnabled: true, - shouldAcceptDrop: null, - shouldAnimateDrop: null -}; - -function setAnimation(element, add, animationDuration) { - if (add) { - addClass(element, animationClass); - element.style.transitionDuration = animationDuration + 'ms'; - } else { - removeClass(element, animationClass); - element.style.removeProperty('transition-duration'); - } -} - -function getContainer(element) { - return element ? element[containerInstance] : null; -} - -function initOptions(props = defaultOptions) { - return Object.assign({}, defaultOptions, props); -} - -function isDragRelevant({ element, options }) { - return function(sourceContainer, payload) { - if (options.shouldAcceptDrop) { - return options.shouldAcceptDrop(sourceContainer.getOptions(), payload); - } - const sourceOptions = sourceContainer.getOptions(); - if (options.behaviour === 'copy') return false; - - const parentWrapper = getParent(element, '.' + wrapperClass); - if (parentWrapper === sourceContainer.element) { - return false; - } - - if (sourceContainer.element === element) return true; - if (sourceOptions.groupName && sourceOptions.groupName === options.groupName) return true; - - return false; - }; -} - -function wrapChild(child) { - if (SmoothDnD.wrapChild) { - return SmoothDnD.wrapChild(child); - } - const div = global.document.createElement('div'); - div.className = `${wrapperClass}`; - child.parentElement.insertBefore(div, child); - div.appendChild(child); - return div; -} - -function wrapChildren(element) { - const draggables = []; - Array.prototype.map.call(element.children, child => { - if (child.nodeType === Node.ELEMENT_NODE) { - let wrapper = child; - if (!hasClass(child, wrapperClass)) { - wrapper = wrapChild(child); - } - wrapper[containersInDraggable] = []; - wrapper[translationValue] = 0; - draggables.push(wrapper); - } else { - if (typeof element.removeChild === "function") { - element.removeChild(child); - } - } - }); - return draggables; -} - -function unwrapChildren(element) { - Array.prototype.map.call(element.children, child => { - if (child.nodeType === Node.ELEMENT_NODE) { - let wrapper = child; - if (hasClass(child, wrapperClass)) { - element.insertBefore(wrapper, wrapChild.firstElementChild); - element.removeChild(wrapper); - } - } - }); -} - -function findDraggebleAtPos({ layout }) { - const find = (draggables, pos, startIndex, endIndex, withRespectToMiddlePoints = false) => { - if (endIndex < startIndex) { - return startIndex; - } - // binary serach draggable - if (startIndex === endIndex) { - let { begin, end } = layout.getBeginEnd(draggables[startIndex]); - // mouse pos is inside draggable - // now decide which index to return - if (pos > begin && pos <= end) { - if (withRespectToMiddlePoints) { - return pos < (end + begin) / 2 ? startIndex : startIndex + 1; - } else { - return startIndex; - } - } else { - return null; - } - } else { - const middleIndex = Math.floor((endIndex + startIndex) / 2); - const { begin, end } = layout.getBeginEnd(draggables[middleIndex]); - if (pos < begin) { - return find(draggables, pos, startIndex, middleIndex - 1, withRespectToMiddlePoints); - } else if (pos > end) { - return find(draggables, pos, middleIndex + 1, endIndex, withRespectToMiddlePoints); - } else { - if (withRespectToMiddlePoints) { - return pos < (end + begin) / 2 ? middleIndex : middleIndex + 1; - } else { - return middleIndex; - } - } - } - }; - - return (draggables, pos, withRespectToMiddlePoints = false) => { - return find(draggables, pos, 0, draggables.length - 1, withRespectToMiddlePoints); - }; -} - -function resetDraggables({ element, draggables, layout, options }) { - return function() { - draggables.forEach(p => { - setAnimation(p, false); - layout.setTranslation(p, 0); - layout.setVisibility(p, true); - p[containersInDraggable] = []; - }); - - if (element[stretcherElementInstance]) { - element[stretcherElementInstance].parentNode.removeChild(element[stretcherElementInstance]); - element[stretcherElementInstance] = null; - } - }; -} - -function setTargetContainer(draggableInfo, element, set = true) { - if (element && set) { - draggableInfo.targetElement = element; - } else { - if (draggableInfo.targetElement === element) { - draggableInfo.targetElement = null; - } - } -} - -function handleDrop({ element, draggables, layout, options }) { - const draggablesReset = resetDraggables({ element, draggables, layout, options }); - const dropHandler = (SmoothDnD.dropHandler || domDropHandler)({ element, draggables, layout, options }); - return function(draggableInfo, { addedIndex, removedIndex }) { - draggablesReset(); - // if drop zone is valid => complete drag else do nothing everything will be reverted by draggablesReset() - if (draggableInfo.targetElement || options.removeOnDropOut) { - let actualAddIndex = - addedIndex !== null ? (removedIndex !== null && removedIndex < addedIndex ? addedIndex - 1 : addedIndex) : null; - const dropHandlerParams = { - removedIndex, - addedIndex: actualAddIndex, - payload: draggableInfo.payload, - droppedElement: draggableInfo.element.firstElementChild - }; - dropHandler(dropHandlerParams, options.onDrop); - } - }; -} - -function getContainerProps(element, initialOptions) { - const options = initOptions(initialOptions); - const draggables = wrapChildren(element, options.orientation, options.animationDuration); - // set flex classes before layout is inited for scroll listener - addClass(element, `${containerClass} ${options.orientation}`); - const layout = layoutManager(element, options.orientation, options.animationDuration); - return { - element, - draggables, - options, - layout - }; -} - -function getRelaventParentContainer(container, relevantContainers) { - let current = container.element; - while (current) { - const containerOfParentElement = getContainer(current.parentElement); - if (containerOfParentElement && relevantContainers.indexOf(containerOfParentElement) > -1) { - return { - container: containerOfParentElement, - draggable: current - }; - } - current = current.parentElement; - } - - return null; -} - -function registerToParentContainer(container, relevantContainers) { - const parentInfo = getRelaventParentContainer(container, relevantContainers); - if (parentInfo) { - parentInfo.container.getChildContainers().push(container); - container.setParentContainer(parentInfo.container); - //current should be draggable - parentInfo.draggable[containersInDraggable].push(container); - } -} - -function getRemovedItem({ draggables, element, options }) { - let prevRemovedIndex = null; - return ({ draggableInfo, dragResult }) => { - let removedIndex = prevRemovedIndex; - if (prevRemovedIndex == null && draggableInfo.container.element === element && options.behaviour !== 'copy') { - removedIndex = prevRemovedIndex = draggableInfo.elementIndex; - } - - return { removedIndex }; - }; -} - -function setRemovedItemVisibilty({ draggables, layout }) { - return ({ draggableInfo, dragResult }) => { - if (dragResult.removedIndex !== null) { - layout.setVisibility(draggables[dragResult.removedIndex], false); - } - }; -} - -function getPosition({ element, layout }) { - return ({ draggableInfo }) => { - return { - pos: !getContainer(element).isPosInChildContainer() ? layout.getPosition(draggableInfo.position) : null - }; - }; -} - -function notifyParentOnPositionCapture({ element }) { - let isCaptured = false; - return ({ draggableInfo, dragResult }) => { - if (getContainer(element).getParentContainer() && isCaptured !== (dragResult.pos !== null)) { - isCaptured = dragResult.pos !== null; - getContainer(element) - .getParentContainer() - .onChildPositionCaptured(isCaptured); - } - }; -} - -function getElementSize({ layout }) { - let elementSize = null; - return ({ draggableInfo, dragResult }) => { - if (dragResult.pos === null) { - return (elementSize = null); - } else { - elementSize = elementSize || layout.getSize(draggableInfo.element); - } - return { elementSize }; - }; -} - -function handleTargetContainer({ element }) { - return ({ draggableInfo, dragResult }) => { - setTargetContainer(draggableInfo, element, !!dragResult.pos); - }; -} - -function getDragInsertionIndex({ draggables, layout }) { - const findDraggable = findDraggebleAtPos({ layout }); - return ({ dragResult: { shadowBeginEnd, pos } }) => { - if (!shadowBeginEnd) { - const index = findDraggable(draggables, pos, true); - return index !== null ? index : draggables.length; - } else { - if (shadowBeginEnd.begin + shadowBeginEnd.beginAdjustment <= pos && shadowBeginEnd.end >= pos) { - // position inside ghost - return null; - } - } - - if (pos < shadowBeginEnd.begin + shadowBeginEnd.beginAdjustment) { - return findDraggable(draggables, pos); - } else if (pos > shadowBeginEnd.end) { - return findDraggable(draggables, pos) + 1; - } else { - return draggables.length; - } - }; -} - -function getDragInsertionIndexForDropZone({ draggables, layout }) { - return ({ dragResult: { pos } }) => { - return pos !== null ? { addedIndex: 0 } : { addedIndex: null }; - }; -} - -function getShadowBeginEndForDropZone({ draggables, layout }) { - let prevAddedIndex = null; - return ({ dragResult: { addedIndex } }) => { - if (addedIndex !== prevAddedIndex) { - prevAddedIndex = addedIndex; - const { begin, end } = layout.getBeginEndOfContainer(); - return { - shadowBeginEnd: { - rect: layout.getTopLeftOfElementBegin(begin, end) - } - }; - } - }; -} - -function invalidateShadowBeginEndIfNeeded(params) { - const shadowBoundsGetter = getShadowBeginEnd(params); - return ({ draggableInfo, dragResult }) => { - if (draggableInfo.invalidateShadow) { - return shadowBoundsGetter({ draggableInfo, dragResult }); - } - return null; - }; -} - -function getNextAddedIndex(params) { - const getIndexForPos = getDragInsertionIndex(params); - return ({ dragResult }) => { - let index = null; - if (dragResult.pos !== null) { - index = getIndexForPos({ dragResult }); - if (index === null) { - index = dragResult.addedIndex; - } - } - return { - addedIndex: index - }; - }; -} - -function resetShadowAdjustment() { - let lastAddedIndex = null; - return ({ dragResult: { addedIndex, shadowBeginEnd } }) => { - if (addedIndex !== lastAddedIndex && lastAddedIndex !== null && shadowBeginEnd) { - shadowBeginEnd.beginAdjustment = 0; - } - lastAddedIndex = addedIndex; - }; -} - -function handleInsertionSizeChange({ element, draggables, layout, options }) { - let strectherElement = null; - return function({ dragResult: { addedIndex, removedIndex, elementSize } }) { - if (removedIndex === null) { - if (addedIndex !== null) { - if (!strectherElement) { - const containerBeginEnd = layout.getBeginEndOfContainer(); - containerBeginEnd.end = containerBeginEnd.begin + layout.getSize(element); - const hasScrollBar = layout.getScrollSize(element) > layout.getSize(element); - const containerEnd = hasScrollBar - ? containerBeginEnd.begin + layout.getScrollSize(element) - layout.getScrollValue(element) - : containerBeginEnd.end; - const lastDraggableEnd = - draggables.length > 0 - ? layout.getBeginEnd(draggables[draggables.length - 1]).end - - draggables[draggables.length - 1][translationValue] - : containerBeginEnd.begin; - if (lastDraggableEnd + elementSize > containerEnd) { - strectherElement = global.document.createElement('div'); - strectherElement.className = stretcherElementClass + ' ' + options.orientation; - const stretcherSize = elementSize + lastDraggableEnd - containerEnd; - layout.setSize(strectherElement.style, `${stretcherSize}px`); - element.appendChild(strectherElement); - element[stretcherElementInstance] = strectherElement; - return { - containerBoxChanged: true - }; - } - } - } else { - if (strectherElement) { - layout.setTranslation(strectherElement, 0); - let toRemove = strectherElement; - strectherElement = null; - element.removeChild(toRemove); - element[stretcherElementInstance] = null; - return { - containerBoxChanged: true - }; - } - } - } - }; -} - -function calculateTranslations({ element, draggables, layout }) { - let prevAddedIndex = null; - let prevRemovedIndex = null; - return function({ dragResult: { addedIndex, removedIndex, elementSize } }) { - if (addedIndex !== prevAddedIndex || removedIndex !== prevRemovedIndex) { - for (let index = 0; index < draggables.length; index++) { - if (index !== removedIndex) { - const draggable = draggables[index]; - let translate = 0; - if (removedIndex !== null && removedIndex < index) { - translate -= layout.getSize(draggables[removedIndex]); - } - if (addedIndex !== null && addedIndex <= index) { - translate += elementSize; - } - layout.setTranslation(draggable, translate); - } - } - - prevAddedIndex = addedIndex; - prevRemovedIndex = removedIndex; - - return { addedIndex, removedIndex }; - } - }; -} - -function getShadowBeginEnd({ draggables, layout }) { - let prevAddedIndex = null; - return ({ draggableInfo, dragResult }) => { - const { addedIndex, removedIndex, elementSize, pos, shadowBeginEnd } = dragResult; - if (pos !== null) { - if (addedIndex !== null && (draggableInfo.invalidateShadow || addedIndex !== prevAddedIndex)) { - if (prevAddedIndex) prevAddedIndex = addedIndex; - let beforeIndex = addedIndex - 1; - let begin = 0; - let afterBounds = null; - let beforeBounds = null; - if (beforeIndex === removedIndex) { - beforeIndex--; - } - if (beforeIndex > -1) { - const beforeSize = layout.getSize(draggables[beforeIndex]); - beforeBounds = layout.getBeginEnd(draggables[beforeIndex]); - if (elementSize < beforeSize) { - const threshold = (beforeSize - elementSize) / 2; - begin = beforeBounds.end - threshold; - } else { - begin = beforeBounds.end; - } - } else { - beforeBounds = { end: layout.getBeginEndOfContainer().begin }; - } - - let end = 10000; - let afterIndex = addedIndex; - if (afterIndex === removedIndex) { - afterIndex++; - } - if (afterIndex < draggables.length) { - const afterSize = layout.getSize(draggables[afterIndex]); - afterBounds = layout.getBeginEnd(draggables[afterIndex]); - - if (elementSize < afterSize) { - const threshold = (afterSize - elementSize) / 2; - end = afterBounds.begin + threshold; - } else { - end = afterBounds.begin; - } - } else { - afterBounds = { begin: layout.getContainerRectangles().end }; - } - - const shadowRectTopLeft = - beforeBounds && afterBounds ? layout.getTopLeftOfElementBegin(beforeBounds.end, afterBounds.begin) : null; - - return { - shadowBeginEnd: { - begin, - end, - rect: shadowRectTopLeft, - beginAdjustment: shadowBeginEnd ? shadowBeginEnd.beginAdjustment : 0 - } - }; - } else { - return null; - } - } else { - prevAddedIndex = null; - return { - shadowBeginEnd: null - }; - } - }; -} - -function handleFirstInsertShadowAdjustment() { - let lastAddedIndex = null; - return ({ dragResult: { pos, addedIndex, shadowBeginEnd }, draggableInfo: { invalidateShadow } }) => { - if (pos !== null) { - if (addedIndex != null && lastAddedIndex === null) { - if (pos < shadowBeginEnd.begin) { - const beginAdjustment = pos - shadowBeginEnd.begin - 5; - shadowBeginEnd.beginAdjustment = beginAdjustment; - } - lastAddedIndex = addedIndex; - } - } else { - lastAddedIndex = null; - } - }; -} - -function fireDragEnterLeaveEvents({ options }) { - let wasDragIn = false; - return ({ dragResult: { pos } }) => { - const isDragIn = !!pos; - if (isDragIn !== wasDragIn) { - wasDragIn = isDragIn; - if (isDragIn) { - options.onDragEnter && options.onDragEnter(); - } else { - options.onDragLeave && options.onDragLeave(); - return { - dragLeft: true - }; - } - } - }; -} - -function fireOnDropReady({ options }) { - let lastAddedIndex = null; - return ({ dragResult: { addedIndex, removedIndex }, draggableInfo: { payload, element } }) => { - if (options.onDropReady && lastAddedIndex !== addedIndex) { - lastAddedIndex = addedIndex; - let adjustedAddedIndex = addedIndex; - - if (removedIndex !== null && addedIndex > removedIndex) { - adjustedAddedIndex--; - } - - options.onDropReady({ addedIndex: adjustedAddedIndex, removedIndex, payload, element: element.firstElementChild }); - } - } -} - -function getDragHandler(params) { - if (params.options.behaviour === 'drop-zone') { - // sorting is disabled in container, addedIndex will always be 0 if dropped in - return compose(params)( - getRemovedItem, - setRemovedItemVisibilty, - getPosition, - notifyParentOnPositionCapture, - getElementSize, - handleTargetContainer, - getDragInsertionIndexForDropZone, - getShadowBeginEndForDropZone, - fireDragEnterLeaveEvents, - fireOnDropReady - ); - } else { - return compose(params)( - getRemovedItem, - setRemovedItemVisibilty, - getPosition, - notifyParentOnPositionCapture, - getElementSize, - handleTargetContainer, - invalidateShadowBeginEndIfNeeded, - getNextAddedIndex, - resetShadowAdjustment, - handleInsertionSizeChange, - calculateTranslations, - getShadowBeginEnd, - handleFirstInsertShadowAdjustment, - fireDragEnterLeaveEvents, - fireOnDropReady - ); - } -} - -function getDefaultDragResult() { - return { - addedIndex: null, - removedIndex: null, - elementSize: null, - pos: null, - shadowBeginEnd: null - }; -} - -function compose(params) { - return (...functions) => { - const hydratedFunctions = functions.map(p => p(params)); - let result = null; - return draggableInfo => { - result = hydratedFunctions.reduce((dragResult, fn) => { - return Object.assign(dragResult, fn({ draggableInfo, dragResult })); - }, result || getDefaultDragResult()); - return result; - }; - }; -} - -// Container definition begin -function Container(element) { - return function(options) { - let dragResult = null; - let lastDraggableInfo = null; - const props = getContainerProps(element, options); - let dragHandler = getDragHandler(props); - let dropHandler = handleDrop(props); - let parentContainer = null; - let posIsInChildContainer = false; - let childContainers = []; - - function processLastDraggableInfo() { - if (lastDraggableInfo !== null) { - lastDraggableInfo.invalidateShadow = true; - dragResult = dragHandler(lastDraggableInfo); - lastDraggableInfo.invalidateShadow = false; - } - } - - function onChildPositionCaptured(isCaptured) { - posIsInChildContainer = isCaptured; - if (parentContainer) { - parentContainer.onChildPositionCaptured(isCaptured); - if (lastDraggableInfo) { - dragResult = dragHandler(lastDraggableInfo); - } - } - } - - function setDraggables(draggables, element, options) { - const newDraggables = wrapChildren(element, options.orientation, options.animationDuration); - for (let i = 0; i < newDraggables.length; i++) { - draggables[i] = newDraggables[i]; - } - - for (let i = 0; i < draggables.length - newDraggables.length; i++) { - draggables.pop(); - } - } - - function prepareDrag(container, relevantContainers) { - const element = container.element; - const draggables = props.draggables; - const options = container.getOptions(); - setDraggables(draggables, element, options); - container.layout.invalidateRects(); - registerToParentContainer(container, relevantContainers); - draggables.forEach(p => setAnimation(p, true, options.animationDuration)); - } - - props.layout.setScrollListener(function() { - processLastDraggableInfo(); - }); - - function handleDragLeftDeferedTranslation() { - if (dragResult.dragLeft && props.options.behaviour !== 'drop-zone') { - dragResult.dragLeft = false; - setTimeout(() => { - if (dragResult) calculateTranslations(props)({ dragResult }); - }, 20); - } - } - - function dispose(container) { - unwrapChildren(container.element); - } - - return { - element, - draggables: props.draggables, - isDragRelevant: isDragRelevant(props), - getScale: props.layout.getContainerScale, - layout: props.layout, - getChildContainers: () => childContainers, - onChildPositionCaptured, - dispose, - prepareDrag, - isPosInChildContainer: () => posIsInChildContainer, - handleDrag: function(draggableInfo) { - lastDraggableInfo = draggableInfo; - dragResult = dragHandler(draggableInfo); - handleDragLeftDeferedTranslation(); - return dragResult; - }, - handleDrop: function(draggableInfo) { - lastDraggableInfo = null; - onChildPositionCaptured(false); - dragHandler = getDragHandler(props); - dropHandler(draggableInfo, dragResult); - dragResult = null; - parentContainer = null; - childContainers = []; - }, - getDragResult: function() { - return dragResult; - }, - getTranslateCalculator: function(...params) { - return calculateTranslations(props)(...params); - }, - setParentContainer: e => { - parentContainer = e; - }, - getParentContainer: () => parentContainer, - onTranslated: () => { - processLastDraggableInfo(); - }, - getOptions: () => props.options, - setDraggables: () => { - setDraggables(props.draggables, element, props.options); - } - }; - }; -} - -const options = { - behaviour: 'move', - groupName: 'bla bla', // if not defined => container will not interfere with other containers - orientation: 'vertical', - dragHandleSelector: null, - nonDragAreaSelector: 'some selector', - dragBeginDelay: 0, - animationDuration: 180, - autoScrollEnabled: true, - lockAxis: true, - dragClass: null, - dropClass: null, - onDragStart: (index, payload) => {}, - onDrop: ({ removedIndex, addedIndex, payload, element }) => {}, - getChildPayload: index => null, - shouldAnimateDrop: (sourceContainerOptions, payload) => true, - shouldAcceptDrop: (sourceContainerOptions, payload) => true, - onDragEnter: () => {}, - onDragLeave: () => { }, - onDropReady: ({ removedIndex, addedIndex, payload, element }) => { }, -}; - -// exported part of container -function SmoothDnD(element, options) { - const containerIniter = Container(element); - const container = containerIniter(options); - element[containerInstance] = container; - Mediator.register(container); - return { - dispose: function() { - Mediator.unregister(container); - container.layout.dispose(); - container.dispose(container); - } - }; -} - -export default SmoothDnD; diff --git a/client/src/components/trello-board/smooth-dnd/src/dragscroller.js b/client/src/components/trello-board/smooth-dnd/src/dragscroller.js deleted file mode 100644 index 4c38c5b37..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/dragscroller.js +++ /dev/null @@ -1,208 +0,0 @@ -import { getScrollingAxis, getVisibleRect } from "./utils"; - -const maxSpeed = 1500; // px/s -// const minSpeed = 20; // px/s - -function addScrollValue(element, axis, value) { - if (element) { - if (element !== window) { - if (axis === "x") { - element.scrollLeft += value; - } else { - element.scrollTop += value; - } - } else { - if (axis === "x") { - element.scrollBy(value, 0); - } else { - element.scrollBy(0, value); - } - } - } -} - -const createAnimator = (element, axis = "y") => { - let isAnimating = false; - let request = null; - let startTime = null; - let direction = null; - let speed = null; - - function animate(_direction, _speed) { - direction = _direction; - speed = _speed; - isAnimating = true; - if (isAnimating) { - start(); - } - } - - function start() { - if (request === null) { - request = requestAnimationFrame((timestamp) => { - if (startTime === null) { - startTime = timestamp; - } - const timeDiff = timestamp - startTime; - startTime = timestamp; - let distanceDiff = (timeDiff / 1000) * speed; - distanceDiff = direction === "begin" ? 0 - distanceDiff : distanceDiff; - addScrollValue(element, axis, distanceDiff); - request = null; - start(); - }); - } - } - - function stop() { - if (isAnimating) { - cancelAnimationFrame(request); - isAnimating = false; - startTime = null; - request = null; - } - } - - return { - animate, - stop - }; -}; - -function getAutoScrollInfo(position, scrollableInfo) { - const { left, right, top, bottom } = scrollableInfo.rect; - const { x, y } = position; - if (x < left || x > right || y < top || y > bottom) { - return null; - } - - let begin; - let end; - let pos; - if (scrollableInfo.axis === "x") { - begin = left; - end = right; - pos = x; - } else { - begin = top; - end = bottom; - pos = y; - } - - const moveDistance = 100; - if (end - pos < moveDistance) { - return { - direction: "end", - speedFactor: (moveDistance - (end - pos)) / moveDistance - }; - } else if (pos - begin < moveDistance) { - // console.log(pos - begin); - return { - direction: "begin", - speedFactor: (moveDistance - (pos - begin)) / moveDistance - }; - } -} - -function scrollableInfo(element) { - const result = { - element, - rect: getVisibleRect(element, element.getBoundingClientRect()), - descendants: [], - invalidate, - axis: null, - dispose - }; - - function dispose() { - element.removeEventListener("scroll", invalidate); - } - - function invalidate() { - result.rect = getVisibleRect(element, element.getBoundingClientRect()); - result.descendants.forEach((p) => p.invalidate()); - } - - element.addEventListener("scroll", invalidate); - - return result; -} - -function handleCurrentElement(current, scrollables, firstDescendentScrollable) { - const scrollingAxis = getScrollingAxis(current); - if (scrollingAxis) { - if (!scrollables.some((p) => p.element === current)) { - const info = scrollableInfo(current); - if (firstDescendentScrollable) { - info.descendants.push(firstDescendentScrollable); - } - firstDescendentScrollable = info; - if (scrollingAxis === "xy") { - scrollables.push(Object.assign({}, info, { axis: "x" })); - scrollables.push(Object.assign({}, info, { axis: "y" }, { descendants: [] })); - } else { - scrollables.push(Object.assign({}, info, { axis: scrollingAxis })); - } - } - } - return { current: current.parentElement, firstDescendentScrollable }; -} - -function getScrollableElements(containerElements) { - const scrollables = []; - let firstDescendentScrollable = null; - containerElements.forEach((el) => { - let current = el; - firstDescendentScrollable = null; - while (current) { - const result = handleCurrentElement(current, scrollables, firstDescendentScrollable); - current = result.current; - firstDescendentScrollable = result.firstDescendentScrollable; - } - }); - return scrollables; -} -function getScrollableAnimator(scrollableInfo) { - return Object.assign(scrollableInfo, createAnimator(scrollableInfo.element, scrollableInfo.axis)); -} - -function getWindowAnimators() { - function getWindowRect() { - return { - left: 0, - right: global.innerWidth, - top: 0, - bottom: global.innerHeight - }; - } - - return [ - Object.assign({ rect: getWindowRect(), axis: "y" }, createAnimator(global)), - Object.assign({ rect: getWindowRect(), axis: "x" }, createAnimator(global, "x")) - ]; -} - -const dragScroller = (containers) => { - const scrollablesInfo = getScrollableElements(containers.map((p) => p.element)); - const animators = [...scrollablesInfo.map(getScrollableAnimator), ...getWindowAnimators()]; - return ({ draggableInfo, reset }) => { - if (animators.length) { - if (reset) { - animators.forEach((p) => p.stop()); - scrollablesInfo.forEach((p) => p.dispose()); - return null; - } - - animators.forEach((animator) => { - const scrollParams = getAutoScrollInfo(draggableInfo.mousePosition, animator); - if (scrollParams) { - animator.animate(scrollParams.direction, scrollParams.speedFactor * maxSpeed); - } else { - animator.stop(); - } - }); - } - }; -}; - -export default dragScroller; diff --git a/client/src/components/trello-board/smooth-dnd/src/dropHandlers.js b/client/src/components/trello-board/smooth-dnd/src/dropHandlers.js deleted file mode 100644 index 24fa65034..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/dropHandlers.js +++ /dev/null @@ -1,49 +0,0 @@ -import { addChildAt, removeChildAt } from './utils'; -import { - wrapperClass, - animationClass, - containersInDraggable -} from './constants'; - - -export function domDropHandler({ element, draggables, layout, options }) { - return (dropResult, onDrop) => { - const { removedIndex, addedIndex, droppedElement } = dropResult; - let removedWrapper = null; - if (removedIndex !== null) { - removedWrapper = removeChildAt(element, removedIndex); - draggables.splice(removedIndex, 1); - } - - if (addedIndex !== null) { - const wrapper = global.document.createElement('div'); - wrapper.className = `${wrapperClass}`; - wrapper.appendChild(removedWrapper && removedWrapper.firstElementChild ? removedWrapper.firstElementChild : droppedElement); - wrapper[containersInDraggable] = []; - addChildAt(element, wrapper, addedIndex); - if (addedIndex >= draggables.length) { - draggables.push(wrapper); - } else { - draggables.splice(addedIndex, 0, wrapper); - } - } - - if (onDrop) { - onDrop(dropResult); - } - }; -} - -export function reactDropHandler() { - const handler = ({ element, draggables, layout, options }) => { - return (dropResult, onDrop) => { - if (onDrop) { - onDrop(dropResult); - } - }; - }; - - return { - handler - }; -} diff --git a/client/src/components/trello-board/smooth-dnd/src/layoutManager.js b/client/src/components/trello-board/smooth-dnd/src/layoutManager.js deleted file mode 100644 index d67b3a490..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/layoutManager.js +++ /dev/null @@ -1,288 +0,0 @@ -import * as Utils from './utils'; -import { translationValue, visibilityValue, extraSizeForInsertion, containersInDraggable } from './constants'; - - - -const horizontalMap = { - size: 'offsetWidth', - distanceToParent: 'offsetLeft', - translate: 'transform', - begin: 'left', - end: 'right', - dragPosition: 'x', - scrollSize: 'scrollWidth', - offsetSize: 'offsetWidth', - scrollValue: 'scrollLeft', - scale: 'scaleX', - setSize: 'width', - setters: { - 'translate': (val) => `translate3d(${val}px, 0, 0)` - } -}; - -const verticalMap = { - size: 'offsetHeight', - distanceToParent: 'offsetTop', - translate: 'transform', - begin: 'top', - end: 'bottom', - dragPosition: 'y', - scrollSize: 'scrollHeight', - offsetSize: 'offsetHeight', - scrollValue: 'scrollTop', - scale: 'scaleY', - setSize: 'height', - setters: { - 'translate': (val) => `translate3d(0,${val}px, 0)` - } -}; - -function orientationDependentProps(map) { - function get(obj, prop) { - const mappedProp = map[prop]; - return obj[mappedProp || prop]; - } - - function set(obj, prop, value) { - requestAnimationFrame(() => { - obj[map[prop]] = map.setters[prop] ? map.setters[prop](value) : value; - }); - } - - return { get, set }; -} - -export default function layoutManager(containerElement, orientation, _animationDuration) { - containerElement[extraSizeForInsertion] = 0; - const animationDuration = _animationDuration; - const map = orientation === 'horizontal' ? horizontalMap : verticalMap; - const propMapper = orientationDependentProps(map); - const values = { - translation: 0 - }; - let registeredScrollListener = null; - - global.addEventListener('resize', function() { - invalidateContainerRectangles(containerElement); - // invalidateContainerScale(containerElement); - }); - - setTimeout(() => { - invalidate(); - }, 10); - // invalidate(); - - const scrollListener = Utils.listenScrollParent(containerElement, function() { - invalidateContainerRectangles(containerElement); - registeredScrollListener && registeredScrollListener(); - }); - function invalidate() { - invalidateContainerRectangles(containerElement); - invalidateContainerScale(containerElement); - } - - let visibleRect; - function invalidateContainerRectangles(containerElement) { - values.rect = Utils.getContainerRect(containerElement); - values.visibleRect = Utils.getVisibleRect(containerElement, values.rect); - } - - function invalidateContainerScale(containerElement) { - const rect = containerElement.getBoundingClientRect(); - values.scaleX = containerElement.offsetWidth ? ((rect.right - rect.left) / containerElement.offsetWidth) : 1; - values.scaleY = containerElement.offsetHeight ? ((rect.bottom - rect.top) / containerElement.offsetHeight) : 1; - } - - function getContainerRectangles() { - return { - rect: values.rect, - visibleRect: values.visibleRect - }; - } - - function getBeginEndOfDOMRect(rect) { - return { - begin: propMapper.get(rect, 'begin'), - end: propMapper.get(rect, 'end') - }; - } - - function getBeginEndOfContainer() { - const begin = propMapper.get(values.rect, 'begin') + values.translation; - const end = propMapper.get(values.rect, 'end') + values.translation; - return { begin, end }; - } - - function getBeginEndOfContainerVisibleRect() { - const begin = propMapper.get(values.visibleRect, 'begin') + values.translation; - const end = propMapper.get(values.visibleRect, 'end') + values.translation; - return { begin, end }; - } - - function getContainerScale() { - return { scaleX: values.scaleX, scaleY: values.scaleY }; - } - - function getSize(element) { - return propMapper.get(element, 'size') * propMapper.get(values, 'scale'); - } - - function getDistanceToOffsetParent(element) { - const distance = propMapper.get(element, 'distanceToParent') + (element[translationValue] || 0); - return distance * propMapper.get(values, 'scale'); - } - - function getBeginEnd(element) { - const begin = getDistanceToOffsetParent(element) + (propMapper.get(values.rect, 'begin') + values.translation) - propMapper.get(containerElement, 'scrollValue'); - return { - begin, - end: begin + getSize(element) * propMapper.get(values, 'scale') - }; - } - - function setSize(element, size) { - propMapper.set(element, 'setSize', size); - } - - function getAxisValue(position) { - return propMapper.get(position, 'dragPosition'); - } - - function updateDescendantContainerRects(container) { - container.layout.invalidateRects(); - container.onTranslated(); - if (container.getChildContainers()) { - container.getChildContainers().forEach(p => updateDescendantContainerRects(p)); - } - } - - function setTranslation(element, translation) { - if (!translation) { - element.style.removeProperty('transform'); - } else { - propMapper.set(element.style, 'translate', translation); - } - element[translationValue] = translation; - - if (element[containersInDraggable]) { - setTimeout(() => { - element[containersInDraggable].forEach(p => { - updateDescendantContainerRects(p); - }); - }, animationDuration + 20); - } - } - - function getTranslation(element) { - return element[translationValue]; - } - - function setVisibility(element, isVisible) { - if (element[visibilityValue] === undefined || element[visibilityValue] !== isVisible) { - if (isVisible) { - element.style.removeProperty('visibility'); - } else { - element.style.visibility = 'hidden'; - } - element[visibilityValue] = isVisible; - } - } - - function isVisible(element) { - return element[visibilityValue] === undefined || element[visibilityValue]; - } - - function isInVisibleRect(x, y) { - let { left, top, right, bottom } = values.visibleRect; - - // if there is no wrapper in rect size will be 0 and wont accept any drop - // so make sure at least there is 30px difference - if (bottom - top < 2) { - bottom = top + 30; - } - const containerRect = values.rect; - if (orientation === 'vertical') { - return x > containerRect.left && x < containerRect.right && y > top && y < bottom; - } else { - return x > left && x < right && y > containerRect.top && y < containerRect.bottom; - } - } - - function setScrollListener(callback) { - registeredScrollListener = callback; - } - - function getTopLeftOfElementBegin(begin) { - let top = 0; - let left = 0; - if (orientation === 'horizontal') { - left = begin; - top = values.rect.top; - } else { - left = values.rect.left; - top = begin; - } - - return { - top, left - }; - } - - function getScrollSize(element) { - return propMapper.get(element, 'scrollSize'); - } - - function getScrollValue(element) { - return propMapper.get(element, 'scrollValue'); - } - - function setScrollValue(element, val) { - return propMapper.set(element, 'scrollValue', val); - } - - function dispose() { - if (scrollListener) { - scrollListener.dispose(); - } - - if (visibleRect) { - visibleRect.parentNode.removeChild(visibleRect); - visibleRect = null; - } - } - - function getPosition(position) { - return isInVisibleRect(position.x, position.y) ? getAxisValue(position) : null; - } - - function invalidateRects() { - invalidateContainerRectangles(containerElement); - } - - return { - getSize, - //getDistanceToContainerBegining, - getContainerRectangles, - getBeginEndOfDOMRect, - getBeginEndOfContainer, - getBeginEndOfContainerVisibleRect, - getBeginEnd, - getAxisValue, - setTranslation, - getTranslation, - setVisibility, - isVisible, - isInVisibleRect, - dispose, - getContainerScale, - setScrollListener, - setSize, - getTopLeftOfElementBegin, - getScrollSize, - getScrollValue, - setScrollValue, - invalidate, - invalidateRects, - getPosition, - }; -} \ No newline at end of file diff --git a/client/src/components/trello-board/smooth-dnd/src/mediator.js b/client/src/components/trello-board/smooth-dnd/src/mediator.js deleted file mode 100644 index 07a1be903..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/mediator.js +++ /dev/null @@ -1,479 +0,0 @@ -import './polyfills'; -import * as Utils from './utils'; -import * as constants from './constants'; -import { addStyleToHead, addCursorStyleToBody, removeStyle } from './styles'; -import dragScroller from './dragscroller'; - -const grabEvents = ['mousedown', 'touchstart']; -const moveEvents = ['mousemove', 'touchmove']; -const releaseEvents = ['mouseup', 'touchend']; - -let dragListeningContainers = null; -let grabbedElement = null; -let ghostInfo = null; -let draggableInfo = null; -let containers = []; -let isDragging = false; -let removedElement = null; - -let handleDrag = null; -let handleScroll = null; -let sourceContainer = null; -let sourceContainerLockAxis = null; -let cursorStyleElement = null; - -// Utils.addClass(document.body, 'clearfix'); - -const isMobile = Utils.isMobile(); - -function listenEvents() { - if (typeof window !== 'undefined') { - addGrabListeners(); - } -} - -function addGrabListeners() { - grabEvents.forEach(e => { - global.document.addEventListener(e, onMouseDown, { passive: false }); - }); -} - -function addMoveListeners() { - moveEvents.forEach(e => { - global.document.addEventListener(e, onMouseMove, { passive: false }); - }); -} - -function removeMoveListeners() { - moveEvents.forEach(e => { - global.document.removeEventListener(e, onMouseMove, { passive: false }); - }); -} - -function addReleaseListeners() { - releaseEvents.forEach(e => { - global.document.addEventListener(e, onMouseUp, { passive: false }); - }); -} - -function removeReleaseListeners() { - releaseEvents.forEach(e => { - global.document.removeEventListener(e, onMouseUp, { passive: false }); - }); -} - -function getGhostParent() { - if (draggableInfo.ghostParent) { - return draggableInfo.ghostParent; - } - - if (grabbedElement) { - return grabbedElement.parentElement || global.document.body; - } else { - return global.document.body; - } -} - -function getGhostElement(wrapperElement, { x, y }, container, cursor) { - const { scaleX = 1, scaleY = 1 } = container.getScale(); - const { left, top, right, bottom } = wrapperElement.getBoundingClientRect(); - const midX = left + (right - left) / 2; - const midY = top + (bottom - top) / 2; - const ghost = wrapperElement.cloneNode(true); - ghost.style.zIndex = 1000; - ghost.style.boxSizing = 'border-box'; - ghost.style.position = 'fixed'; - ghost.style.left = left + 'px'; - ghost.style.top = top + 'px'; - ghost.style.width = right - left + 'px'; - ghost.style.height = bottom - top + 'px'; - ghost.style.overflow = 'visible'; - ghost.style.transition = null; - ghost.style.removeProperty('transition'); - ghost.style.pointerEvents = 'none'; - - if (container.getOptions().dragClass) { - setTimeout(() => { - Utils.addClass(ghost.firstElementChild, container.getOptions().dragClass); - const dragCursor = global.getComputedStyle(ghost.firstElementChild).cursor; - cursorStyleElement = addCursorStyleToBody(dragCursor); - }); - } else { - cursorStyleElement = addCursorStyleToBody(cursor); - } - Utils.addClass(ghost, container.getOptions().orientation); - Utils.addClass(ghost, constants.ghostClass); - - return { - ghost: ghost, - centerDelta: { x: midX - x, y: midY - y }, - positionDelta: { left: left - x, top: top - y } - }; -} - -function getDraggableInfo(draggableElement) { - const container = containers.filter(p => draggableElement.parentElement === p.element)[0]; - const draggableIndex = container.draggables.indexOf(draggableElement); - const getGhostParent = container.getOptions().getGhostParent; - return { - container, - element: draggableElement, - elementIndex: draggableIndex, - payload: container.getOptions().getChildPayload - ? container.getOptions().getChildPayload(draggableIndex) - : undefined, - targetElement: null, - position: { x: 0, y: 0 }, - groupName: container.getOptions().groupName, - ghostParent: getGhostParent ? getGhostParent() : null, - }; -} - -function handleDropAnimation(callback) { - function endDrop() { - Utils.removeClass(ghostInfo.ghost, 'animated'); - ghostInfo.ghost.style.transitionDuration = null; - getGhostParent().removeChild(ghostInfo.ghost); - callback(); - } - - function animateGhostToPosition({ top, left }, duration, dropClass) { - Utils.addClass(ghostInfo.ghost, 'animated'); - if (dropClass) { - Utils.addClass(ghostInfo.ghost.firstElementChild, dropClass); - } - ghostInfo.ghost.style.transitionDuration = duration + 'ms'; - ghostInfo.ghost.style.left = left + 'px'; - ghostInfo.ghost.style.top = top + 'px'; - setTimeout(function() { - endDrop(); - }, duration + 20); - } - - function shouldAnimateDrop(options) { - return options.shouldAnimateDrop - ? options.shouldAnimateDrop(draggableInfo.container.getOptions(), draggableInfo.payload) - : true; - } - - if (draggableInfo.targetElement) { - const container = containers.filter(p => p.element === draggableInfo.targetElement)[0]; - if (shouldAnimateDrop(container.getOptions())) { - const dragResult = container.getDragResult(); - animateGhostToPosition( - dragResult.shadowBeginEnd.rect, - Math.max(150, container.getOptions().animationDuration / 2), - container.getOptions().dropClass - ); - } else { - endDrop(); - } - } else { - const container = containers.filter(p => p === draggableInfo.container)[0]; - const { behaviour, removeOnDropOut } = container.getOptions(); - if (behaviour === 'move' && !removeOnDropOut && container.getDragResult()) { - const { removedIndex, elementSize } = container.getDragResult(); - const layout = container.layout; - // drag ghost to back - container.getTranslateCalculator({ - dragResult: { - removedIndex, - addedIndex: removedIndex, - elementSize - } - }); - const prevDraggableEnd = - removedIndex > 0 - ? layout.getBeginEnd(container.draggables[removedIndex - 1]).end - : layout.getBeginEndOfContainer().begin; - animateGhostToPosition( - layout.getTopLeftOfElementBegin(prevDraggableEnd), - container.getOptions().animationDuration, - container.getOptions().dropClass - ); - } else { - Utils.addClass(ghostInfo.ghost, 'animated'); - ghostInfo.ghost.style.transitionDuration = container.getOptions().animationDuration + 'ms'; - ghostInfo.ghost.style.opacity = '0'; - ghostInfo.ghost.style.transform = 'scale(0.90)'; - setTimeout(function() { - endDrop(); - }, container.getOptions().animationDuration); - } - } -} - -const handleDragStartConditions = (function handleDragStartConditions() { - let startEvent; - let delay; - let clb; - let timer = null; - const moveThreshold = 1; - const maxMoveInDelay = 5; - - function onMove(event) { - const { clientX: currentX, clientY: currentY } = getPointerEvent(event); - if (!delay) { - if ( - Math.abs(startEvent.clientX - currentX) > moveThreshold || - Math.abs(startEvent.clientY - currentY) > moveThreshold - ) { - return callCallback(); - } - } else { - if ( - Math.abs(startEvent.clientX - currentX) > maxMoveInDelay || - Math.abs(startEvent.clientY - currentY) > maxMoveInDelay - ) { - deregisterEvent(); - } - } - } - - function onUp() { - deregisterEvent(); - } - function onHTMLDrag() { - deregisterEvent(); - } - - function registerEvents() { - if (delay) { - timer = setTimeout(callCallback, delay); - } - - moveEvents.forEach(e => global.document.addEventListener(e, onMove), { - passive: false - }); - releaseEvents.forEach(e => global.document.addEventListener(e, onUp), { - passive: false - }); - global.document.addEventListener('drag', onHTMLDrag, { - passive: false - }); - } - - function deregisterEvent() { - clearTimeout(timer); - moveEvents.forEach(e => global.document.removeEventListener(e, onMove), { - passive: false - }); - releaseEvents.forEach(e => global.document.removeEventListener(e, onUp), { - passive: false - }); - global.document.removeEventListener('drag', onHTMLDrag, { - passive: false - }); - } - - function callCallback() { - clearTimeout(timer); - deregisterEvent(); - clb(); - } - - return function(_startEvent, _delay, _clb) { - startEvent = getPointerEvent(_startEvent); - delay = (typeof _delay === 'number') ? _delay : (isMobile ? 200 : 0); - clb = _clb; - - registerEvents(); - }; -})(); - -function onMouseDown(event) { - const e = getPointerEvent(event); - if (!isDragging && (e.button === undefined || e.button === 0)) { - grabbedElement = Utils.getParent(e.target, '.' + constants.wrapperClass); - if (grabbedElement) { - const containerElement = Utils.getParent(grabbedElement, '.' + constants.containerClass); - const container = containers.filter(p => p.element === containerElement)[0]; - const dragHandleSelector = container.getOptions().dragHandleSelector; - const nonDragAreaSelector = container.getOptions().nonDragAreaSelector; - - let startDrag = true; - if (dragHandleSelector && !Utils.getParent(e.target, dragHandleSelector)) { - startDrag = false; - } - - if (nonDragAreaSelector && Utils.getParent(e.target, nonDragAreaSelector)) { - startDrag = false; - } - - if (startDrag) { - handleDragStartConditions(e, container.getOptions().dragBeginDelay, () => { - Utils.clearSelection(); - initiateDrag(e, Utils.getElementCursor(event.target)); - addMoveListeners(); - addReleaseListeners(); - }); - } - } - } -} - -function onMouseUp() { - removeMoveListeners(); - removeReleaseListeners(); - handleScroll({ reset: true }); - if (cursorStyleElement) { - removeStyle(cursorStyleElement); - cursorStyleElement = null; - } - if (draggableInfo) { - handleDropAnimation(() => { - Utils.removeClass(global.document.body, constants.disbaleTouchActions); - Utils.removeClass(global.document.body, constants.noUserSelectClass); - fireOnDragStartEnd(false); - (dragListeningContainers || []).forEach(p => { - p.handleDrop(draggableInfo); - }); - - dragListeningContainers = null; - grabbedElement = null; - ghostInfo = null; - draggableInfo = null; - isDragging = false; - sourceContainer = null; - sourceContainerLockAxis = null; - handleDrag = null; - }); - } -} - -function getPointerEvent(e) { - return e.touches ? e.touches[0] : e; -} - -function dragHandler(dragListeningContainers) { - let targetContainers = dragListeningContainers; - return function(draggableInfo) { - let containerBoxChanged = false; - targetContainers.forEach(p => { - const dragResult = p.handleDrag(draggableInfo); - containerBoxChanged |= dragResult.containerBoxChanged || false; - dragResult.containerBoxChanged = false; - }); - handleScroll({ draggableInfo }); - - if (containerBoxChanged) { - containerBoxChanged = false; - setTimeout(() => { - containers.forEach(p => { - p.layout.invalidateRects(); - p.onTranslated(); - }); - }, 10); - } - }; -} - -function getScrollHandler(container, dragListeningContainers) { - if (container.getOptions().autoScrollEnabled) { - return dragScroller(dragListeningContainers); - } else { - return () => null; - } -} - -function fireOnDragStartEnd(isStart) { - containers.forEach(p => { - const fn = isStart ? p.getOptions().onDragStart : p.getOptions().onDragEnd; - if (fn) { - const options = { - isSource: p === draggableInfo.container, - payload: draggableInfo.payload - }; - if (p.isDragRelevant(draggableInfo.container, draggableInfo.payload)) { - options.willAcceptDrop = true; - } else { - options.willAcceptDrop = false; - } - fn(options); - } - }); -} - -function initiateDrag(position, cursor) { - isDragging = true; - const container = containers.filter(p => grabbedElement.parentElement === p.element)[0]; - container.setDraggables(); - sourceContainer = container; - sourceContainerLockAxis = container.getOptions().lockAxis ? container.getOptions().lockAxis.toLowerCase() : null; - - draggableInfo = getDraggableInfo(grabbedElement); - ghostInfo = getGhostElement( - grabbedElement, - { x: position.clientX, y: position.clientY }, - draggableInfo.container, - cursor - ); - draggableInfo.position = { - x: position.clientX + ghostInfo.centerDelta.x, - y: position.clientY + ghostInfo.centerDelta.y - }; - draggableInfo.mousePosition = { - x: position.clientX, - y: position.clientY - }; - - Utils.addClass(global.document.body, constants.disbaleTouchActions); - Utils.addClass(global.document.body, constants.noUserSelectClass); - - dragListeningContainers = containers.filter(p => p.isDragRelevant(container, draggableInfo.payload)); - handleDrag = dragHandler(dragListeningContainers); - if (handleScroll) { - handleScroll({ reset: true }); - } - handleScroll = getScrollHandler(container, dragListeningContainers); - dragListeningContainers.forEach(p => p.prepareDrag(p, dragListeningContainers)); - fireOnDragStartEnd(true); - handleDrag(draggableInfo); - getGhostParent().appendChild(ghostInfo.ghost); -} - -function onMouseMove(event) { - event.preventDefault(); - const e = getPointerEvent(event); - if (!draggableInfo) { - initiateDrag(e, Utils.getElementCursor(event.target)); - } else { - // just update ghost position && draggableInfo position - if (sourceContainerLockAxis) { - if (sourceContainerLockAxis === 'y') { - ghostInfo.ghost.style.top = `${e.clientY + ghostInfo.positionDelta.top}px`; - draggableInfo.position.y = e.clientY + ghostInfo.centerDelta.y; - draggableInfo.mousePosition.y = e.clientY; - } else if (sourceContainerLockAxis === 'x') { - ghostInfo.ghost.style.left = `${e.clientX + ghostInfo.positionDelta.left}px`; - draggableInfo.position.x = e.clientX + ghostInfo.centerDelta.x; - draggableInfo.mousePosition.x = e.clientX; - } - } else { - ghostInfo.ghost.style.left = `${e.clientX + ghostInfo.positionDelta.left}px`; - ghostInfo.ghost.style.top = `${e.clientY + ghostInfo.positionDelta.top}px`; - draggableInfo.position.x = e.clientX + ghostInfo.centerDelta.x; - draggableInfo.position.y = e.clientY + ghostInfo.centerDelta.y; - draggableInfo.mousePosition.x = e.clientX; - draggableInfo.mousePosition.y = e.clientY; - } - - handleDrag(draggableInfo); - } -} - -function Mediator() { - listenEvents(); - return { - register: function(container) { - containers.push(container); - }, - unregister: function(container) { - containers.splice(containers.indexOf(container), 1); - } - }; -} - -addStyleToHead(); - -export default Mediator(); diff --git a/client/src/components/trello-board/smooth-dnd/src/polyfills.js b/client/src/components/trello-board/smooth-dnd/src/polyfills.js deleted file mode 100644 index 3999fc507..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/polyfills.js +++ /dev/null @@ -1,17 +0,0 @@ -(function(constructor) { - if (constructor && constructor.prototype && !constructor.prototype.matches) { - constructor.prototype.matches = - constructor.prototype.matchesSelector || - constructor.prototype.mozMatchesSelector || - constructor.prototype.msMatchesSelector || - constructor.prototype.oMatchesSelector || - constructor.prototype.webkitMatchesSelector || - function(s) { - var matches = (this.document || this.ownerDocument).querySelectorAll(s), - i = matches.length; - while (--i >= 0 && matches.item(i) !== this) {} - return i > -1; - }; - } -})(global.Node || global.Element); - diff --git a/client/src/components/trello-board/smooth-dnd/src/styles.js b/client/src/components/trello-board/smooth-dnd/src/styles.js deleted file mode 100644 index 01d9b9e25..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/styles.js +++ /dev/null @@ -1,118 +0,0 @@ -import * as constants from "./constants"; - -const verticalWrapperClass = { - overflow: "hidden", - display: "block" -}; - -const horizontalWrapperClass = { - height: "100%", - display: "inline-block", - "vertical-align": "top", - "white-space": "normal" -}; - -const stretcherElementHorizontalClass = { - display: "inline-block" -}; - -const css = { - [`.${constants.containerClass}`]: { - position: "relative" - }, - [`.${constants.containerClass} *`]: { - "box-sizing": "border-box" - }, - [`.${constants.containerClass}.horizontal`]: { - "white-space": "nowrap" - }, - [`.${constants.containerClass}.horizontal > .${constants.stretcherElementClass}`]: stretcherElementHorizontalClass, - [`.${constants.containerClass}.horizontal > .${constants.wrapperClass}`]: horizontalWrapperClass, - [`.${constants.containerClass}.vertical > .${constants.wrapperClass}`]: verticalWrapperClass, - [`.${constants.wrapperClass}`]: { - // 'overflow': 'hidden' - }, - [`.${constants.wrapperClass}.horizontal`]: horizontalWrapperClass, - [`.${constants.wrapperClass}.vertical`]: verticalWrapperClass, - [`.${constants.wrapperClass}.animated`]: { - transition: "transform ease" - }, - [`.${constants.ghostClass} *`]: { - //'perspective': '800px', - "box-sizing": "border-box" - }, - [`.${constants.ghostClass}.animated`]: { - transition: "all ease-in-out" - }, - [`.${constants.disbaleTouchActions} *`]: { - "touch-actions": "none", - "-ms-touch-actions": "none" - }, - [`.${constants.noUserSelectClass} *`]: { - "-webkit-touch-callout": "none", - "-webkit-user-select": "none", - "-khtml-user-select": "none", - "-moz-user-select": "none", - "-ms-user-select": "none", - "user-select": "none" - } -}; - -function convertToCssString(css) { - return Object.keys(css).reduce((styleString, propName) => { - const propValue = css[propName]; - if (typeof propValue === "object") { - return `${styleString}${propName}{${convertToCssString(propValue)}}`; - } - return `${styleString}${propName}:${propValue};`; - }, ""); -} - -function addStyleToHead() { - if (typeof window !== "undefined") { - const head = global.document.head || global.document.getElementsByTagName("head")[0]; - const style = global.document.createElement("style"); - const cssString = convertToCssString(css); - style.type = "text/css"; - if (style.styleSheet) { - style.styleSheet.cssText = cssString; - } else { - style.appendChild(global.document.createTextNode(cssString)); - } - - head.appendChild(style); - } -} - -function addCursorStyleToBody(cursor) { - if (cursor && typeof window !== "undefined") { - const head = global.document.head || global.document.getElementsByTagName("head")[0]; - const style = global.document.createElement("style"); - const cssString = convertToCssString({ - "body *": { - cursor: `${cursor} !important` - } - }); - style.type = "text/css"; - if (style.styleSheet) { - style.styleSheet.cssText = cssString; - } else { - style.appendChild(global.document.createTextNode(cssString)); - } - - head.appendChild(style); - - return style; - } - - return null; -} - -function removeStyle(styleElement) { - if (styleElement && typeof window !== "undefined") { - const head = global.document.head || global.document.getElementsByTagName("head")[0]; - head.removeChild(styleElement); - } -} - -export { addStyleToHead, addCursorStyleToBody, removeStyle }; diff --git a/client/src/components/trello-board/smooth-dnd/src/utils.js b/client/src/components/trello-board/smooth-dnd/src/utils.js deleted file mode 100644 index 5c420520a..000000000 --- a/client/src/components/trello-board/smooth-dnd/src/utils.js +++ /dev/null @@ -1,282 +0,0 @@ -export const getIntersection = (rect1, rect2) => { - return { - left: Math.max(rect1.left, rect2.left), - top: Math.max(rect1.top, rect2.top), - right: Math.min(rect1.right, rect2.right), - bottom: Math.min(rect1.bottom, rect2.bottom) - }; -}; - -export const getIntersectionOnAxis = (rect1, rect2, axis) => { - if (axis === "x") { - return { - left: Math.max(rect1.left, rect2.left), - top: rect1.top, - right: Math.min(rect1.right, rect2.right), - bottom: rect1.bottom - }; - } else { - return { - left: rect1.left, - top: Math.max(rect1.top, rect2.top), - right: rect1.right, - bottom: Math.min(rect1.bottom, rect2.bottom) - }; - } -}; - -export const getContainerRect = element => { - const _rect = element.getBoundingClientRect(); - const rect = { - left: _rect.left, - right: _rect.right + 10, - top: _rect.top, - bottom: _rect.bottom - }; - - if (hasBiggerChild(element, "x") && !isScrollingOrHidden(element, "x")) { - const width = rect.right - rect.left; - rect.right = rect.right + element.scrollWidth - width; - } - - if (hasBiggerChild(element, "y") && !isScrollingOrHidden(element, "y")) { - const height = rect.bottom - rect.top; - rect.bottom = rect.bottom + element.scrollHeight - height; - } - - return rect; -}; - -export const getScrollingAxis = element => { - const style = global.getComputedStyle(element); - const overflow = style["overflow"]; - const general = overflow === "auto" || overflow === "scroll"; - if (general) return "xy"; - const overFlowX = style[`overflow-x`]; - const xScroll = overFlowX === "auto" || overFlowX === "scroll"; - const overFlowY = style[`overflow-y`]; - const yScroll = overFlowY === "auto" || overFlowY === "scroll"; - - return `${xScroll ? "x" : ""}${yScroll ? "y" : ""}` || null; -}; - -export const isScrolling = (element, axis) => { - const style = global.getComputedStyle(element); - const overflow = style["overflow"]; - const overFlowAxis = style[`overflow-${axis}`]; - const general = overflow === "auto" || overflow === "scroll"; - const dimensionScroll = overFlowAxis === "auto" || overFlowAxis === "scroll"; - return general || dimensionScroll; -}; - -export const isScrollingOrHidden = (element, axis) => { - const style = global.getComputedStyle(element); - const overflow = style["overflow"]; - const overFlowAxis = style[`overflow-${axis}`]; - const general = - overflow === "auto" || overflow === "scroll" || overflow === "hidden"; - const dimensionScroll = - overFlowAxis === "auto" || - overFlowAxis === "scroll" || - overFlowAxis === "hidden"; - return general || dimensionScroll; -}; - -export const hasBiggerChild = (element, axis) => { - if (axis === "x") { - return element.scrollWidth > element.clientWidth; - } else { - return element.scrollHeight > element.clientHeight; - } -}; - -export const hasScrollBar = (element, axis) => { - return hasBiggerChild(element, axis) && isScrolling(element, axis); -}; - -export const getVisibleRect = (element, elementRect) => { - let currentElement = element; - let rect = elementRect || getContainerRect(element); - currentElement = element.parentElement; - while (currentElement) { - if ( - hasBiggerChild(currentElement, "x") && - isScrollingOrHidden(currentElement, "x") - ) { - rect = getIntersectionOnAxis( - rect, - currentElement.getBoundingClientRect(), - "x" - ); - } - - if ( - hasBiggerChild(currentElement, "y") && - isScrollingOrHidden(currentElement, "y") - ) { - rect = getIntersectionOnAxis( - rect, - currentElement.getBoundingClientRect(), - "y" - ); - } - - currentElement = currentElement.parentElement; - } - - return rect; -}; - -export const listenScrollParent = (element, clb) => { - let scrollers = []; - const dispose = () => { - scrollers.forEach(p => { - p.removeEventListener("scroll", clb); - }); - global.removeEventListener("scroll", clb); - }; - - setTimeout(function() { - let currentElement = element; - while (currentElement) { - if ( - isScrolling(currentElement, "x") || - isScrolling(currentElement, "y") - ) { - currentElement.addEventListener("scroll", clb); - scrollers.push(currentElement); - } - currentElement = currentElement.parentElement; - } - - global.addEventListener("scroll", clb); - }, 10); - - return { - dispose - }; -}; - -export const hasParent = (element, parent) => { - let current = element; - while (current) { - if (current === parent) { - return true; - } - current = current.parentElement; - } - return false; -}; - -export const getParent = (element, selector) => { - let current = element; - while (current) { - if (current.matches(selector)) { - return current; - } - current = current.parentElement; - } - - return null; -}; - -export const hasClass = (element, cls) => { - return ( - element.className - .split(" ") - .map(p => p) - .indexOf(cls) > -1 - ); -}; - -export const addClass = (element, cls) => { - if (element) { - element.className = element.className || '' - const classes = element.className.split(" ").filter(p => p); - if (classes.indexOf(cls) === -1) { - classes.unshift(cls); - element.className = classes.join(" "); - } - } -}; - -export const removeClass = (element, cls) => { - if (element) { - const classes = element.className.split(" ").filter(p => p && p !== cls); - element.className = classes.join(" "); - } -}; - -export const debounce = (fn, delay, immediate) => { - let timer = null; - return (...params) => { - if (timer) { - clearTimeout(timer); - } - if (immediate && !timer) { - fn.call(this, ...params); - } else { - timer = setTimeout(() => { - timer = null; - fn.call(this, ...params); - }, delay); - } - }; -}; - -export const removeChildAt = (parent, index) => { - return parent.removeChild(parent.children[index]); -}; - -export const addChildAt = (parent, child, index) => { - if (index >= parent.children.lenght) { - parent.appendChild(child); - } else { - parent.insertBefore(child, parent.children[index]); - } -}; - -export const isMobile = () => { - if (typeof window !== 'undefined') { - if ( - global.navigator.userAgent.match(/Android/i) || - global.navigator.userAgent.match(/webOS/i) || - global.navigator.userAgent.match(/iPhone/i) || - global.navigator.userAgent.match(/iPad/i) || - global.navigator.userAgent.match(/iPod/i) || - global.navigator.userAgent.match(/BlackBerry/i) || - global.navigator.userAgent.match(/Windows Phone/i) - ) { - return true; - } else { - return false; - } - } - return false; -}; - -export const clearSelection = () => { - if (global.getSelection) { - if (global.getSelection().empty) { - // Chrome - global.getSelection().empty(); - } else if (global.getSelection().removeAllRanges) { - // Firefox - global.getSelection().removeAllRanges(); - } - } else if (global.document.selection) { - // IE? - global.document.selection.empty(); - } -}; - -export const getElementCursor = (element) => { - if (element) { - const style = global.getComputedStyle(element); - if (style) { - return style.cursor; - } - } - - return null; -} diff --git a/client/src/components/trello-board/styles/Base.js b/client/src/components/trello-board/styles/Base.js index df4010e2e..771ffc80d 100644 --- a/client/src/components/trello-board/styles/Base.js +++ b/client/src/components/trello-board/styles/Base.js @@ -82,30 +82,12 @@ export const StyleVertical = styled.div` // TODO ? This is the question. We need the same drag-zone we get in horizontal mode min-height: 50px; // Not needed, just for extra landing space } - .smooth-dnd-container.horizontal { - // TODO: This is what is currently providing us multi row cols, and may need to be adjusted with new DND Library - display: flex; /* Allows wrapping */ - flex-wrap: wrap; /* Allows wrapping */ - //background-color: yellow !important; - } - .smooth-dnd-ghost { - //background-color: red !important; - } .react-trello-card { //background-color: orange !important; - margin: 5px; - // TODO: This is what is currently providing us multi row cols, and may need to be adjusted with new DND Library flex: 0 1 auto; } - .smooth-dnd-stretcher-element { - //background-color: purple !important; - } - .smooth-dnd-draggable-wrapper { - //background-color: blue !important; - flex: 0 1 auto; /* Allows items to grow and shrink */ - } .react-trello-board { - overflow-y: hidden !important; + display: flex; } `;