Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/src/services/routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import CallOutExample
import CodeExample
from '../../views/code/code_example';

import CodeEditorExample
from '../../views/code_editor/code_editor_example';

import ContextMenuExample
from '../../views/context_menu/context_menu_example';

Expand Down Expand Up @@ -131,6 +134,9 @@ const components = [{
}, {
name: 'Code',
component: CodeExample,
}, {
name: 'CodeEditor',
component: CodeEditorExample,
}, {
name: 'ContextMenu',
component: ContextMenuExample,
Expand Down
32 changes: 32 additions & 0 deletions docs/src/views/code_editor/code_editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { Component } from 'react';

import 'brace/mode/less';
import 'brace/theme/github';

import {
EuiCodeEditor,
} from '../../../../src/components';

export default class extends Component {
state = {
value: ''
};

onChange = (value) => {
this.setState({ value });
};

render() {
return (
<EuiCodeEditor
mode="less"
theme="github"
width="100%"
value={this.state.value}
onChange={this.onChange}
setOptions={{ fontSize: '14px' }}
onBlur={() => { console.log('blur'); }}
/>
);
}
}
49 changes: 49 additions & 0 deletions docs/src/views/code_editor/code_editor_example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';

import { renderToHtml } from '../../services';

import {
GuidePage,
GuideSection,
GuideSectionTypes,
} from '../../components';

import {
EuiCode,
} from '../../../../src/components';

import CodeEditor from './code_editor';
const codeEditorSource = require('!!raw-loader!./code_editor');
const codeEditorHtml = renderToHtml(CodeEditor);

export default props => (
<GuidePage title={props.route.name}>
<GuideSection
title="Code Editor"
source={[{
type: GuideSectionTypes.JS,
code: codeEditorSource,
}, {
type: GuideSectionTypes.HTML,
code: codeEditorHtml,
}]}
text={
<div>
<p>
The KuiCodeEditor component is a wrapper around <EuiCode>react-ace</EuiCode> (which
itself wraps the ACE code editor), that adds an accessible keyboard mode
to it. You should always use this component instead of <EuiCode>AceEditor</EuiCode>.
</p>
<p>
All parameters, that you specify are passed down to the
underlying <EuiCode>AceEditor</EuiCode> component.
</p>
</div>
}
demo={
<CodeEditor />
}
/>
</GuidePage>
);

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"alias": "eui"
},
"dependencies": {
"brace": "0.10.0",
"classnames": "2.2.5",
"core-js": "2.5.1",
"focus-trap-react": "3.0.4",
Expand All @@ -32,6 +33,7 @@
"lodash": "4.17.4",
"prop-types": "15.6.0",
"react": "16.0.0",
"react-ace": "5.5.0",
"react-router": "3.2.0",
"serve": "6.3.1",
"tabbable": "1.1.0",
Expand Down
16 changes: 8 additions & 8 deletions src/components/accessibility/keyboard_accessible.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export class EuiKeyboardAccessible extends Component {
if (e.keyCode === keyCodes.SPACE) {
e.preventDefault();
}

if (this.props.children.props.onKeyDown) {
this.props.children.props.onKeyDown(e);
}
}

onKeyUp = e => {
Expand All @@ -41,6 +45,10 @@ export class EuiKeyboardAccessible extends Component {
// Delegate to the click handler on the element.
this.props.children.props.onClick(e);
}

if (this.props.children.props.onKeyUp) {
this.props.children.props.onKeyUp(e);
}
}

applyKeyboardAccessibility(child) {
Expand Down Expand Up @@ -86,14 +94,6 @@ const keyboardInaccessibleElement = (props, propName, componentName) => {
if (typeof child.props.onClick !== 'function') {
throw new Error(`${componentName}'s child's onClick prop needs to be a function.`);
}

if (child.props.onKeyDown) {
throw new Error(`${componentName}'s child can't have an onKeyDown prop because the implementation will override it.`);
}

if (child.props.onKeyUp) {
throw new Error(`${componentName}'s child can't have an onKeyUp prop because the implementation will override it.`);
}
};

EuiKeyboardAccessible.propTypes = {
Expand Down
60 changes: 34 additions & 26 deletions src/components/accessibility/keyboard_accessible.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,32 +83,6 @@ describe('EuiKeyboardAccessible', () => {
`child's onClick prop needs to be a function.`
);
});

test(`when the child has an onKeyDown prop`, () => {
const component = ( // eslint-disable-line no-unused-vars
<EuiKeyboardAccessible>
<div onClick={() => {}} onKeyDown={() => {}} />
</EuiKeyboardAccessible>
);

expect(consoleStub.calledOnce).toBe(true);
expect(consoleStub.getCall(0).args[0]).toContain(
`child can't have an onKeyDown prop because the implementation will override it.`
);
});

test(`when the child has an onKeyUp prop`, () => {
const component = ( // eslint-disable-line no-unused-vars
<EuiKeyboardAccessible>
<div onClick={() => {}} onKeyUp={() => {}} />
</EuiKeyboardAccessible>
);

expect(consoleStub.calledOnce).toBe(true);
expect(consoleStub.getCall(0).args[0]).toContain(
`child can't have an onKeyUp prop because the implementation will override it.`
);
});
});

describe(`doesn't throw an error`, () => {
Expand Down Expand Up @@ -195,4 +169,38 @@ describe('EuiKeyboardAccessible', () => {
sinon.assert.calledOnce(onClickHandler);
});
});

describe(`child's props`, () => {
test(`onKeyUp handler is called`, () => {
const onKeyUpHandler = sinon.stub();

const $button = shallow(
<EuiKeyboardAccessible>
<div data-div onKeyUp={onKeyUpHandler} />
</EuiKeyboardAccessible>
);

$button.find('[data-div]').simulate('keyup', {
keyCode: 0,
});

sinon.assert.calledOnce(onKeyUpHandler);
});

test(`onKeyDown handler is called`, () => {
const onKeyDownHandler = sinon.stub();

const $button = shallow(
<EuiKeyboardAccessible>
<div data-div onKeyDown={onKeyDownHandler} />
</EuiKeyboardAccessible>
);

$button.find('[data-div]').simulate('keydown', {
keyCode: 0,
});

sinon.assert.calledOnce(onKeyDownHandler);
});
});
});
Loading