Skip to content

Commit

Permalink
onKeyDown, onKeyUp, onPaste
Browse files Browse the repository at this point in the history
  • Loading branch information
stulip committed Dec 16, 2020
1 parent f64a829 commit a1f9dcb
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 43 deletions.
13 changes: 9 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@

## 1.3.2
#### Fix
- Toolbar buttons activate/deactivate erratically after backspacing

## 1.3.1
## 1.4.0
#### Added
- Add `pasteAsPlainText` props on editor
- Add `removeFormat` props on editor
- Add `autoCapitalize` props on editor of autocapitalize
- Add `onPaste` props on editor callback paste value
- Add `onKeyUp` props on editor callback keyup event
- Add `onKeyDown` props on editor callback keydown event

#### Fix
- Toolbar buttons activate/deactivate erratically after backspacing
- disabled editor height fix

## 1.3.0
#### Added
Expand Down
53 changes: 28 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ The editor component. Simply place this component in your view hierarchy to rece
* `initialContentHTML`

HTML that will be rendered in the content section on load.
* `initialFocus`

* `initialFocus`
* Boolean value to Initial content request focus. The default value is `false`.

* `disabled`
* `disabled`
* Boolean value to disable editor. The default value is `false`.

* `editorInitializedCallback `

A function that will be called when the editor has been initialized.

* `editorStyle`

Styling for container or for Rich Editor more dark or light settings. Object containing the following options:
Expand All @@ -55,18 +55,21 @@ The editor component. Simply place this component in your view hierarchy to rece

* `onChange`
Callback after editor data modification

* `onHeightChange`
Callback after height change
Callback after height change

* `useContainer`

A boolean value that determines if a View container is wrapped around the WebView. The default value is true. If you are using your own View to wrap this library around, set this value to false.
A boolean value that determines if a View container is wrapped around the WebView. The default value is true. If you are using your own View to wrap this library around, set this value to false.

* `pasteAsPlainText`

A boolean value (false as default) that determines if the clipboard paste will keep its format or it will be done as plain text

* `onPaste`
Callback clipboard paste value


`RichEditor` also has methods that can be used on its `ref` to set:

Expand All @@ -82,7 +85,7 @@ The editor component. Simply place this component in your view hierarchy to rece

This method registers a function that will get called whenver the cursor position changes or a change is made to the styling of the editor at the cursor's position., The callback will be called with an array of `actions` that are active at the cusor position, allowing a toolbar to respond to changes.

* `registerToolbar(listener: Function)`
* `registerToolbar(listener: Function)`



Expand All @@ -103,59 +106,59 @@ This method registers a function that will get called whenver the cursor positio

This is a Component that provides a toolbar for easily controlling an editor. It is designed to be used together with a `RichEditor` component.

The `RichToolbar` has one required property:
The `RichToolbar` has one required property:

* `getEditor()`

Which must provide a **function** that returns a `ref` to a `RichEditor` component.
Which must provide a **function** that returns a `ref` to a `RichEditor` component.

This is because the `ref` is not created until after the first render, before which the toolbar is rendered. This means that any `ref` passed directly will inevitably be passed as `undefined`.

Other props supported by the `RichToolbar` component are:

* `actions`

An `array` of `actions` to be provided by this toolbar. The default actions are:
An `array` of `actions` to be provided by this toolbar. The default actions are:
* `actions.insertImage`
* `actions.setBold`
* `actions.setItalic`
* `actions.insertBulletsList`
* `actions.insertOrderedList`
* `actions.insertLink`

* `onPressAddImage`
Functions called when the `addImage` actions are tapped.
* `onInsertLink`
Functions called when the `addImage` actions are tapped.

* `onInsertLink`
Logic for what happens when you press on the add insert link button

* `disabled`
* `disabled`
* Boolean value to disable editor. The default value is `false`.


* `iconTint`
* `unselectedButtonStyle`
* `selectedIconTint`
* `selectedButtonStyle`
* `disabledIconTint`
* `disabledButtonStyle`

These provide options for styling action buttons.

* `iconSize`

Defines the size of the icon in pixels. Default is 50.

* `renderAction`

Altenatively, you can provide a render function that will be used instead of the default, so you can fully control the tollbar design.
* `iconMap`


* `iconMap`

`RichTextToolbar` comes with default icons for the default actions it renders. To override those, or to add icons for non-default actions, provide them in a dictionary to this prop.


### Example Usage:

```javascript
Expand Down
16 changes: 16 additions & 0 deletions examples/src/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,18 @@ class Example extends React.Component {
this.setState({disabled: !this.state.disabled});
}

handlePaste = (data) => {
console.log('Paste:', data);
};

handleKeyUp = (data) => {
console.log('KeyUp:', data);
};

handleKeyDown = (data) => {
console.log('KeyDown:', data);
};

render() {
let that = this;
const {contentStyle, theme, emojiVisible, disabled} = that.state;
Expand Down Expand Up @@ -245,6 +257,10 @@ class Example extends React.Component {
editorInitializedCallback={that.editorInitializedCallback}
onChange={that.handleChange}
onHeightChange={that.handleHeightChange}
onPaste={that.handlePaste}
onKeyUp={that.handleKeyUp}
onKeyDown={that.handleKeyDown}
pasteAsPlainText={true}
/>
</ScrollView>
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
Expand Down
16 changes: 13 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ declare module 'react-native-pell-rich-editor' {
* String value to set text auto capitalization.
* See: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize
*/
autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters";

autoCapitalize?: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';

/**
* Boolean value to enable paste as plain text. The default value is false.
Expand All @@ -69,8 +68,19 @@ declare module 'react-native-pell-rich-editor' {

/**
* Callback when the user pastes some content
* @param {string} data pastes values
*/
onPaste?: (data: string) => void;

/**
* Callback when the user keyup some content
*/
onKeyUp?: ({keyCode: number, key: string}) => void;

/**
* Callback when the user keydown some content
*/
onPaste?: () => void;
onKeyDown?: ({keyCode: number, key: string}) => void;

/**
* Callback after height change
Expand Down
25 changes: 21 additions & 4 deletions src/RichEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export default class RichTextEditor extends Component {
// onHeightChange: PropTypes.func,
// initialFocus: PropTypes.bool,
// disabled: PropTypes.bool,
// onPaste: PropTypes.func,
// onKeyUp: PropTypes.func,
// onKeyDown: PropTypes.func,
// };

static defaultProps = {
Expand Down Expand Up @@ -48,6 +51,8 @@ export default class RichTextEditor extends Component {
html,
pasteAsPlainText,
onPaste,
onKeyUp,
onKeyDown,
autoCapitalize,
defaultParagraphSeparator,
} = props;
Expand All @@ -63,6 +68,8 @@ export default class RichTextEditor extends Component {
contentCSSText,
pasteAsPlainText,
pasteListener: !!onPaste,
keyUpListener: !!onKeyUp,
keyDownListener: !!onKeyDown,
autoCapitalize,
defaultParagraphSeparator,
}),
Expand Down Expand Up @@ -122,6 +129,7 @@ export default class RichTextEditor extends Component {
onMessage(event) {
try {
const message = JSON.parse(event.nativeEvent.data);
const data = message.data;
switch (message.type) {
case messages.CONTENT_HTML_RESPONSE:
if (this.contentResolve) {
Expand All @@ -135,7 +143,7 @@ export default class RichTextEditor extends Component {
}
break;
case messages.LOG:
console.log('FROM EDIT:', ...message.data);
console.log('FROM EDIT:', ...data);
break;
case messages.SELECTION_CHANGE: {
const items = message.data;
Expand All @@ -149,14 +157,23 @@ export default class RichTextEditor extends Component {
break;
}
case messages.CONTENT_CHANGE: {
this.props.onChange && this.props.onChange(message.data);
this.props.onChange && this.props.onChange(data);
break;
}
case messages.CONTENT_PASTED: {
this.props.onPaste && this.props.onPaste();
this.props.onPaste && this.props.onPaste(data);
break;
}
case messages.CONTENT_KEYUP: {
this.props.onKeyUp && this.props.onKeyUp(data);
break;
}
case messages.CONTENT_KEYDOWN: {
this.props.onKeyDown && this.props.onKeyDown(data);
break;
}
case messages.OFFSET_HEIGHT:
this.setWebHeight(message.data);
this.setWebHeight(data);
break;
}
} catch (e) {
Expand Down
2 changes: 2 additions & 0 deletions src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export const messages = {
SELECTION_CHANGE: 'SELECTION_CHANGE',
CONTENT_CHANGE: 'CONTENT_CHANGE',
CONTENT_PASTED: 'CONTENT_PASTED',
CONTENT_KEYUP: 'CONTENT_KEYUP',
CONTENT_KEYDOWN: 'CONTENT_KEYDOWN',
SELECTED_TEXT_RESPONSE: 'SELECTED_TEXT_RESPONSE',
LINK_TOUCHED: 'LINK_TOUCHED',
SELECTED_TEXT_CHANGED: 'SELECTED_TEXT_CHANGED',
Expand Down
25 changes: 18 additions & 7 deletions src/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ function createHTML(options = {}) {
cssText = '',
pasteAsPlainText = false,
pasteListener = false,
keyDownListener = false,
keyUpListener = false,
autoCapitalize = 'off',
defaultParagraphSeparator = 'div',
} = options;
Expand Down Expand Up @@ -37,9 +39,10 @@ function createHTML(options = {}) {
<body>
<div class="content"><div id="editor" class="pell"></div></div>
<script>
var placeholderColor = '${placeholderColor}';
var __DEV__ = !!${window.__DEV__};
(function (exports) {
var placeholderColor = '${placeholderColor}';
var body = document.body, docEle = document.documentElement;
var defaultParagraphSeparatorString = 'defaultParagraphSeparator';
var formatBlock = 'formatBlock';
Expand Down Expand Up @@ -253,29 +256,37 @@ function createHTML(options = {}) {
saveSelection();
}, 50);
}
var postKeyAction = function (event, type){
postAction({type: type, data: {keyCode: event.keyCode, key: event.key}});
}
var handleKeyup = function (event){
if (event.keyCode === 8) handleSelecting (event);
${keyUpListener} && postKeyAction(event, "CONTENT_KEYUP")
}
var handleKeydown = function (event){
${keyDownListener} && postKeyAction(event, "CONTENT_KEYDOWN");
}
addEventListener(content, 'touchcancel', handleSelecting);
addEventListener(content, 'mouseup', handleSelecting);
addEventListener(content, 'touchend', handleSelecting);
// Toolbar buttons activate/deactivate erratically after backspacing
addEventListener(content, 'keyup', handleKeyup);
addEventListener(content, 'keydown', handleKeydown);
addEventListener(content, 'blur', function () {
postAction({type: 'SELECTION_CHANGE', data: []});
});
addEventListener(content, 'focus', function () {
postAction({type: 'CONTENT_FOCUSED'});
});
${pasteListener} && addEventListener(content, 'paste', function (e) {
postAction({type: 'CONTENT_PASTED'});
addEventListener(content, 'paste', function (e) {
// get text representation of clipboard
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
${pasteListener} && postAction({type: 'CONTENT_PASTED', data: text});
if (${pasteAsPlainText}) {
// cancel paste
e.preventDefault();
// get text representation of clipboard
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
// insert text manually
document.execCommand("insertHTML", false, text);
}
Expand Down

0 comments on commit a1f9dcb

Please sign in to comment.