@wordpress/block-editor
Version:
8 lines (7 loc) • 7.84 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../src/components/use-moving-animation/index.js"],
"sourcesContent": ["/**\n * External dependencies\n */\nimport { Controller } from '@react-spring/web';\n\n/**\n * WordPress dependencies\n */\nimport { useLayoutEffect, useMemo, useRef } from '@wordpress/element';\nimport { getScrollContainer } from '@wordpress/dom';\nimport { useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../../store';\n\n/**\n * If the block count exceeds the threshold, we disable the reordering animation\n * to avoid laginess.\n */\nconst BLOCK_ANIMATION_THRESHOLD = 200;\n\nfunction getAbsolutePosition( element ) {\n\treturn {\n\t\ttop: element.offsetTop,\n\t\tleft: element.offsetLeft,\n\t};\n}\n\n/**\n * Hook used to compute the styles required to move a div into a new position.\n *\n * The way this animation works is the following:\n * - It first renders the element as if there was no animation.\n * - It takes a snapshot of the position of the block to use it\n * as a destination point for the animation.\n * - It restores the element to the previous position using a CSS transform\n * - It uses the \"resetAnimation\" flag to reset the animation\n * from the beginning in order to animate to the new destination point.\n *\n * @param {Object} $1 Options\n * @param {*} $1.triggerAnimationOnChange Variable used to trigger the animation if it changes.\n * @param {string} $1.clientId\n */\nfunction useMovingAnimation( { triggerAnimationOnChange, clientId } ) {\n\tconst ref = useRef();\n\tconst {\n\t\tisTyping,\n\t\tgetGlobalBlockCount,\n\t\tisBlockSelected,\n\t\tisFirstMultiSelectedBlock,\n\t\tisBlockMultiSelected,\n\t\tisAncestorMultiSelected,\n\t\tisDraggingBlocks,\n\t} = useSelect( blockEditorStore );\n\n\t// Whenever the trigger changes, we need to take a snapshot of the current\n\t// position of the block to use it as a destination point for the animation.\n\tconst { previous, prevRect } = useMemo(\n\t\t() => ( {\n\t\t\tprevious: ref.current && getAbsolutePosition( ref.current ),\n\t\t\tprevRect: ref.current && ref.current.getBoundingClientRect(),\n\t\t} ),\n\t\t[ triggerAnimationOnChange ]\n\t);\n\n\tuseLayoutEffect( () => {\n\t\tif ( ! previous || ! ref.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst scrollContainer = getScrollContainer( ref.current );\n\t\tconst isSelected = isBlockSelected( clientId );\n\t\tconst adjustScrolling =\n\t\t\tisSelected || isFirstMultiSelectedBlock( clientId );\n\t\tconst isDragging = isDraggingBlocks();\n\n\t\tfunction preserveScrollPosition() {\n\t\t\t// The user already scrolled when dragging blocks.\n\t\t\tif ( isDragging ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( adjustScrolling && prevRect ) {\n\t\t\t\tconst blockRect = ref.current.getBoundingClientRect();\n\t\t\t\tconst diff = blockRect.top - prevRect.top;\n\n\t\t\t\tif ( diff ) {\n\t\t\t\t\tscrollContainer.scrollTop += diff;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// We disable the animation if the user has a preference for reduced\n\t\t// motion, if the user is typing (insertion by Enter), or if the block\n\t\t// count exceeds the threshold (insertion caused all the blocks that\n\t\t// follow to animate).\n\t\t// To do: consider enabling the _moving_ animation even for large\n\t\t// posts, while only disabling the _insertion_ animation?\n\t\tconst disableAnimation =\n\t\t\twindow.matchMedia( '(prefers-reduced-motion: reduce)' ).matches ||\n\t\t\tisTyping() ||\n\t\t\tgetGlobalBlockCount() > BLOCK_ANIMATION_THRESHOLD;\n\n\t\tif ( disableAnimation ) {\n\t\t\t// If the animation is disabled and the scroll needs to be adjusted,\n\t\t\t// just move directly to the final scroll position.\n\t\t\tpreserveScrollPosition();\n\t\t\treturn;\n\t\t}\n\n\t\tconst isPartOfSelection =\n\t\t\tisSelected ||\n\t\t\tisBlockMultiSelected( clientId ) ||\n\t\t\tisAncestorMultiSelected( clientId );\n\n\t\t// The user already dragged the blocks to the new position, so don't\n\t\t// animate the dragged blocks.\n\t\tif ( isPartOfSelection && isDragging ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure the other blocks move under the selected block(s).\n\t\tconst zIndex = isPartOfSelection ? '1' : '';\n\n\t\tconst controller = new Controller( {\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t\tconfig: { mass: 5, tension: 2000, friction: 200 },\n\t\t\tonChange( { value } ) {\n\t\t\t\tif ( ! ref.current ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet { x, y } = value;\n\t\t\t\tx = Math.round( x );\n\t\t\t\ty = Math.round( y );\n\t\t\t\tconst finishedMoving = x === 0 && y === 0;\n\t\t\t\tref.current.style.transformOrigin = 'center center';\n\t\t\t\tref.current.style.transform = finishedMoving\n\t\t\t\t\t? null // Set to `null` to explicitly remove the transform.\n\t\t\t\t\t: `translate3d(${ x }px,${ y }px,0)`;\n\t\t\t\tref.current.style.zIndex = zIndex;\n\t\t\t\tpreserveScrollPosition();\n\t\t\t},\n\t\t} );\n\n\t\tref.current.style.transform = undefined;\n\t\tconst destination = getAbsolutePosition( ref.current );\n\n\t\tconst x = Math.round( previous.left - destination.left );\n\t\tconst y = Math.round( previous.top - destination.top );\n\n\t\tcontroller.start( { x: 0, y: 0, from: { x, y } } );\n\n\t\treturn () => {\n\t\t\tcontroller.stop();\n\t\t\tcontroller.set( { x: 0, y: 0 } );\n\t\t};\n\t}, [\n\t\tprevious,\n\t\tprevRect,\n\t\tclientId,\n\t\tisTyping,\n\t\tgetGlobalBlockCount,\n\t\tisBlockSelected,\n\t\tisFirstMultiSelectedBlock,\n\t\tisBlockMultiSelected,\n\t\tisAncestorMultiSelected,\n\t\tisDraggingBlocks,\n\t] );\n\n\treturn ref;\n}\n\nexport default useMovingAnimation;\n"],
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAA2B;AAK3B,qBAAiD;AACjD,iBAAmC;AACnC,kBAA0B;AAK1B,mBAA0C;AAM1C,IAAM,4BAA4B;AAElC,SAAS,oBAAqB,SAAU;AACvC,SAAO;AAAA,IACN,KAAK,QAAQ;AAAA,IACb,MAAM,QAAQ;AAAA,EACf;AACD;AAiBA,SAAS,mBAAoB,EAAE,0BAA0B,SAAS,GAAI;AACrE,QAAM,UAAM,uBAAO;AACnB,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,QAAI,uBAAW,aAAAA,KAAiB;AAIhC,QAAM,EAAE,UAAU,SAAS,QAAI;AAAA,IAC9B,OAAQ;AAAA,MACP,UAAU,IAAI,WAAW,oBAAqB,IAAI,OAAQ;AAAA,MAC1D,UAAU,IAAI,WAAW,IAAI,QAAQ,sBAAsB;AAAA,IAC5D;AAAA,IACA,CAAE,wBAAyB;AAAA,EAC5B;AAEA,sCAAiB,MAAM;AACtB,QAAK,CAAE,YAAY,CAAE,IAAI,SAAU;AAClC;AAAA,IACD;AAEA,UAAM,sBAAkB,+BAAoB,IAAI,OAAQ;AACxD,UAAM,aAAa,gBAAiB,QAAS;AAC7C,UAAM,kBACL,cAAc,0BAA2B,QAAS;AACnD,UAAM,aAAa,iBAAiB;AAEpC,aAAS,yBAAyB;AAEjC,UAAK,YAAa;AACjB;AAAA,MACD;AAEA,UAAK,mBAAmB,UAAW;AAClC,cAAM,YAAY,IAAI,QAAQ,sBAAsB;AACpD,cAAM,OAAO,UAAU,MAAM,SAAS;AAEtC,YAAK,MAAO;AACX,0BAAgB,aAAa;AAAA,QAC9B;AAAA,MACD;AAAA,IACD;AAQA,UAAM,mBACL,OAAO,WAAY,kCAAmC,EAAE,WACxD,SAAS,KACT,oBAAoB,IAAI;AAEzB,QAAK,kBAAmB;AAGvB,6BAAuB;AACvB;AAAA,IACD;AAEA,UAAM,oBACL,cACA,qBAAsB,QAAS,KAC/B,wBAAyB,QAAS;AAInC,QAAK,qBAAqB,YAAa;AACtC;AAAA,IACD;AAGA,UAAM,SAAS,oBAAoB,MAAM;AAEzC,UAAM,aAAa,IAAI,sBAAY;AAAA,MAClC,GAAG;AAAA,MACH,GAAG;AAAA,MACH,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAM,UAAU,IAAI;AAAA,MAChD,SAAU,EAAE,MAAM,GAAI;AACrB,YAAK,CAAE,IAAI,SAAU;AACpB;AAAA,QACD;AACA,YAAI,EAAE,GAAAC,IAAG,GAAAC,GAAE,IAAI;AACf,QAAAD,KAAI,KAAK,MAAOA,EAAE;AAClB,QAAAC,KAAI,KAAK,MAAOA,EAAE;AAClB,cAAM,iBAAiBD,OAAM,KAAKC,OAAM;AACxC,YAAI,QAAQ,MAAM,kBAAkB;AACpC,YAAI,QAAQ,MAAM,YAAY,iBAC3B,OACA,eAAgBD,EAAE,MAAOC,EAAE;AAC9B,YAAI,QAAQ,MAAM,SAAS;AAC3B,+BAAuB;AAAA,MACxB;AAAA,IACD,CAAE;AAEF,QAAI,QAAQ,MAAM,YAAY;AAC9B,UAAM,cAAc,oBAAqB,IAAI,OAAQ;AAErD,UAAM,IAAI,KAAK,MAAO,SAAS,OAAO,YAAY,IAAK;AACvD,UAAM,IAAI,KAAK,MAAO,SAAS,MAAM,YAAY,GAAI;AAErD,eAAW,MAAO,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,EAAE,GAAG,EAAE,EAAE,CAAE;AAEjD,WAAO,MAAM;AACZ,iBAAW,KAAK;AAChB,iBAAW,IAAK,EAAE,GAAG,GAAG,GAAG,EAAE,CAAE;AAAA,IAChC;AAAA,EACD,GAAG;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAE;AAEF,SAAO;AACR;AAEA,IAAO,+BAAQ;",
"names": ["blockEditorStore", "x", "y"]
}