diff --git a/packages/modifiers/index.js b/packages/modifiers/index.js index 4d7c5b9fe..4e8064121 100644 --- a/packages/modifiers/index.js +++ b/packages/modifiers/index.js @@ -1,6 +1,7 @@ import modifiers from './base'; import snap from './snap'; import snapSize from './snapSize'; +import snapEdges from './snapEdges'; import restrict from './restrict'; import restrictEdges from './restrictEdges'; import restrictSize from './restrictSize'; @@ -9,6 +10,7 @@ function init (scope) { modifiers.init(scope); snap.init(scope); snapSize.init(scope); + snapEdges.init(scope); restrict.init(scope); restrictEdges.init(scope); restrictSize.init(scope); @@ -18,6 +20,7 @@ export { modifiers, snap, snapSize, + snapEdges, restrict, restrictEdges, restrictSize, diff --git a/packages/modifiers/snapEdges.js b/packages/modifiers/snapEdges.js new file mode 100644 index 000000000..e93de91af --- /dev/null +++ b/packages/modifiers/snapEdges.js @@ -0,0 +1,50 @@ +// This module allows snapping of the edges of targets during resize +// interactions. + +import clone from '@interactjs/utils/clone'; +import extend from '@interactjs/utils/extend'; +import snapSize from './snapSize'; + +function init (scope) { + const { + modifiers, + defaults, + } = scope; + + modifiers.snapEdges = snapEdges; + modifiers.names.push('snapEdges'); + + defaults.perAction.snapEdges = snapEdges.defaults; +} + +function start (arg) { + const edges = arg.interaction.prepared.edges; + + if (!edges) { return null; } + + arg.status.targetFields = arg.status.targetFields || [ + [edges.left ? 'left' : 'right', edges.top ? 'top' : 'bottom'], + ]; + + return snapSize.start(arg); +} + +function set (arg) { + return snapSize.set(arg); +} + +function modifyCoords (arg) { + snapSize.modifyCoords(arg); +} + +const snapEdges = { + init, + start, + set, + modifyCoords, + defaults: extend(clone(snapSize.defaults), { + offset: { x: 0, y: 0 }, + }), +}; + +export default snapEdges; diff --git a/tests/modifiers/snapEdges.js b/tests/modifiers/snapEdges.js new file mode 100644 index 000000000..c6b5a3136 --- /dev/null +++ b/tests/modifiers/snapEdges.js @@ -0,0 +1,64 @@ +import test from '../test'; +import { mockSignals, mockInteractable } from '../helpers'; +import snapEdges from '@interactjs/modifiers/snapEdges'; +import Interaction from '@interactjs/core/Interaction'; +import { mockScope } from '../helpers'; + +test('modifiers/snapEdges', t => { + mockScope(); + const interaction = new Interaction({ signals: mockSignals() }); + interaction.target = mockInteractable(); + interaction.target.getRect = () => + ({ top: 0, left: 0, bottom: 100, right: 100 }); + + // resize from top left + interaction.prepared.edges = { top: true, left: true }; + interaction._interacting = true; + + const target0 = Object.freeze({ + left: 50, + right: 150, + top: 0, + bottom: 100, + }); + const options = { + targets: [ + target0, + ], + range: Infinity, + }; + const status = { + delta: { x: 0, y: 0 }, + }; + const pageCoords = Object.freeze({ x: 0, y: 0 }); + const arg = { + interaction, + options, + status, + pageCoords, + modifiedCoords: { ...pageCoords }, + offset: [{ x: 0, y: 0 }], + }; + + snapEdges.set(arg); + + t.deepEqual( + [status.modifiedX, status.modifiedY], + [target0.left - pageCoords.x, target0.top - pageCoords.y], + 'modified delta is correct'); + + // resize from bottom right + interaction.prepared.edges = { bottom: true, right: true }; + + snapEdges.set({ + ...arg, + options, + }); + + t.deepEqual( + [status.modifiedX, status.modifiedY], + [target0.right - pageCoords.x, target0.bottom - pageCoords.y], + 'modified coord is correct'); + + t.end(); +});