diff --git a/examples/editor/basic-drag-editor/editPolicies.js b/examples/editor/basic-drag-editor/editPolicies.js index a3beb1a..e54c9e3 100644 --- a/examples/editor/basic-drag-editor/editPolicies.js +++ b/examples/editor/basic-drag-editor/editPolicies.js @@ -2,13 +2,16 @@ import { moveBox } from '@regraph/editor/actions'; const editPolicies = { node: { - move: { - drag: event => - moveBox({ - id: event.source.id, - delta: event.delta, - }), - }, + move: dispatch => ({ + drag: event => { + dispatch( + moveBox({ + id: event.source.id, + delta: event.delta, + }) + ); + }, + }), }, }; diff --git a/examples/editor/chip-editor/editPolicies.js b/examples/editor/chip-editor/editPolicies.js index ab7dd42..b271afe 100644 --- a/examples/editor/chip-editor/editPolicies.js +++ b/examples/editor/chip-editor/editPolicies.js @@ -24,8 +24,9 @@ import { targetifyNode, targetifyConnection } from './targetify'; const getEndId = end => `${end.id}/${end.port}`; const generateId = ({ src, dst }) => `${getEndId(src)}->${getEndId(dst)}`; -const setSelection = (action, selected) => target => - action({ ids: [target.id], updates: { selected } }); +const setSelection = (action, selected) => dispatch => target => { + dispatch(action({ ids: [target.id], updates: { selected } })); +}; const getEnd = ({ id, port, type }) => ({ id, @@ -34,10 +35,11 @@ const getEnd = ({ id, port, type }) => ({ }); const port = { - connection: () => { + connection: (dispatch, getState) => { let beforeState; return { - start: (event, state) => { + start: event => { + const state = getState(); beforeState = state; const { connections } = state; const { source, target } = event; @@ -47,30 +49,34 @@ const port = { target.type === 'output' ? ['src', 'dst'] : ['dst', 'src']; const end = getEnd(target); - return [ + [ setNodes(nextNodes), addConnection({ id: '@@draggedConnection', [from]: end, [to]: isValid ? end : event.position, }), - ]; + ].map(dispatch); }, - drag: (event, { connections }) => { + drag: event => { + const { connections } = getState(); const isValid = isValidConnection( event.source, event.target, connections ); const end = event.source.type === 'output' ? 'dst' : 'src'; - return updateConnections({ - ids: ['@@draggedConnection'], - updates: { - [end]: isValid ? getEnd(event.target) : event.position, - }, - }); + dispatch( + updateConnections({ + ids: ['@@draggedConnection'], + updates: { + [end]: isValid ? getEnd(event.target) : event.position, + }, + }) + ); }, - end: (event, state) => { + end: event => { + const state = getState(); const { connections, nodes } = state; const isValid = isValidConnection( event.source, @@ -78,10 +84,10 @@ const port = { connections ); const nextNodes = unmarkValidPorts(nodes); - const actions = [setNodes(nextNodes)]; + dispatch(setNodes(nextNodes)); if (isValid) { const connection = getConnectionById(state, '@@draggedConnection'); - actions.push( + [ updateConnections({ ids: ['@@draggedConnection'], updates: targetifyConnection({ @@ -91,10 +97,10 @@ const port = { addCommand({ title: 'New Connection', beforeState, - }) - ); + }), + ].map(dispatch); } else { - actions.push( + dispatch( removeConnections({ ids: ['@@draggedConnection'], }) @@ -102,7 +108,6 @@ const port = { } beforeState = null; - return actions; }, }; }, @@ -112,49 +117,59 @@ const editPolicies = { connection: { select: setSelection(updateConnections, true), deselect: setSelection(updateConnections, false), - delete: target => removeConnections({ ids: [target.id] }), + delete: dispatch => target => { + dispatch(removeConnections({ ids: [target.id] })); + }, }, node: { - new: (node, state) => { + new: (dispatch, getState) => node => { const newNode = targetifyNode({ ...node, id: node.id || uuid(), }); - return [ + [ addBox({ id: newNode.id, box: { x: 20, y: 20 } }), addNode(newNode), addCommand({ title: 'New Node', - beforeState: state, + beforeState: getState(), }), - ]; + ].map(dispatch); }, select: setSelection(updateNodes, true), deselect: setSelection(updateNodes, false), - delete: (target, state) => [ - removeNodes({ ids: [target.id] }), - removeConnections({ ids: getNodeConnectionsIds(state, target.id) }), - ], - move: () => { + delete: (dispatch, getState) => target => { + [ + removeNodes({ ids: [target.id] }), + removeConnections({ + ids: getNodeConnectionsIds(getState(), target.id), + }), + ].map(dispatch); + }, + move: (dispatch, getState) => { let beforeState; let hasMoved = false; return { - start: (event, state) => { - beforeState = state; + start: () => { + beforeState = getState(); }, drag: event => { hasMoved = true; - return moveBox({ - id: event.source.id, - delta: event.delta, - }); + dispatch( + moveBox({ + id: event.source.id, + delta: event.delta, + }) + ); }, end: () => { if (hasMoved) { - return addCommand({ - title: 'Move', - beforeState, - }); + dispatch( + addCommand({ + title: 'Move', + beforeState, + }) + ); } return undefined; }, diff --git a/examples/editor/mutli-tool-editor/editPolicies.js b/examples/editor/mutli-tool-editor/editPolicies.js index 9e692de..05d698a 100644 --- a/examples/editor/mutli-tool-editor/editPolicies.js +++ b/examples/editor/mutli-tool-editor/editPolicies.js @@ -17,10 +17,10 @@ const getEnd = ({ id }) => ({ id }); const editPolicies = { background: { - create(event) { + create: dispatch => event => { const id = uuid(); const { position } = event; - return [ + [ addBox({ id, box: { @@ -31,49 +31,54 @@ const editPolicies = { }, }), addNode({ id }), - ]; + ].map(dispatch); }, }, node: { - move: { - drag: event => - moveBox({ - id: event.source.id, - delta: event.delta, - }), - }, - connection: { - start(event) { + move: dispatch => ({ + drag: event => { + dispatch( + moveBox({ + id: event.source.id, + delta: event.delta, + }) + ); + }, + }), + connection: (dispatch, getState) => ({ + start: event => { const { source, target } = event; const isValid = isValidConnection(source, target); const src = getEnd(target); - return [ + dispatch( addConnection({ id: '@@draggedConnection', src, dst: isValid ? src : event.position, - }), - ]; + }) + ); }, - drag(event) { + drag: event => { const isValid = isValidConnection(event.source, event.target); - return updateConnections({ - ids: ['@@draggedConnection'], - updates: { - dst: isValid - ? getEnd(event.target) - : { ...event.position, id: undefined }, - }, - }); + dispatch( + updateConnections({ + ids: ['@@draggedConnection'], + updates: { + dst: isValid + ? getEnd(event.target) + : { ...event.position, id: undefined }, + }, + }) + ); }, - end(event, state) { + end: event => { const isValid = isValidConnection(event.source, event.target); - const actions = []; if (isValid) { + const state = getState(); const connection = getConnectionById(state, '@@draggedConnection'); - actions.push( + dispatch( updateConnections({ ids: ['@@draggedConnection'], updates: { @@ -82,16 +87,14 @@ const editPolicies = { }) ); } else { - actions.push( + dispatch( removeConnections({ ids: ['@@draggedConnection'], }) ); } - - return actions; }, - }, + }), }, }; diff --git a/packages/editor/src/thunks/deleteSelected.js b/packages/editor/src/thunks/deleteSelected.js index 9ebac52..8443d6a 100644 --- a/packages/editor/src/thunks/deleteSelected.js +++ b/packages/editor/src/thunks/deleteSelected.js @@ -1,14 +1,13 @@ import { clearSelection, addCommand } from '../actions'; -import { ensureArray } from '../utils'; export default () => (dispatch, getState, getEditPolicies) => { const state = getState(); const { selected } = state; selected.forEach(target => { - const deletePolicy = getEditPolicies(target).delete; - if (deletePolicy) { - ensureArray(deletePolicy(target, state)).forEach(dispatch); + const policy = getEditPolicies(target).delete; + if (policy) { + policy(dispatch, getState)(target); } }); diff --git a/packages/editor/src/thunks/newNode.js b/packages/editor/src/thunks/newNode.js index 87520e1..803bb25 100644 --- a/packages/editor/src/thunks/newNode.js +++ b/packages/editor/src/thunks/newNode.js @@ -1,10 +1,6 @@ -import { ensureArray } from '../utils'; - export default node => (dispatch, getState, getEditPolicies) => { - const state = getState(); - - const newNodePolicy = getEditPolicies({ type: 'node' }).new; - if (newNodePolicy) { - ensureArray(newNodePolicy(node, state)).forEach(dispatch); + const policy = getEditPolicies({ type: 'node' }).new; + if (policy) { + policy(dispatch, getState)(node); } }; diff --git a/packages/editor/src/tools/connectionTool.js b/packages/editor/src/tools/connectionTool.js index 2934d2d..4af201a 100644 --- a/packages/editor/src/tools/connectionTool.js +++ b/packages/editor/src/tools/connectionTool.js @@ -1,6 +1,3 @@ -import { isFunction } from '@regraph/core/'; -import { ensureArray } from '../utils'; - const connectionTool = getEditPolicies => ({ dispatch, getState }) => { let source = null; let policy = null; @@ -10,12 +7,10 @@ const connectionTool = getEditPolicies => ({ dispatch, getState }) => { const { target } = action.event; action.event.source = target; policy = getEditPolicies(target).connection; - if (isFunction(policy)) { - policy = policy(); - } if (policy) { + policy = policy(dispatch, getState); source = target; - ensureArray(policy.start(action.event, getState())).forEach(dispatch); + policy.start(action.event); } break; } @@ -23,7 +18,7 @@ const connectionTool = getEditPolicies => ({ dispatch, getState }) => { case 'mouseMove': { if (policy) { action.event.source = source; - dispatch(policy.drag(action.event, getState())); + policy.drag(action.event); } break; } @@ -31,7 +26,7 @@ const connectionTool = getEditPolicies => ({ dispatch, getState }) => { case 'mouseUp': { if (policy) { action.event.source = source; - ensureArray(policy.end(action.event, getState())).forEach(dispatch); + policy.end(action.event); policy = null; } break; diff --git a/packages/editor/src/tools/creationTool.js b/packages/editor/src/tools/creationTool.js index b99beea..2529055 100644 --- a/packages/editor/src/tools/creationTool.js +++ b/packages/editor/src/tools/creationTool.js @@ -1,16 +1,13 @@ -import { ensureArray } from '../utils'; - const creationTool = getEditPolicies => ({ getState, dispatch }) => { return action => { switch (action.type) { case 'mouseUp': { const { target } = action.event; - const policies = getEditPolicies(target); - const createPolicy = policies.create; + const policy = getEditPolicies(target).create; - if (createPolicy) { - ensureArray(createPolicy(action.event, getState)).forEach(dispatch); + if (policy) { + policy(dispatch, getState)(action.event, getState); } break; } diff --git a/packages/editor/src/tools/moveSelectionTool.js b/packages/editor/src/tools/moveSelectionTool.js index cc36cf8..5f891cf 100644 --- a/packages/editor/src/tools/moveSelectionTool.js +++ b/packages/editor/src/tools/moveSelectionTool.js @@ -1,9 +1,6 @@ -import { isFunction } from '@regraph/core/'; -import { ensureArray } from '../utils'; - const moveSelectionTool = getEditPolicies => ({ getState, dispatch }) => { let selected = null; - let movePolicy; + let policy; return action => { switch (action.type) { case 'mouseDown': { @@ -13,42 +10,37 @@ const moveSelectionTool = getEditPolicies => ({ getState, dispatch }) => { const { target } = action.event; action.event.source = target; - const policies = getEditPolicies(target); - movePolicy = policies.move; - if (isFunction(movePolicy)) { - movePolicy = movePolicy(); - } + policy = getEditPolicies(target).move; - if (movePolicy && movePolicy.start) { - ensureArray(movePolicy.start(action.event, getState())).forEach( - dispatch - ); + if (policy) { + policy = policy(dispatch, getState); + if (policy.start) { + policy.start(action.event); + } } } break; } case 'mouseMove': { - if (movePolicy) { + if (policy) { selected.forEach(target => { action.event.source = target; - dispatch(movePolicy.drag(action.event)); + policy.drag(action.event); }); } break; } case 'mouseUp': { - if (movePolicy && movePolicy.end) { + if (policy && policy.end) { selected.forEach(target => { action.event.source = target; - ensureArray(movePolicy.end(action.event, getState())).forEach( - dispatch - ); + policy.end(action.event); }); } - movePolicy = null; + policy = null; break; } diff --git a/packages/editor/src/tools/moveTool.js b/packages/editor/src/tools/moveTool.js index c63a34f..a422c8f 100644 --- a/packages/editor/src/tools/moveTool.js +++ b/packages/editor/src/tools/moveTool.js @@ -1,49 +1,38 @@ -import { isFunction } from '@regraph/core/'; -import { ensureArray } from '../utils'; - const moveTool = getEditPolicies => ({ getState, dispatch }) => { - let current; - let movePolicy; + let source; + let policy; return action => { switch (action.type) { case 'mouseDown': { const { target } = action.event; action.event.source = target; - const policies = getEditPolicies(target); - movePolicy = policies.move; - if (isFunction(movePolicy)) { - movePolicy = movePolicy(); - } - - if (movePolicy && movePolicy.start) { - ensureArray(movePolicy.start(action.event, getState())).forEach( - dispatch - ); - } + policy = getEditPolicies(target).move; - if (movePolicy) { - current = target; + if (policy) { + policy = policy(dispatch, getState); + if (policy.start) { + policy.start(action.event); + } + source = target; } break; } case 'mouseMove': { - if (current && movePolicy) { - action.event.source = current; - dispatch(movePolicy.drag(action.event)); + if (policy) { + action.event.source = source; + policy.drag(action.event); } break; } case 'mouseUp': { - if (current && movePolicy && movePolicy.end) { - action.event.source = current; - ensureArray(movePolicy.end(action.event, getState())).forEach( - dispatch - ); + if (policy && policy.end) { + action.event.source = source; + policy.end(action.event); } - current = null; + policy = null; break; } diff --git a/packages/editor/src/tools/selectionTool.js b/packages/editor/src/tools/selectionTool.js index 663dfb5..bb17b21 100644 --- a/packages/editor/src/tools/selectionTool.js +++ b/packages/editor/src/tools/selectionTool.js @@ -1,19 +1,12 @@ import { select, clearSelection } from '../actions'; -import { ensureArray } from '../utils'; - -const isEmpty = collection => collection.length === 0; const isEqual = a => b => JSON.stringify(a) === JSON.stringify(b); -const deselectAll = (getEditPolicies, dispatch, selected) => { - if (isEmpty(selected)) { - return false; - } - +const deselectAll = (getEditPolicies, dispatch, getState, selected) => { selected.forEach(target => { - const { deselect: deselectPolicy } = getEditPolicies(target); - if (deselectPolicy) { - dispatch(deselectPolicy(target)); + const policy = getEditPolicies(target).deselect; + if (policy) { + policy(dispatch, getState)(target); } }); @@ -28,19 +21,17 @@ const selectionTool = getEditPolicies => ({ getState, dispatch }) => { const { target, shiftKey } = action.event; action.event.source = target; - const policies = getEditPolicies(target); - const alreadySelected = selected.some(isEqual(target)); if (!alreadySelected) { if (!shiftKey) { - deselectAll(getEditPolicies, dispatch, selected); + deselectAll(getEditPolicies, dispatch, getState, selected); } - if (policies.select) { - ensureArray( - policies.select(target, action.event, getState()) - ).forEach(dispatch); + const policy = getEditPolicies(target).select; + if (policy) { + policy(dispatch, getState)(target); + dispatch(select({ targets: [target] })); } }