diff --git a/x-pack/legacy/plugins/canvas/common/lib/constants.ts b/x-pack/legacy/plugins/canvas/common/lib/constants.ts index 3f5efd70bd4d6..83d53123ddde5 100644 --- a/x-pack/legacy/plugins/canvas/common/lib/constants.ts +++ b/x-pack/legacy/plugins/canvas/common/lib/constants.ts @@ -25,3 +25,5 @@ export const DEFAULT_WORKPAD_CSS = '.canvasPage {\n\n}'; export const DEFAULT_ELEMENT_CSS = '.canvasRenderEl{\n\n}'; export const VALID_IMAGE_TYPES = ['gif', 'jpeg', 'png', 'svg+xml']; export const ASSET_MAX_SIZE = 25000; +export const ELEMENT_SHIFT_OFFSET = 10; +export const ELEMENT_NUDGE_OFFSET = 1; diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot index 939f3fd777533..d41370f7f3558 100644 --- a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot @@ -451,6 +451,218 @@ exports[`Storyshots components/KeyboardShortcutsDoc default 1`] = ` +
+ Shift up by 10px +
+
+ + + + ↑ + + + +
+
+ Shift down by 10px +
+
+ + + + ↓ + + + +
+
+ Shift left by 10px +
+
+ + + + ← + + + +
+
+ Shift right by 10px +
+
+ + + + → + + + +
+
+ Shift up by 1px +
+
+ + + + SHIFT + + + + + + ↑ + + + +
+
+ Shift down by 1px +
+
+ + + + SHIFT + + + + + + ↓ + + + +
+
+ Shift left by 1px +
+
+ + + + SHIFT + + + + + + ← + + + +
+
+ Shift right by 1px +
+
+ + + + SHIFT + + + + + + → + + + +
({ removeNodes: (nodeIds, pageId) => dispatch(removeElements(nodeIds, pageId)), selectToplevelNodes: nodes => dispatch(selectToplevelNodes(nodes.filter(e => !e.position.parent).map(e => e.id))), - // TODO: Abstract this out, this is similar to layering code in sidebar/index.js: - elementLayer: (pageId, elementId, movement) => { - dispatch(elementLayer({ pageId, elementId, movement })); - }, + elementLayer: (pageId, elementId, movement) => + dispatch(elementLayer({ pageId, elementId, movement })), + setMultiplePositions: pageId => repositionedNodes => + dispatch( + setMultiplePositions(repositionedNodes.map(node => ({ ...node, pageId, elementId: node.id }))) + ), }); const mergeProps = ( @@ -132,6 +139,7 @@ const mergeProps = ( ...restDispatchProps, ...restStateProps, updateGlobalState: globalStateUpdater(dispatch, state), + setMultiplePositions: restDispatchProps.setMultiplePositions(ownProps.pageId), }); export const InteractivePage = compose( diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js b/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js index 881503132d233..8d32d47b4d3f7 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js @@ -47,6 +47,7 @@ export class InteractiveWorkpadPage extends PureComponent { canvasOrigin, saveCanvasOrigin, commit, + setMultiplePositions, } = this.props; let shortcuts = null; @@ -59,6 +60,7 @@ export class InteractiveWorkpadPage extends PureComponent { selectedNodes, selectToplevelNodes, commit, + setMultiplePositions, }; shortcuts = ; diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/index.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/index.tsx index e9e947ae5fd5e..dc6a90ae298ce 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/index.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/index.tsx @@ -13,13 +13,15 @@ import { basicHandlerCreators, clipboardHandlerCreators, Props as HandlerCreatorProps, + positionHandlerCreators, } from '../../lib/element_handler_creators'; export const WorkpadShortcuts = compose( withHandlers(groupHandlerCreators), withHandlers(layerHandlerCreators), withHandlers(basicHandlerCreators), - withHandlers(clipboardHandlerCreators) + withHandlers(clipboardHandlerCreators), + withHandlers(positionHandlerCreators) )(Component); WorkpadShortcuts.propTypes = { diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx index 545042eba31a8..57d637502c9a3 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx @@ -56,6 +56,38 @@ export interface Props { * ungroups selected group */ ungroupNodes: () => void; + /** + * shifts selected elements 10px up + */ + shiftUp: () => void; + /** + * shifts selected elements 10px down + */ + shiftDown: () => void; + /** + * shifts selected elements 10px left + */ + shiftLeft: () => void; + /** + * shifts selected elements 10px right + */ + shiftRight: () => void; + /** + * nudges selected elements 1px up + */ + nudgeUp: () => void; + /** + * nudges selected elements 1px down + */ + nudgeDown: () => void; + /** + * nudges selected elements 1px left + */ + nudgeLeft: () => void; + /** + * nudges selected elements 1px right + */ + nudgeRight: () => void; } export class WorkpadShortcuts extends Component { @@ -71,6 +103,14 @@ export class WorkpadShortcuts extends Component { SEND_TO_BACK: this.props.sendToBack, GROUP: this.props.groupNodes, UNGROUP: this.props.ungroupNodes, + SHIFT_UP: this.props.shiftUp, + SHIFT_DOWN: this.props.shiftDown, + SHIFT_LEFT: this.props.shiftLeft, + SHIFT_RIGHT: this.props.shiftRight, + NUDGE_UP: this.props.nudgeUp, + NUDGE_DOWN: this.props.nudgeDown, + NUDGE_LEFT: this.props.nudgeLeft, + NUDGE_RIGHT: this.props.nudgeRight, }; public render() { diff --git a/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts b/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts index ee402a07497f5..c698001e75fc0 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts +++ b/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts @@ -15,6 +15,7 @@ import { notify } from './notify'; import * as customElementService from './custom_element_service'; import { getId } from './get_id'; import { PositionedElement } from './positioned_element'; +import { ELEMENT_NUDGE_OFFSET, ELEMENT_SHIFT_OFFSET } from '../../common/lib/constants'; const extractId = (node: { id: string }): string => node.id; @@ -47,9 +48,13 @@ export interface Props { * commits events to layout engine */ commit: (eventType: string, config: { event: string }) => void; + /** + * sets new position for multiple elements + */ + setMultiplePositions: (elements: PositionedElement[]) => void; } -// handlers for clone and delete +// handlers for clone, delete, and saving custom elements export const basicHandlerCreators = { cloneNodes: ({ insertNodes, pageId, selectToplevelNodes, selectedNodes }: Props) => (): void => { const clonedNodes = selectedNodes && cloneSubgraphs(selectedNodes); @@ -154,3 +159,71 @@ export const layerHandlerCreators = { } }, }; + +// handlers for shifting elements up, down, left, and right +export const positionHandlerCreators = { + shiftUp: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.top -= ELEMENT_SHIFT_OFFSET; + return element; + }) + ); + }, + shiftDown: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.top += ELEMENT_SHIFT_OFFSET; + return element; + }) + ); + }, + shiftLeft: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.left -= ELEMENT_SHIFT_OFFSET; + return element; + }) + ); + }, + shiftRight: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.left += ELEMENT_SHIFT_OFFSET; + return element; + }) + ); + }, + nudgeUp: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.top -= ELEMENT_NUDGE_OFFSET; + return element; + }) + ); + }, + nudgeDown: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.top += ELEMENT_NUDGE_OFFSET; + return element; + }) + ); + }, + nudgeLeft: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.left -= ELEMENT_NUDGE_OFFSET; + return element; + }) + ); + }, + nudgeRight: ({ selectedNodes, setMultiplePositions }: Props) => (): void => { + setMultiplePositions( + selectedNodes.map(element => { + element.position.left += ELEMENT_NUDGE_OFFSET; + return element; + }) + ); + }, +}; diff --git a/x-pack/legacy/plugins/canvas/public/lib/keymap.ts b/x-pack/legacy/plugins/canvas/public/lib/keymap.ts index 8d1127e9e9e58..d0ee49de37f5e 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/keymap.ts +++ b/x-pack/legacy/plugins/canvas/public/lib/keymap.ts @@ -5,6 +5,7 @@ */ import { mapValues } from 'lodash'; +import { ELEMENT_NUDGE_OFFSET, ELEMENT_SHIFT_OFFSET } from '../../common/lib/constants'; export interface ShortcutMap { osx: string[]; @@ -86,6 +87,26 @@ export const keymap: KeyMap = { SEND_TO_BACK: getShortcuts('down', { modifiers: ['ctrl', 'shift'], help: 'Send to back' }), GROUP: getShortcuts('g', { help: 'Group' }), UNGROUP: getShortcuts('u', { help: 'Ungroup' }), + SHIFT_UP: getShortcuts('up', { help: `Shift up by ${ELEMENT_SHIFT_OFFSET}px` }), + SHIFT_DOWN: getShortcuts('down', { help: `Shift down by ${ELEMENT_SHIFT_OFFSET}px` }), + SHIFT_LEFT: getShortcuts('left', { help: `Shift left by ${ELEMENT_SHIFT_OFFSET}px` }), + SHIFT_RIGHT: getShortcuts('right', { help: `Shift right by ${ELEMENT_SHIFT_OFFSET}px` }), + NUDGE_UP: getShortcuts('up', { + modifiers: ['shift'], + help: `Shift up by ${ELEMENT_NUDGE_OFFSET}px`, + }), + NUDGE_DOWN: getShortcuts('down', { + modifiers: ['shift'], + help: `Shift down by ${ELEMENT_NUDGE_OFFSET}px`, + }), + NUDGE_LEFT: getShortcuts('left', { + modifiers: ['shift'], + help: `Shift left by ${ELEMENT_NUDGE_OFFSET}px`, + }), + NUDGE_RIGHT: getShortcuts('right', { + modifiers: ['shift'], + help: `Shift right by ${ELEMENT_NUDGE_OFFSET}px`, + }), }, EXPRESSION: { displayName: 'Expression controls',