rn-rich-text-editor 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,31 +1,160 @@
1
- export interface RichTextEditorRef {
2
- registerToolbar: (listener: (items: string[]) => void) => void;
3
- setContentFocusHandler: (listener: () => void) => void;
4
- setContentHTML: (html: string) => void;
5
- setPlaceholder: (placeholder: string) => void;
6
- setContentStyle: (styles: any) => void;
7
- setDisable: (dis: boolean) => void;
8
- blurContentEditor: () => void;
9
- focusContentEditor: () => void;
10
- showAndroidKeyboard: () => void;
11
- insertImage: (attributes: any, style?: any) => void;
12
- insertVideo: (attributes: any, style?: any) => void;
13
- insertText: (text: string) => void;
14
- insertHTML: (html: string) => void;
15
- insertLink: (title: string, url: string) => void;
16
- injectJavascript: (script: string) => void;
17
- preCode: (type: any) => void;
18
- setFontSize: (size: any) => void;
19
- setForeColor: (color: string) => void;
20
- setHiliteColor: (color: string) => void;
21
- setFontName: (name: string) => void;
22
- commandDOM: (command: any) => void;
23
- command: (command: any) => void;
24
- dismissKeyboard: () => void;
25
- getContentHtml: () => Promise<string>;
26
- isKeyboardOpen: boolean;
27
- sendAction: (action: string) => void;
1
+ import { Component } from 'react';
2
+ import { WebView } from 'react-native-webview';
3
+ import { TextInput } from 'react-native';
4
+ export interface RichTextEditorProps {
5
+ contentInset?: object;
6
+ style?: object;
7
+ placeholder?: string;
8
+ initialContentHTML?: string;
9
+ initialFocus?: boolean;
10
+ disabled?: boolean;
11
+ useContainer?: boolean;
12
+ pasteAsPlainText?: boolean;
13
+ autoCapitalize?: string;
14
+ defaultParagraphSeparator?: string;
15
+ editorInitializedCallback?: () => void;
16
+ initialHeight?: number;
17
+ dataDetectorTypes?: string[];
18
+ editorStyle?: {
19
+ backgroundColor?: string;
20
+ color?: string;
21
+ placeholderColor?: string;
22
+ initialCSSText?: string;
23
+ cssText?: string;
24
+ contentCSSText?: string;
25
+ caretColor?: string;
26
+ [key: string]: any;
27
+ };
28
+ html?: string | {
29
+ html: string;
30
+ };
31
+ onFocus?: () => void;
32
+ onBlur?: () => void;
33
+ onChange?: (data: string) => void;
34
+ onPaste?: (data: any) => void;
35
+ onKeyUp?: (data: any) => void;
36
+ onKeyDown?: (data: any) => void;
37
+ onInput?: (data: any) => void;
38
+ onMessage?: (message: any) => void;
39
+ onCursorPosition?: (offsetY: number) => void;
40
+ onLink?: (data: any) => void;
41
+ onHeightChange?: (height: number) => void;
42
+ [key: string]: any;
28
43
  }
29
- export declare const RichTextEditor: any;
30
- export default RichTextEditor;
31
- export { RichTextEditor as RichEditor };
44
+ interface RichTextEditorState {
45
+ html: {
46
+ html: string;
47
+ };
48
+ keyboardHeight: number;
49
+ height: number;
50
+ }
51
+ export default class RichTextEditor extends Component<RichTextEditorProps, RichTextEditorState> {
52
+ readonly props: RichTextEditorProps;
53
+ state: RichTextEditorState;
54
+ setState: Component<RichTextEditorProps, RichTextEditorState>['setState'];
55
+ webviewBridge: WebView | null;
56
+ _input: TextInput | null;
57
+ layout: {
58
+ x?: number;
59
+ y?: number;
60
+ width?: number;
61
+ height?: number;
62
+ };
63
+ unmount: boolean;
64
+ _keyOpen: boolean;
65
+ _focus: boolean;
66
+ selectionChangeListeners: Array<(items: string[]) => void>;
67
+ focusListeners: Array<() => void>;
68
+ contentResolve?: (value: string) => void;
69
+ contentReject?: (reason?: any) => void;
70
+ pendingContentHtml?: ReturnType<typeof setTimeout>;
71
+ keyboardEventListeners: Array<{
72
+ remove: () => void;
73
+ }>;
74
+ static defaultProps: {
75
+ contentInset: {};
76
+ style: {};
77
+ placeholder: string;
78
+ initialContentHTML: string;
79
+ initialFocus: boolean;
80
+ disabled: boolean;
81
+ useContainer: boolean;
82
+ pasteAsPlainText: boolean;
83
+ autoCapitalize: string;
84
+ defaultParagraphSeparator: string;
85
+ editorInitializedCallback: () => void;
86
+ initialHeight: number;
87
+ dataDetectorTypes: string[];
88
+ };
89
+ constructor(props: RichTextEditorProps);
90
+ componentDidMount(): void;
91
+ componentWillUnmount(): void;
92
+ _onKeyboardWillShow(event: any): void;
93
+ _onKeyboardWillHide(event: any): void;
94
+ onMessage(event: any): void;
95
+ setWebHeight(height: any): void;
96
+ /**
97
+ * @param type - Action type (or single toolbar action name when called with 1 arg)
98
+ * @param action - Optional action name (e.g. 'result', 'setHtml')
99
+ * @param data - Optional payload
100
+ * @param options - Optional options
101
+ */
102
+ sendAction(type: string, action?: string, data?: any, options?: any): void;
103
+ componentDidUpdate(prevProps: any, prevState: any, snapshot: any): void;
104
+ setRef(ref: WebView | null): void;
105
+ renderWebView(): any;
106
+ onViewLayout({ nativeEvent: { layout } }: {
107
+ nativeEvent: {
108
+ layout: any;
109
+ };
110
+ }): void;
111
+ render(): any;
112
+ registerToolbar(listener: any): void;
113
+ /**
114
+ * Subsequent versions will be deleted, please use onFocus
115
+ * @deprecated remove
116
+ * @param listener
117
+ */
118
+ setContentFocusHandler(listener: any): void;
119
+ setContentHTML(html: any): void;
120
+ setPlaceholder(placeholder: any): void;
121
+ setContentStyle(styles: any): void;
122
+ setDisable(dis: any): void;
123
+ blurContentEditor(): void;
124
+ focusContentEditor(): void;
125
+ /**
126
+ * open android keyboard
127
+ * @platform android
128
+ */
129
+ showAndroidKeyboard(): void;
130
+ /**
131
+ * @param attributes
132
+ * @param [style]
133
+ */
134
+ insertImage(attributes: any, style: any): void;
135
+ /**
136
+ * @param attributes
137
+ * @param [style]
138
+ */
139
+ insertVideo(attributes: any, style: any): void;
140
+ insertText(text: any): void;
141
+ insertHTML(html: any): void;
142
+ insertLink(title: any, url: any): void;
143
+ injectJavascript(script: string): void;
144
+ preCode(type: any): void;
145
+ setFontSize(size: any): void;
146
+ setForeColor(color: any): void;
147
+ setHiliteColor(color: any): void;
148
+ setFontName(name: any): void;
149
+ commandDOM(command: any): void;
150
+ command(command: any): void;
151
+ dismissKeyboard(): void;
152
+ get isKeyboardOpen(): boolean;
153
+ init(): void;
154
+ /**
155
+ * @deprecated please use onChange
156
+ * @returns {Promise}
157
+ */
158
+ getContentHtml(): Promise<unknown>;
159
+ }
160
+ export {};
@@ -33,7 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.RichEditor = exports.RichTextEditor = void 0;
37
36
  const react_1 = __importStar(require("react"));
38
37
  const react_native_webview_1 = require("react-native-webview");
39
38
  const actions_1 = require("./actions");
@@ -41,126 +40,107 @@ const messages_1 = require("./messages");
41
40
  const react_native_1 = require("react-native");
42
41
  const createHTML_1 = require("./editor/createHTML");
43
42
  const PlatformIOS = react_native_1.Platform.OS === 'ios';
44
- function buildCreateHTMLOptions(props) {
45
- const { editorStyle: { backgroundColor, color, placeholderColor, initialCSSText, cssText, contentCSSText, caretColor, } = {}, html, pasteAsPlainText, onPaste, onKeyUp, onKeyDown, onInput, enterKeyHint, autoCapitalize, autoCorrect, defaultParagraphSeparator, firstFocusEnd, useContainer, initialFocus, disabled, styleWithCSS, useCharacter, defaultHttps, } = props;
46
- return {
47
- backgroundColor,
48
- color,
49
- caretColor,
50
- placeholderColor,
51
- initialCSSText,
52
- cssText,
53
- contentCSSText,
54
- pasteAsPlainText,
55
- pasteListener: !!onPaste,
56
- keyUpListener: !!onKeyUp,
57
- keyDownListener: !!onKeyDown,
58
- inputListener: !!onInput,
59
- enterKeyHint,
60
- autoCapitalize,
61
- autoCorrect,
62
- initialFocus: initialFocus && !disabled,
63
- defaultParagraphSeparator,
64
- firstFocusEnd,
65
- useContainer,
66
- styleWithCSS,
67
- useCharacter,
68
- defaultHttps,
69
- };
70
- }
71
- exports.RichTextEditor = (0, react_1.forwardRef)(function RichTextEditor({ contentInset = {}, style = {}, placeholder = '', initialContentHTML = '', initialFocus = false, disabled = false, useContainer = true, pasteAsPlainText = false, autoCapitalize = 'off', defaultParagraphSeparator = 'div', editorInitializedCallback = () => { }, initialHeight = 0, dataDetectorTypes = ['none'], editorStyle, html: htmlProp, onFocus, onBlur, onChange, onPaste, onKeyUp, onKeyDown, onInput, onMessage, onCursorPosition, onLink, onHeightChange, ...rest }, ref) {
72
- const webRef = (0, react_1.useRef)(null);
73
- const inputRef = (0, react_1.useRef)(null);
74
- const selectionChangeListeners = (0, react_1.useRef)([]);
75
- const focusListeners = (0, react_1.useRef)([]);
76
- const contentResolveRef = (0, react_1.useRef)();
77
- const contentRejectRef = (0, react_1.useRef)();
78
- const pendingContentHtmlRef = (0, react_1.useRef)();
79
- const unmountRef = (0, react_1.useRef)(false);
80
- const keyOpenRef = (0, react_1.useRef)(false);
81
- const focusRef = (0, react_1.useRef)(false);
82
- const layoutRef = (0, react_1.useRef)({});
83
- const viewHTML = (0, react_1.useMemo)(() => htmlProp || (0, createHTML_1.createHTML)(buildCreateHTMLOptions({
84
- editorStyle,
85
- html: htmlProp,
86
- pasteAsPlainText,
87
- onPaste,
88
- onKeyUp,
89
- onKeyDown,
90
- onInput,
91
- enterKeyHint: rest.enterKeyHint,
92
- autoCapitalize,
93
- autoCorrect: rest.autoCorrect,
94
- defaultParagraphSeparator,
95
- firstFocusEnd: rest.firstFocusEnd,
96
- useContainer,
97
- initialFocus,
98
- disabled,
99
- styleWithCSS: rest.styleWithCSS,
100
- useCharacter: rest.useCharacter,
101
- defaultHttps: rest.defaultHttps,
102
- })), []);
103
- const [height, setHeight] = (0, react_1.useState)(initialHeight);
104
- (0, react_1.useEffect)(() => {
105
- unmountRef.current = false;
106
- const keyboardShow = () => {
107
- keyOpenRef.current = true;
108
- };
109
- const keyboardHide = () => {
110
- keyOpenRef.current = false;
43
+ class RichTextEditor extends react_1.Component {
44
+ constructor(props) {
45
+ super(props);
46
+ this.webviewBridge = null;
47
+ this._input = null;
48
+ this.layout = {};
49
+ this.unmount = false;
50
+ this._keyOpen = false;
51
+ this._focus = false;
52
+ this.selectionChangeListeners = [];
53
+ this.focusListeners = [];
54
+ this.keyboardEventListeners = [];
55
+ const that = this;
56
+ that.renderWebView = that.renderWebView.bind(that);
57
+ that.onMessage = that.onMessage.bind(that);
58
+ that.sendAction = that.sendAction.bind(that);
59
+ that.registerToolbar = that.registerToolbar.bind(that);
60
+ that._onKeyboardWillShow = that._onKeyboardWillShow.bind(that);
61
+ that._onKeyboardWillHide = that._onKeyboardWillHide.bind(that);
62
+ that.init = that.init.bind(that);
63
+ that.setRef = that.setRef.bind(that);
64
+ that.onViewLayout = that.onViewLayout.bind(that);
65
+ that.unmount = false;
66
+ that._keyOpen = false;
67
+ that._focus = false;
68
+ that.layout = {};
69
+ that.selectionChangeListeners = [];
70
+ const { editorStyle: { backgroundColor, color, placeholderColor, initialCSSText, cssText, contentCSSText, caretColor, } = {}, html, pasteAsPlainText, onPaste, onKeyUp, onKeyDown, onInput, enterKeyHint, autoCapitalize, autoCorrect, defaultParagraphSeparator, firstFocusEnd, useContainer, initialHeight, initialFocus, disabled, styleWithCSS, useCharacter, defaultHttps, } = props;
71
+ const htmlString = (typeof html === 'string' ? html : (html && typeof html === 'object' && 'html' in html ? html.html : undefined)) ||
72
+ (0, createHTML_1.createHTML)({
73
+ backgroundColor,
74
+ color,
75
+ caretColor,
76
+ placeholderColor,
77
+ initialCSSText,
78
+ cssText,
79
+ contentCSSText,
80
+ pasteAsPlainText,
81
+ pasteListener: !!onPaste,
82
+ keyUpListener: !!onKeyUp,
83
+ keyDownListener: !!onKeyDown,
84
+ inputListener: !!onInput,
85
+ enterKeyHint,
86
+ autoCapitalize,
87
+ autoCorrect,
88
+ initialFocus: initialFocus && !disabled,
89
+ defaultParagraphSeparator,
90
+ firstFocusEnd,
91
+ useContainer,
92
+ styleWithCSS,
93
+ useCharacter,
94
+ defaultHttps,
95
+ });
96
+ that.state = {
97
+ html: { html: htmlString },
98
+ keyboardHeight: 0,
99
+ height: (initialHeight !== null && initialHeight !== void 0 ? initialHeight : 0),
111
100
  };
112
- const listeners = PlatformIOS
113
- ? [
114
- react_native_1.Keyboard.addListener('keyboardWillShow', keyboardShow),
115
- react_native_1.Keyboard.addListener('keyboardWillHide', keyboardHide),
116
- ]
117
- : [
118
- react_native_1.Keyboard.addListener('keyboardDidShow', keyboardShow),
119
- react_native_1.Keyboard.addListener('keyboardDidHide', keyboardHide),
101
+ that.focusListeners = [];
102
+ }
103
+ componentDidMount() {
104
+ this.unmount = false;
105
+ if (PlatformIOS) {
106
+ this.keyboardEventListeners = [
107
+ react_native_1.Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow),
108
+ react_native_1.Keyboard.addListener('keyboardWillHide', this._onKeyboardWillHide),
120
109
  ];
121
- return () => {
122
- unmountRef.current = true;
123
- listeners.forEach(l => l.remove());
124
- };
125
- }, []);
126
- (0, react_1.useEffect)(() => {
127
- if (editorStyle) {
128
- sendAction(actions_1.actions.content, 'setContentStyle', editorStyle);
129
- }
130
- }, [editorStyle]);
131
- (0, react_1.useEffect)(() => {
132
- sendAction(actions_1.actions.content, 'setDisable', !!disabled);
133
- }, [disabled]);
134
- (0, react_1.useEffect)(() => {
135
- sendAction(actions_1.actions.content, 'setPlaceholder', placeholder);
136
- }, [placeholder]);
137
- function sendAction(type, action, data, options) {
138
- var _a, _b;
139
- const jsonString = JSON.stringify({ type, name: action, data, options });
140
- if (unmountRef.current || !webRef.current)
141
- return;
142
- const webRefAny = webRef.current;
143
- if (typeof webRefAny.postMessage === 'function') {
144
- webRefAny.postMessage(jsonString);
145
110
  }
146
111
  else {
147
- (_b = (_a = webRef.current).injectJavaScript) === null || _b === void 0 ? void 0 : _b.call(_a, `window.dispatchEvent(new MessageEvent('message', { data: ${JSON.stringify(jsonString)} })); true;`);
112
+ this.keyboardEventListeners = [
113
+ react_native_1.Keyboard.addListener('keyboardDidShow', this._onKeyboardWillShow),
114
+ react_native_1.Keyboard.addListener('keyboardDidHide', this._onKeyboardWillHide),
115
+ ];
148
116
  }
149
117
  }
150
- const handleMessage = (event) => {
151
- var _a, _b;
118
+ componentWillUnmount() {
119
+ this.unmount = true;
120
+ this.keyboardEventListeners.forEach(eventListener => eventListener.remove());
121
+ }
122
+ _onKeyboardWillShow(event) {
123
+ this._keyOpen = true;
124
+ }
125
+ _onKeyboardWillHide(event) {
126
+ this._keyOpen = false;
127
+ }
128
+ onMessage(event) {
129
+ var _a;
130
+ const that = this;
131
+ const { onFocus, onBlur, onChange, onPaste, onKeyUp, onKeyDown, onInput, onMessage, onCursorPosition, onLink } = that.props;
152
132
  try {
153
133
  const message = JSON.parse(event.nativeEvent.data);
154
134
  const data = message.data;
155
135
  switch (message.type) {
156
136
  case messages_1.messages.CONTENT_HTML_RESPONSE:
157
- if (contentResolveRef.current) {
158
- contentResolveRef.current(message.data);
159
- contentResolveRef.current = undefined;
160
- contentRejectRef.current = undefined;
161
- if (pendingContentHtmlRef.current) {
162
- clearTimeout(pendingContentHtmlRef.current);
163
- pendingContentHtmlRef.current = undefined;
137
+ if (that.contentResolve) {
138
+ that.contentResolve(message.data);
139
+ that.contentResolve = undefined;
140
+ that.contentReject = undefined;
141
+ if (that.pendingContentHtml) {
142
+ clearTimeout(that.pendingContentHtml);
143
+ that.pendingContentHtml = undefined;
164
144
  }
165
145
  }
166
146
  break;
@@ -171,15 +151,18 @@ exports.RichTextEditor = (0, react_1.forwardRef)(function RichTextEditor({ conte
171
151
  console.log('FROM EDIT:', ...data);
172
152
  break;
173
153
  case messages_1.messages.SELECTION_CHANGE:
174
- selectionChangeListeners.current.forEach(listener => listener(message.data));
154
+ const items = message.data;
155
+ that.selectionChangeListeners.map(listener => {
156
+ listener(items);
157
+ });
175
158
  break;
176
159
  case messages_1.messages.CONTENT_FOCUSED:
177
- focusRef.current = true;
178
- focusListeners.current.forEach(fn => fn());
160
+ that._focus = true;
161
+ that.focusListeners.map(da => da()); // Subsequent versions will be deleted
179
162
  onFocus === null || onFocus === void 0 ? void 0 : onFocus();
180
163
  break;
181
164
  case messages_1.messages.CONTENT_BLUR:
182
- focusRef.current = false;
165
+ that._focus = false;
183
166
  onBlur === null || onBlur === void 0 ? void 0 : onBlur();
184
167
  break;
185
168
  case messages_1.messages.CONTENT_CHANGE:
@@ -198,185 +181,239 @@ exports.RichTextEditor = (0, react_1.forwardRef)(function RichTextEditor({ conte
198
181
  onInput === null || onInput === void 0 ? void 0 : onInput(data);
199
182
  break;
200
183
  case messages_1.messages.OFFSET_HEIGHT:
201
- if (data !== height) {
202
- const maxHeight = Math.max(data, initialHeight);
203
- if (!unmountRef.current && useContainer && maxHeight >= initialHeight) {
204
- setHeight(maxHeight);
205
- }
206
- onHeightChange === null || onHeightChange === void 0 ? void 0 : onHeightChange(data);
207
- }
184
+ that.setWebHeight(data);
208
185
  break;
209
- case messages_1.messages.OFFSET_Y:
210
- const offsetY = Number(Number(data) + ((_b = (_a = layoutRef.current) === null || _a === void 0 ? void 0 : _a.y) !== null && _b !== void 0 ? _b : 0));
186
+ case messages_1.messages.OFFSET_Y: {
187
+ const offsetY = Number(Number(data) + ((_a = that.layout.y) !== null && _a !== void 0 ? _a : 0));
211
188
  if (offsetY > 0)
212
189
  onCursorPosition === null || onCursorPosition === void 0 ? void 0 : onCursorPosition(offsetY);
213
190
  break;
191
+ }
214
192
  default:
215
193
  onMessage === null || onMessage === void 0 ? void 0 : onMessage(message);
216
194
  break;
217
195
  }
218
196
  }
219
- catch (_c) {
220
- // Non-JSON message, ignore
197
+ catch (_b) {
198
+ //alert('NON JSON MESSAGE');
221
199
  }
222
- };
223
- const init = () => {
224
- var _a, _b, _c;
225
- if (initialContentHTML)
226
- sendAction(actions_1.actions.content, 'setHtml', initialContentHTML);
227
- if (placeholder)
228
- sendAction(actions_1.actions.content, 'setPlaceholder', placeholder);
229
- sendAction(actions_1.actions.content, 'setDisable', !!disabled);
230
- editorInitializedCallback();
231
- if (initialFocus && !disabled) {
232
- if (react_native_1.Platform.OS === 'android') {
233
- if (!keyOpenRef.current)
234
- (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
235
- (_c = (_b = webRef.current) === null || _b === void 0 ? void 0 : _b.requestFocus) === null || _c === void 0 ? void 0 : _c.call(_b);
200
+ }
201
+ setWebHeight(height) {
202
+ const { onHeightChange, useContainer, initialHeight } = this.props;
203
+ if (height !== this.state.height) {
204
+ const maxHeight = Math.max(height, initialHeight);
205
+ if (!this.unmount && useContainer && maxHeight >= initialHeight) {
206
+ this.setState({ height: maxHeight });
236
207
  }
237
- sendAction(actions_1.actions.content, 'focus');
208
+ onHeightChange && onHeightChange(height);
238
209
  }
239
- sendAction(actions_1.actions.init);
240
- };
241
- (0, react_1.useImperativeHandle)(ref, () => {
242
- const postActionToWebView = sendAction;
243
- return {
244
- registerToolbar(listener) {
245
- selectionChangeListeners.current = [...selectionChangeListeners.current, listener];
246
- },
247
- setContentFocusHandler(listener) {
248
- focusListeners.current.push(listener);
249
- },
250
- setContentHTML(html) {
251
- sendAction(actions_1.actions.content, 'setHtml', html);
252
- },
253
- setPlaceholder(placeholderText) {
254
- sendAction(actions_1.actions.content, 'setPlaceholder', placeholderText);
255
- },
256
- setContentStyle(styles) {
257
- sendAction(actions_1.actions.content, 'setContentStyle', styles);
258
- },
259
- setDisable(dis) {
260
- sendAction(actions_1.actions.content, 'setDisable', !!dis);
261
- },
262
- blurContentEditor() {
263
- sendAction(actions_1.actions.content, 'blur');
264
- },
265
- focusContentEditor() {
266
- var _a, _b, _c;
267
- if (react_native_1.Platform.OS === 'android') {
268
- if (!keyOpenRef.current)
269
- (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
270
- (_c = (_b = webRef.current) === null || _b === void 0 ? void 0 : _b.requestFocus) === null || _c === void 0 ? void 0 : _c.call(_b);
271
- }
272
- sendAction(actions_1.actions.content, 'focus');
273
- },
274
- showAndroidKeyboard() {
275
- var _a, _b, _c;
276
- if (react_native_1.Platform.OS === 'android') {
277
- if (!keyOpenRef.current)
278
- (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
279
- (_c = (_b = webRef.current) === null || _b === void 0 ? void 0 : _b.requestFocus) === null || _c === void 0 ? void 0 : _c.call(_b);
280
- }
281
- },
282
- insertImage(attributes, styleOpt) {
283
- sendAction(actions_1.actions.insertImage, 'result', attributes, styleOpt);
284
- },
285
- insertVideo(attributes, styleOpt) {
286
- sendAction(actions_1.actions.insertVideo, 'result', attributes, styleOpt);
287
- },
288
- insertText(text) {
289
- sendAction(actions_1.actions.insertText, 'result', text);
290
- },
291
- insertHTML(html) {
292
- sendAction(actions_1.actions.insertHTML, 'result', html);
293
- },
294
- insertLink(title, url) {
295
- var _a, _b, _c;
296
- if (url) {
297
- if (react_native_1.Platform.OS === 'android') {
298
- if (!keyOpenRef.current)
299
- (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
300
- (_c = (_b = webRef.current) === null || _b === void 0 ? void 0 : _b.requestFocus) === null || _c === void 0 ? void 0 : _c.call(_b);
301
- }
302
- sendAction(actions_1.actions.insertLink, 'result', { title, url });
303
- }
304
- },
305
- injectJavascript(script) {
306
- var _a, _b;
307
- return (_b = (_a = webRef.current) === null || _a === void 0 ? void 0 : _a.injectJavaScript) === null || _b === void 0 ? void 0 : _b.call(_a, script);
308
- },
309
- preCode(type) {
310
- sendAction(actions_1.actions.code, 'result', type);
311
- },
312
- setFontSize(size) {
313
- sendAction(actions_1.actions.fontSize, 'result', size);
314
- },
315
- setForeColor(color) {
316
- sendAction(actions_1.actions.foreColor, 'result', color);
317
- },
318
- setHiliteColor(color) {
319
- sendAction(actions_1.actions.hiliteColor, 'result', color);
320
- },
321
- setFontName(name) {
322
- sendAction(actions_1.actions.fontName, 'result', name);
323
- },
324
- commandDOM(command) {
325
- if (command)
326
- sendAction(actions_1.actions.content, 'commandDOM', command);
327
- },
328
- command(command) {
329
- if (command)
330
- sendAction(actions_1.actions.content, 'command', command);
331
- },
332
- dismissKeyboard() {
333
- if (focusRef.current)
334
- sendAction(actions_1.actions.content, 'blur');
335
- else
336
- react_native_1.Keyboard.dismiss();
337
- },
338
- get isKeyboardOpen() {
339
- return keyOpenRef.current;
340
- },
341
- getContentHtml() {
342
- return new Promise((resolve, reject) => {
343
- contentResolveRef.current = resolve;
344
- contentRejectRef.current = reject;
345
- postActionToWebView(actions_1.actions.content, 'postHtml');
346
- pendingContentHtmlRef.current = setTimeout(() => {
347
- if (contentRejectRef.current)
348
- contentRejectRef.current('timeout');
349
- }, 5000);
350
- });
351
- },
352
- sendAction(action) {
353
- postActionToWebView(action, 'result');
354
- },
355
- };
356
- });
357
- const onViewLayout = ({ nativeEvent: { layout } }) => {
358
- layoutRef.current = layout;
359
- };
360
- const renderWebView = () => {
361
- var _a;
210
+ }
211
+ /**
212
+ * @param type - Action type (or single toolbar action name when called with 1 arg)
213
+ * @param action - Optional action name (e.g. 'result', 'setHtml')
214
+ * @param data - Optional payload
215
+ * @param options - Optional options
216
+ */
217
+ sendAction(type, action, data, options) {
218
+ // Toolbar calls sendAction(action) with one arg; forward as type + 'result'
219
+ const name = arguments.length === 1 ? 'result' : action;
220
+ const payload = arguments.length === 1 ? undefined : data;
221
+ const opts = arguments.length === 1 ? undefined : options;
222
+ const jsonString = JSON.stringify({ type, name, data: payload, options: opts });
223
+ if (!this.unmount && this.webviewBridge) {
224
+ this.webviewBridge.postMessage(jsonString);
225
+ }
226
+ }
227
+ componentDidUpdate(prevProps, prevState, snapshot) {
228
+ const { editorStyle, disabled, placeholder } = this.props;
229
+ if (prevProps.editorStyle !== editorStyle) {
230
+ editorStyle && this.setContentStyle(editorStyle);
231
+ }
232
+ if (disabled !== prevProps.disabled) {
233
+ this.setDisable(disabled);
234
+ }
235
+ if (placeholder !== prevProps.placeholder) {
236
+ this.setPlaceholder(placeholder);
237
+ }
238
+ }
239
+ setRef(ref) {
240
+ this.webviewBridge = ref;
241
+ }
242
+ renderWebView() {
243
+ const that = this;
244
+ const { html: _html, editorStyle, useContainer, style, onLink, dataDetectorTypes, ...rest } = that.props;
245
+ const { html: viewHTML } = that.state;
362
246
  return (react_1.default.createElement(react_1.default.Fragment, null,
363
- react_1.default.createElement(react_native_webview_1.WebView, { ref: webRef, useWebKit: true, scrollEnabled: false, hideKeyboardAccessoryView: true, keyboardDisplayRequiresUserAction: false, nestedScrollEnabled: !useContainer, style: [styles.webview, style], ...rest, onMessage: handleMessage, originWhitelist: ['*'], dataDetectorTypes: dataDetectorTypes, domStorageEnabled: false, bounces: false, javaScriptEnabled: true, source: { html: typeof viewHTML === 'string' ? viewHTML : (_a = viewHTML === null || viewHTML === void 0 ? void 0 : viewHTML.html) !== null && _a !== void 0 ? _a : '' }, onLoad: init, onShouldStartLoadWithRequest: (event) => {
364
- var _a, _b, _c;
247
+ react_1.default.createElement(react_native_webview_1.WebView, { useWebKit: true, scrollEnabled: false, hideKeyboardAccessoryView: true, keyboardDisplayRequiresUserAction: false, nestedScrollEnabled: !useContainer, style: [styles.webview, style], ...rest, ref: that.setRef, onMessage: that.onMessage, originWhitelist: ['*'], dataDetectorTypes: dataDetectorTypes, domStorageEnabled: false, bounces: false, javaScriptEnabled: true, source: viewHTML, onLoad: that.init, onShouldStartLoadWithRequest: event => {
248
+ var _a;
365
249
  if (event.url !== 'about:blank') {
366
- (_b = (_a = webRef.current) === null || _a === void 0 ? void 0 : _a.stopLoading) === null || _b === void 0 ? void 0 : _b.call(_a);
367
- (_c = react_native_1.Linking === null || react_native_1.Linking === void 0 ? void 0 : react_native_1.Linking.openURL) === null || _c === void 0 ? void 0 : _c.call(react_native_1.Linking, event.url);
250
+ (_a = this.webviewBridge) === null || _a === void 0 ? void 0 : _a.stopLoading();
251
+ react_native_1.Linking === null || react_native_1.Linking === void 0 ? void 0 : react_native_1.Linking.openURL(event.url);
368
252
  return false;
369
253
  }
370
254
  return true;
371
255
  } }),
372
- react_native_1.Platform.OS === 'android' && react_1.default.createElement(react_native_1.TextInput, { ref: inputRef, style: styles._input })));
373
- };
374
- if (useContainer) {
375
- return (react_1.default.createElement(react_native_1.View, { style: [style, { height }], onLayout: onViewLayout }, renderWebView()));
256
+ react_native_1.Platform.OS === 'android' && react_1.default.createElement(react_native_1.TextInput, { ref: ref => (that._input = ref), style: styles._input })));
376
257
  }
377
- return renderWebView();
378
- });
379
- exports.RichEditor = exports.RichTextEditor;
258
+ onViewLayout({ nativeEvent: { layout } }) {
259
+ this.layout = layout;
260
+ }
261
+ render() {
262
+ let { height } = this.state;
263
+ // useContainer is an optional prop with default value of true
264
+ // If set to true, it will use a View wrapper with styles and height.
265
+ // If set to false, it will not use a View wrapper
266
+ const { useContainer, style } = this.props;
267
+ return useContainer ? (react_1.default.createElement(react_native_1.View, { style: [style, { height }], onLayout: this.onViewLayout }, this.renderWebView())) : (this.renderWebView());
268
+ }
269
+ registerToolbar(listener) {
270
+ this.selectionChangeListeners = [...this.selectionChangeListeners, listener];
271
+ }
272
+ /**
273
+ * Subsequent versions will be deleted, please use onFocus
274
+ * @deprecated remove
275
+ * @param listener
276
+ */
277
+ setContentFocusHandler(listener) {
278
+ this.focusListeners.push(listener);
279
+ }
280
+ setContentHTML(html) {
281
+ this.sendAction(actions_1.actions.content, 'setHtml', html);
282
+ }
283
+ setPlaceholder(placeholder) {
284
+ this.sendAction(actions_1.actions.content, 'setPlaceholder', placeholder);
285
+ }
286
+ setContentStyle(styles) {
287
+ this.sendAction(actions_1.actions.content, 'setContentStyle', styles);
288
+ }
289
+ setDisable(dis) {
290
+ this.sendAction(actions_1.actions.content, 'setDisable', !!dis);
291
+ }
292
+ blurContentEditor() {
293
+ this.sendAction(actions_1.actions.content, 'blur');
294
+ }
295
+ focusContentEditor() {
296
+ this.showAndroidKeyboard();
297
+ this.sendAction(actions_1.actions.content, 'focus');
298
+ }
299
+ /**
300
+ * open android keyboard
301
+ * @platform android
302
+ */
303
+ showAndroidKeyboard() {
304
+ var _a, _b;
305
+ let that = this;
306
+ if (react_native_1.Platform.OS === 'android') {
307
+ !that._keyOpen && that._input.focus();
308
+ (_b = (_a = that.webviewBridge) === null || _a === void 0 ? void 0 : _a.requestFocus) === null || _b === void 0 ? void 0 : _b.call(_a);
309
+ }
310
+ }
311
+ /**
312
+ * @param attributes
313
+ * @param [style]
314
+ */
315
+ insertImage(attributes, style) {
316
+ this.sendAction(actions_1.actions.insertImage, 'result', attributes, style);
317
+ }
318
+ /**
319
+ * @param attributes
320
+ * @param [style]
321
+ */
322
+ insertVideo(attributes, style) {
323
+ this.sendAction(actions_1.actions.insertVideo, 'result', attributes, style);
324
+ }
325
+ insertText(text) {
326
+ this.sendAction(actions_1.actions.insertText, 'result', text);
327
+ }
328
+ insertHTML(html) {
329
+ this.sendAction(actions_1.actions.insertHTML, 'result', html);
330
+ }
331
+ insertLink(title, url) {
332
+ if (url) {
333
+ this.showAndroidKeyboard();
334
+ this.sendAction(actions_1.actions.insertLink, 'result', { title, url });
335
+ }
336
+ }
337
+ injectJavascript(script) {
338
+ var _a, _b;
339
+ return (_b = (_a = this.webviewBridge) === null || _a === void 0 ? void 0 : _a.injectJavaScript) === null || _b === void 0 ? void 0 : _b.call(_a, script);
340
+ }
341
+ preCode(type) {
342
+ this.sendAction(actions_1.actions.code, 'result', type);
343
+ }
344
+ setFontSize(size) {
345
+ this.sendAction(actions_1.actions.fontSize, 'result', size);
346
+ }
347
+ setForeColor(color) {
348
+ this.sendAction(actions_1.actions.foreColor, 'result', color);
349
+ }
350
+ setHiliteColor(color) {
351
+ this.sendAction(actions_1.actions.hiliteColor, 'result', color);
352
+ }
353
+ setFontName(name) {
354
+ this.sendAction(actions_1.actions.fontName, 'result', name);
355
+ }
356
+ commandDOM(command) {
357
+ if (command) {
358
+ this.sendAction(actions_1.actions.content, 'commandDOM', command);
359
+ }
360
+ }
361
+ command(command) {
362
+ if (command) {
363
+ this.sendAction(actions_1.actions.content, 'command', command);
364
+ }
365
+ }
366
+ dismissKeyboard() {
367
+ this._focus ? this.blurContentEditor() : react_native_1.Keyboard.dismiss();
368
+ }
369
+ get isKeyboardOpen() {
370
+ return this._keyOpen;
371
+ }
372
+ init() {
373
+ let that = this;
374
+ const { initialFocus, initialContentHTML, placeholder, editorInitializedCallback, disabled } = that.props;
375
+ initialContentHTML && that.setContentHTML(initialContentHTML);
376
+ placeholder && that.setPlaceholder(placeholder);
377
+ that.setDisable(disabled);
378
+ editorInitializedCallback();
379
+ // initial request focus
380
+ initialFocus && !disabled && that.focusContentEditor();
381
+ // no visible ?
382
+ that.sendAction(actions_1.actions.init);
383
+ }
384
+ /**
385
+ * @deprecated please use onChange
386
+ * @returns {Promise}
387
+ */
388
+ async getContentHtml() {
389
+ return new Promise((resolve, reject) => {
390
+ this.contentResolve = resolve;
391
+ this.contentReject = reject;
392
+ this.sendAction(actions_1.actions.content, 'postHtml');
393
+ this.pendingContentHtml = setTimeout(() => {
394
+ if (this.contentReject) {
395
+ this.contentReject('timeout');
396
+ }
397
+ }, 5000);
398
+ });
399
+ }
400
+ }
401
+ RichTextEditor.defaultProps = {
402
+ contentInset: {},
403
+ style: {},
404
+ placeholder: '',
405
+ initialContentHTML: '',
406
+ initialFocus: false,
407
+ disabled: false,
408
+ useContainer: true,
409
+ pasteAsPlainText: false,
410
+ autoCapitalize: 'off',
411
+ defaultParagraphSeparator: 'div',
412
+ editorInitializedCallback: () => { },
413
+ initialHeight: 0,
414
+ dataDetectorTypes: ['none'],
415
+ };
416
+ exports.default = RichTextEditor;
380
417
  const styles = react_native_1.StyleSheet.create({
381
418
  _input: {
382
419
  position: 'absolute',
@@ -390,4 +427,3 @@ const styles = react_native_1.StyleSheet.create({
390
427
  backgroundColor: 'transparent',
391
428
  },
392
429
  });
393
- exports.default = exports.RichTextEditor;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { RichEditor } from './RichEditor';
1
+ export { default as RichTextEditor } from './RichEditor';
2
2
  export { RichToolbar, defaultActions } from './RichToolbar';
3
3
  export { actions } from './actions';
4
4
  export { createHTML } from './editor/createHTML';
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getContentCSS = exports.createHTML = exports.actions = exports.defaultActions = exports.RichToolbar = exports.RichEditor = void 0;
6
+ exports.getContentCSS = exports.createHTML = exports.actions = exports.defaultActions = exports.RichToolbar = exports.RichTextEditor = void 0;
4
7
  var RichEditor_1 = require("./RichEditor");
5
- Object.defineProperty(exports, "RichEditor", { enumerable: true, get: function () { return RichEditor_1.RichEditor; } });
8
+ Object.defineProperty(exports, "RichTextEditor", { enumerable: true, get: function () { return __importDefault(RichEditor_1).default; } });
6
9
  var RichToolbar_1 = require("./RichToolbar");
7
10
  Object.defineProperty(exports, "RichToolbar", { enumerable: true, get: function () { return RichToolbar_1.RichToolbar; } });
8
11
  Object.defineProperty(exports, "defaultActions", { enumerable: true, get: function () { return RichToolbar_1.defaultActions; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-rich-text-editor",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "A rich text editor component for React Native",
5
5
  "keywords": [
6
6
  "react-native",