mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* Fixed tooltip in fullscreen_control * Removed aeroelastic keyboard event handlers * Added input target check to workpad page keyhandler * Fixed ungrouping * Removed tabIndex * Fix: reintroduce additional call on keyboard event
This commit is contained in:
parent
5d59537338
commit
7488b22a95
7 changed files with 160 additions and 124 deletions
|
@ -25,7 +25,13 @@ export class FullscreenControl extends React.PureComponent {
|
|||
|
||||
return (
|
||||
<span>
|
||||
<Shortcuts name="EDITOR" handler={keyHandler} targetNodeSelector="body" global isolate />
|
||||
<Shortcuts
|
||||
name="PRESENTATION"
|
||||
handler={keyHandler}
|
||||
targetNodeSelector="body"
|
||||
global
|
||||
isolate
|
||||
/>
|
||||
{children({ isFullscreen, toggleFullscreen: this.toggleFullscreen })}
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -80,7 +80,7 @@ export const WorkpadHeader = ({
|
|||
<EuiFlexItem grow={false}>
|
||||
<FullscreenControl>
|
||||
{({ toggleFullscreen }) => (
|
||||
<EuiToolTip position="bottom" content="Toggle fullscreen mode">
|
||||
<EuiToolTip position="bottom" content="Enter fullscreen mode">
|
||||
<EuiButtonIcon
|
||||
iconType="fullScreen"
|
||||
aria-label="View fullscreen"
|
||||
|
|
|
@ -124,70 +124,10 @@ const handleMouseDown = (commit, e, isEditable) => {
|
|||
);
|
||||
};
|
||||
|
||||
const keyCode = key => (key === 'Meta' ? 'MetaLeft' : 'Key' + key.toUpperCase());
|
||||
|
||||
const isTextInput = ({ tagName, type }) => {
|
||||
// input types that aren't variations of text input
|
||||
const nonTextInputs = [
|
||||
'button',
|
||||
'checkbox',
|
||||
'color',
|
||||
'file',
|
||||
'image',
|
||||
'radio',
|
||||
'range',
|
||||
'reset',
|
||||
'submit',
|
||||
];
|
||||
|
||||
switch (tagName.toLowerCase()) {
|
||||
case 'input':
|
||||
return !nonTextInputs.includes(type);
|
||||
case 'textarea':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const modifierKey = key => ['KeyALT', 'KeyCONTROL'].indexOf(keyCode(key)) > -1;
|
||||
|
||||
const handleKeyDown = (commit, e, isEditable) => {
|
||||
const { key } = e;
|
||||
|
||||
if (isEditable && !modifierKey(key)) {
|
||||
commit('keyboardEvent', {
|
||||
event: 'keyDown',
|
||||
code: keyCode(key), // convert to standard event code
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyPress = (commit, e, isEditable) => {
|
||||
const { key, target } = e;
|
||||
const upcaseKey = key && key.toUpperCase();
|
||||
if (isEditable && !isTextInput(target) && 'GU'.indexOf(upcaseKey) !== -1) {
|
||||
commit('actionEvent', {
|
||||
event: upcaseKey === 'G' ? 'group' : 'ungroup',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyUp = (commit, { key }, isEditable) => {
|
||||
if (isEditable && !modifierKey(key)) {
|
||||
commit('keyboardEvent', {
|
||||
event: 'keyUp',
|
||||
code: keyCode(key), // convert to standard event code
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const eventHandlers = {
|
||||
onMouseDown: props => e => handleMouseDown(props.commit, e, props.isEditable),
|
||||
onMouseMove: props => e => handleMouseMove(props.commit, e, props.isEditable),
|
||||
onKeyDown: props => e => handleKeyDown(props.commit, e, props.isEditable),
|
||||
onKeyPress: props => e => handleKeyPress(props.commit, e, props.isEditable),
|
||||
onKeyUp: props => e => handleKeyUp(props.commit, e, props.isEditable),
|
||||
onKeyDown: props => () => props.commit('keyboardEvent'), // dummy event
|
||||
onWheel: props => e => handleWheel(props.commit, e, props.isEditable),
|
||||
resetHandler: () => () => resetHandler(),
|
||||
};
|
||||
|
|
|
@ -112,9 +112,10 @@ export const WorkpadPage = compose(
|
|||
];
|
||||
};
|
||||
|
||||
const selectedPrimaryShapeObjects = selectedPrimaryShapes.map(id =>
|
||||
shapes.find(s => s.id === id)
|
||||
);
|
||||
const selectedPrimaryShapeObjects = selectedPrimaryShapes
|
||||
.map(id => shapes.find(s => s.id === id))
|
||||
.filter(shape => shape);
|
||||
|
||||
const selectedPersistentPrimaryShapes = flatten(
|
||||
selectedPrimaryShapeObjects.map(shape =>
|
||||
shape.subtype === 'adHocGroup'
|
||||
|
@ -217,6 +218,16 @@ export const WorkpadPage = compose(
|
|||
};
|
||||
}
|
||||
), // Updates states; needs to have both local and global
|
||||
withHandlers({
|
||||
groupElements: ({ commit }) => () =>
|
||||
commit('actionEvent', {
|
||||
event: 'group',
|
||||
}),
|
||||
ungroupElements: ({ commit }) => () =>
|
||||
commit('actionEvent', {
|
||||
event: 'ungroup',
|
||||
}),
|
||||
}),
|
||||
withHandlers(eventHandlers) // Captures user intent, needs to have reconciled state
|
||||
)(Component);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import { TooltipAnnotation } from '../tooltip_annotation';
|
|||
import { RotationHandle } from '../rotation_handle';
|
||||
import { BorderConnection } from '../border_connection';
|
||||
import { BorderResizeHandle } from '../border_resize_handle';
|
||||
import { isTextInput } from '../../lib/is_text_input';
|
||||
|
||||
// NOTE: the data-shared-* attributes here are used for reporting
|
||||
export class WorkpadPage extends PureComponent {
|
||||
|
@ -39,7 +40,6 @@ export class WorkpadPage extends PureComponent {
|
|||
isEditable: PropTypes.bool.isRequired,
|
||||
onDoubleClick: PropTypes.func,
|
||||
onKeyDown: PropTypes.func,
|
||||
onKeyUp: PropTypes.func,
|
||||
onMouseDown: PropTypes.func,
|
||||
onMouseMove: PropTypes.func,
|
||||
onMouseUp: PropTypes.func,
|
||||
|
@ -72,8 +72,6 @@ export class WorkpadPage extends PureComponent {
|
|||
isEditable,
|
||||
onDoubleClick,
|
||||
onKeyDown,
|
||||
onKeyPress,
|
||||
onKeyUp,
|
||||
onMouseDown,
|
||||
onMouseMove,
|
||||
onMouseUp,
|
||||
|
@ -88,38 +86,48 @@ export class WorkpadPage extends PureComponent {
|
|||
bringToFront,
|
||||
sendBackward,
|
||||
sendToBack,
|
||||
groupElements,
|
||||
ungroupElements,
|
||||
} = this.props;
|
||||
|
||||
const keyHandler = (action, event) => {
|
||||
event.preventDefault();
|
||||
switch (action) {
|
||||
case 'COPY':
|
||||
copyElements();
|
||||
break;
|
||||
case 'CLONE':
|
||||
duplicateElements();
|
||||
break;
|
||||
case 'CUT':
|
||||
cutElements();
|
||||
break;
|
||||
case 'DELETE':
|
||||
removeElements();
|
||||
break;
|
||||
case 'PASTE':
|
||||
pasteElements();
|
||||
break;
|
||||
case 'BRING_FORWARD':
|
||||
bringForward();
|
||||
break;
|
||||
case 'BRING_TO_FRONT':
|
||||
bringToFront();
|
||||
break;
|
||||
case 'SEND_BACKWARD':
|
||||
sendBackward();
|
||||
break;
|
||||
case 'SEND_TO_BACK':
|
||||
sendToBack();
|
||||
break;
|
||||
if (!isTextInput(event.target)) {
|
||||
event.preventDefault();
|
||||
switch (action) {
|
||||
case 'COPY':
|
||||
copyElements();
|
||||
break;
|
||||
case 'CLONE':
|
||||
duplicateElements();
|
||||
break;
|
||||
case 'CUT':
|
||||
cutElements();
|
||||
break;
|
||||
case 'DELETE':
|
||||
removeElements();
|
||||
break;
|
||||
case 'PASTE':
|
||||
pasteElements();
|
||||
break;
|
||||
case 'BRING_FORWARD':
|
||||
bringForward();
|
||||
break;
|
||||
case 'BRING_TO_FRONT':
|
||||
bringToFront();
|
||||
break;
|
||||
case 'SEND_BACKWARD':
|
||||
sendBackward();
|
||||
break;
|
||||
case 'SEND_TO_BACK':
|
||||
sendToBack();
|
||||
break;
|
||||
case 'GROUP':
|
||||
groupElements();
|
||||
break;
|
||||
case 'UNGROUP':
|
||||
ungroupElements();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -137,16 +145,13 @@ export class WorkpadPage extends PureComponent {
|
|||
width,
|
||||
cursor,
|
||||
}}
|
||||
onKeyDown={onKeyDown}
|
||||
onMouseMove={onMouseMove}
|
||||
onMouseUp={onMouseUp}
|
||||
onMouseDown={onMouseDown}
|
||||
onKeyDown={onKeyDown}
|
||||
onKeyPress={onKeyPress}
|
||||
onKeyUp={onKeyUp}
|
||||
onDoubleClick={onDoubleClick}
|
||||
onAnimationEnd={onAnimationEnd}
|
||||
onWheel={onWheel}
|
||||
tabIndex={0} // needed to capture keyboard events; focusing is also needed but React apparently does so implicitly
|
||||
>
|
||||
{isEditable && (
|
||||
<Shortcuts
|
||||
|
|
29
x-pack/plugins/canvas/public/lib/is_text_input.js
Normal file
29
x-pack/plugins/canvas/public/lib/is_text_input.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
// input types that aren't variations of text input
|
||||
const nonTextInputs = [
|
||||
'button',
|
||||
'checkbox',
|
||||
'color',
|
||||
'file',
|
||||
'image',
|
||||
'radio',
|
||||
'range',
|
||||
'reset',
|
||||
'submit',
|
||||
];
|
||||
|
||||
export const isTextInput = ({ tagName, type }) => {
|
||||
switch (tagName.toLowerCase()) {
|
||||
case 'input':
|
||||
return !nonTextInputs.includes(type);
|
||||
case 'textarea':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
|
@ -38,36 +38,81 @@ const getCtrlShortcuts = shortcuts => {
|
|||
};
|
||||
};
|
||||
|
||||
const refreshShortcut = getAltShortcuts('r');
|
||||
const previousPageShortcut = getAltShortcuts('[');
|
||||
const nextPageShortcut = getAltShortcuts(']');
|
||||
const refreshShortcut = { ...getAltShortcuts('r'), help: 'Refresh workpad' };
|
||||
const previousPageShortcut = { ...getAltShortcuts('['), help: 'Go to previous page' };
|
||||
const nextPageShortcut = { ...getAltShortcuts(']'), help: 'Go to next page' };
|
||||
|
||||
export const keymap = {
|
||||
ELEMENT: {
|
||||
displayName: 'Element controls',
|
||||
COPY: { ...getCtrlShortcuts('c'), help: 'Copy' },
|
||||
CLONE: { ...getCtrlShortcuts('d'), help: 'Clone' },
|
||||
CUT: { ...getCtrlShortcuts('x'), help: 'Cut' },
|
||||
PASTE: { ...getCtrlShortcuts('v'), help: 'Paste' },
|
||||
DELETE: {
|
||||
osx: ['backspace'],
|
||||
windows: ['del', 'backspace'],
|
||||
linux: ['del', 'backspace'],
|
||||
other: ['del', 'backspace'],
|
||||
help: 'Delete',
|
||||
},
|
||||
BRING_FORWARD: {
|
||||
...getCtrlShortcuts('up'),
|
||||
help: 'Send forward',
|
||||
},
|
||||
BRING_TO_FRONT: {
|
||||
...getCtrlShortcuts('shift+up'),
|
||||
help: 'Send to front',
|
||||
},
|
||||
SEND_BACKWARD: {
|
||||
...getCtrlShortcuts('down'),
|
||||
help: 'Send backward',
|
||||
},
|
||||
SEND_TO_BACK: {
|
||||
...getCtrlShortcuts('shift+down'),
|
||||
help: 'Send to back',
|
||||
},
|
||||
GROUP: {
|
||||
osx: ['g'],
|
||||
windows: ['g'],
|
||||
linux: ['g'],
|
||||
other: ['g'],
|
||||
help: 'Group',
|
||||
},
|
||||
UNGROUP: {
|
||||
osx: ['u'],
|
||||
windows: ['u'],
|
||||
linux: ['u'],
|
||||
other: ['u'],
|
||||
help: 'Ungroup',
|
||||
},
|
||||
},
|
||||
EDITOR: {
|
||||
UNDO: getCtrlShortcuts('z'),
|
||||
REDO: getCtrlShortcuts('shift+z'),
|
||||
displayName: 'Editor controls',
|
||||
UNDO: { ...getCtrlShortcuts('z'), help: 'Undo last action' },
|
||||
REDO: { ...getCtrlShortcuts('shift+z'), help: 'Redo last action' },
|
||||
PREV: previousPageShortcut,
|
||||
NEXT: nextPageShortcut,
|
||||
FULLSCREEN: getAltShortcuts(['p', 'f']),
|
||||
FULLSCREEN_EXIT: ['escape'],
|
||||
EDITING: getAltShortcuts('e'),
|
||||
GRID: getAltShortcuts('g'),
|
||||
EDITING: { ...getAltShortcuts('e'), help: 'Toggle edit mode' },
|
||||
GRID: { ...getAltShortcuts('g'), help: 'Show grid' },
|
||||
REFRESH: refreshShortcut,
|
||||
},
|
||||
ELEMENT: {
|
||||
COPY: getCtrlShortcuts('c'),
|
||||
CLONE: getCtrlShortcuts('d'),
|
||||
CUT: getCtrlShortcuts('x'),
|
||||
PASTE: getCtrlShortcuts('v'),
|
||||
DELETE: ['del', 'backspace'],
|
||||
BRING_FORWARD: getCtrlShortcuts('up'),
|
||||
SEND_BACKWARD: getCtrlShortcuts('down'),
|
||||
BRING_TO_FRONT: getCtrlShortcuts('shift+up'),
|
||||
SEND_TO_BACK: getCtrlShortcuts('shift+down'),
|
||||
},
|
||||
PRESENTATION: {
|
||||
PREV: mapValues(previousPageShortcut, osShortcuts => osShortcuts.concat(['backspace', 'left'])),
|
||||
NEXT: mapValues(nextPageShortcut, osShortcuts => osShortcuts.concat(['space', 'right'])),
|
||||
displayName: 'Presentation mode',
|
||||
FULLSCREEN: { ...getAltShortcuts(['p', 'f']), help: 'Enter presentation mode' },
|
||||
FULLSCREEN_EXIT: {
|
||||
osx: ['esc'],
|
||||
windows: ['esc'],
|
||||
linux: ['esc'],
|
||||
other: ['esc'],
|
||||
help: 'Exit presentation mode',
|
||||
},
|
||||
PREV: mapValues(previousPageShortcut, (osShortcuts, key) =>
|
||||
key === 'help' ? osShortcuts : osShortcuts.concat(['backspace', 'left'])
|
||||
),
|
||||
NEXT: mapValues(nextPageShortcut, (osShortcuts, key) =>
|
||||
key === 'help' ? osShortcuts : osShortcuts.concat(['space', 'right'])
|
||||
),
|
||||
REFRESH: refreshShortcut,
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue