@hero-design/rn-work-uikit 1.3.0 → 1.4.0

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/lib/index.js +48742 -29649
  3. package/package.json +5 -4
  4. package/src/__tests__/index-export.spec.ts +64 -0
  5. package/src/components/DatePicker/__tests__/__snapshots__/index.spec.tsx.snap +1602 -0
  6. package/src/components/DatePicker/__tests__/index.spec.tsx +56 -0
  7. package/src/components/DatePicker/index.tsx +12 -0
  8. package/src/components/FormGroup/__tests__/__snapshots__/index.spec.tsx.snap +880 -0
  9. package/src/components/FormGroup/__tests__/index.spec.tsx +179 -0
  10. package/src/components/FormGroup/__tests__/utils.spec.ts +73 -0
  11. package/src/components/FormGroup/index.tsx +97 -0
  12. package/src/components/FormGroup/utils.ts +67 -0
  13. package/src/components/RichTextEditor/EditorEvent.ts +7 -0
  14. package/src/components/RichTextEditor/EditorToolbar.tsx +216 -0
  15. package/src/components/RichTextEditor/MentionList.tsx +99 -0
  16. package/src/components/RichTextEditor/RichTextEditor.tsx +88 -0
  17. package/src/components/RichTextEditor/RichTextEditorInput.tsx +286 -0
  18. package/src/components/RichTextEditor/StyledRichTextEditor.tsx +18 -0
  19. package/src/components/RichTextEditor/StyledToolbar.ts +32 -0
  20. package/src/components/RichTextEditor/__mocks__/hero-editor.js +3 -0
  21. package/src/components/RichTextEditor/__mocks__/heroEditorApp.ts +2 -0
  22. package/src/components/RichTextEditor/__tests__/EditorToolbar.spec.tsx +144 -0
  23. package/src/components/RichTextEditor/__tests__/MentionList.spec.tsx +105 -0
  24. package/src/components/RichTextEditor/__tests__/RichTextEditorInput.spec.tsx +136 -0
  25. package/src/components/RichTextEditor/__tests__/__snapshots__/EditorToolbar.spec.tsx.snap +414 -0
  26. package/src/components/RichTextEditor/__tests__/__snapshots__/MentionList.spec.tsx.snap +13 -0
  27. package/src/components/RichTextEditor/constants.ts +9 -0
  28. package/src/{hero-editor.d.ts → components/RichTextEditor/hero-editor.d.ts} +6 -0
  29. package/src/components/RichTextEditor/heroEditorApp.ts +3 -0
  30. package/src/components/RichTextEditor/index.tsx +20 -0
  31. package/src/components/RichTextEditor/types.ts +87 -0
  32. package/src/components/RichTextEditor/utils/events.ts +31 -0
  33. package/src/components/RichTextEditor/utils/rnWebView.tsx +30 -0
  34. package/src/components/Select/__tests__/__snapshots__/index.spec.tsx.snap +1293 -0
  35. package/src/components/Select/__tests__/index.spec.tsx +43 -0
  36. package/src/components/TextInput/Group/__tests__/__snapshots__/index.spec.tsx.snap +0 -3
  37. package/src/components/TextInput/InputComponent.tsx +59 -18
  38. package/src/components/TextInput/InputRow.tsx +13 -7
  39. package/src/components/TextInput/StyledTextInput.tsx +0 -1
  40. package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +0 -17
  41. package/src/components/TextInput/index.tsx +20 -11
  42. package/src/components/TextInput/types.ts +29 -4
  43. package/src/components/TimePicker/__tests__/index.spec.tsx +34 -0
  44. package/src/components/TimePicker/index.tsx +12 -0
  45. package/src/index.ts +4 -1
  46. package/src/utils/functions.ts +2 -0
  47. package/stats/1.3.0/rn-work-uikit-stats.html +1 -1
  48. package/stats/1.4.0/rn-work-uikit-stats.html +4844 -0
  49. package/src/__tests__/theme-export-override.spec.ts +0 -96
@@ -0,0 +1,105 @@
1
+ import type { RenderAPI } from '@testing-library/react-native';
2
+ import { act, fireEvent, render } from '@testing-library/react-native';
3
+ import React from 'react';
4
+ import { Text, View } from 'react-native';
5
+ import { emitter as editorEventEmitter } from '../EditorEvent';
6
+ import MentionList from '../MentionList';
7
+ import * as Events from '../utils/events';
8
+ import renderWithTheme from '../../../../testUtils/renderWithTheme';
9
+
10
+ const SuggestionListData: Array<{ id: string; name: string }> = [
11
+ { id: '1', name: 'Kien Tran' },
12
+ { id: '2', name: 'Minh Dinh' },
13
+ { id: '3', name: 'Hieu Pham' },
14
+ { id: '4', name: 'Hau' },
15
+ { id: '5', name: 'Tung Ten' },
16
+ { id: '6', name: 'Thong Quach' },
17
+ ];
18
+
19
+ const SuggestionList = ({
20
+ searchValue,
21
+ onSelect,
22
+ }: {
23
+ searchValue: string;
24
+ onSelect: (id: string, name: string) => void;
25
+ }) => {
26
+ const filteredData = SuggestionListData.filter((item) =>
27
+ item.name.includes(searchValue)
28
+ );
29
+
30
+ return (
31
+ <View>
32
+ {filteredData.map((item) => (
33
+ <Text key={item.id} onPress={() => onSelect(item.id, item.name)}>
34
+ {item.name}
35
+ </Text>
36
+ ))}
37
+ </View>
38
+ );
39
+ };
40
+
41
+ describe('MentionList', () => {
42
+ describe('when search string is empty', () => {
43
+ it('should not render mention list', () => {
44
+ const wrapper = render(
45
+ <MentionList
46
+ name="give-shout-out"
47
+ render={() => <Text>Mention List</Text>}
48
+ />
49
+ );
50
+
51
+ expect(wrapper.toJSON()).toBeNull();
52
+ });
53
+ });
54
+
55
+ describe('when search string is not empty', () => {
56
+ let wrapper: RenderAPI;
57
+
58
+ beforeEach(async () => {
59
+ wrapper = renderWithTheme(
60
+ <MentionList
61
+ name="give-shout-out"
62
+ render={(
63
+ searchValue: string,
64
+ onSelect: (id: string, name: string) => void
65
+ ) => <SuggestionList searchValue={searchValue} onSelect={onSelect} />}
66
+ />
67
+ );
68
+ await act(() => {
69
+ editorEventEmitter.emit('give-shout-out/mention-search', {
70
+ search: 'Hieu',
71
+ target: 'give-shout-out',
72
+ });
73
+ });
74
+ });
75
+
76
+ it('should render mention list showing filtered results', async () => {
77
+ expect(wrapper.toJSON()).toMatchSnapshot();
78
+ expect(wrapper.queryAllByText('Hieu Pham')).toHaveLength(1);
79
+ expect(wrapper.queryAllByText('Kien Tran')).toHaveLength(0);
80
+ expect(wrapper.queryAllByText('Minh Dinh')).toHaveLength(0);
81
+ expect(wrapper.queryAllByText('Hau')).toHaveLength(0);
82
+ expect(wrapper.queryAllByText('Tung Teng')).toHaveLength(0);
83
+ expect(wrapper.queryAllByText('Thong Quach')).toHaveLength(0);
84
+ });
85
+
86
+ describe('onPress suggesstion item', () => {
87
+ it('should emit action metion-only', () => {
88
+ const result: { id: string; name: string; target: string }[] = [];
89
+ act(() => {
90
+ Events.on(
91
+ editorEventEmitter,
92
+ 'give-shout-out/mention-apply',
93
+ (data: { id: string; name: string; target: string }) => {
94
+ result.push(data);
95
+ }
96
+ );
97
+ });
98
+ fireEvent(wrapper.getByText('Hieu Pham'), 'press');
99
+ expect(result).toMatchObject([
100
+ { id: '3', name: 'Hieu Pham', target: 'give-shout-out' },
101
+ ]);
102
+ });
103
+ });
104
+ });
105
+ });
@@ -0,0 +1,136 @@
1
+ import React from 'react';
2
+ import { fireEvent } from '@testing-library/react-native';
3
+ import RichTextEditorInput from '../RichTextEditorInput';
4
+ import { emitter } from '../EditorEvent';
5
+ import * as Events from '../utils/events';
6
+ import renderWithTheme from '../../../../testUtils/renderWithTheme';
7
+
8
+ // Mock minimal EditorValue type for test
9
+ const initialValue = [
10
+ { type: 'paragraph', children: [{ text: 'Hello world' }] },
11
+ ];
12
+
13
+ describe('RichTextEditorInput', () => {
14
+ it('renders a WebView with correct initial html', () => {
15
+ const { getByTestId } = renderWithTheme(
16
+ <RichTextEditorInput
17
+ value={initialValue}
18
+ name="test-editor"
19
+ autoFocus={false}
20
+ placeholder="Type something..."
21
+ onChange={jest.fn()}
22
+ />
23
+ );
24
+
25
+ const webview = getByTestId('webview');
26
+ expect(webview).toBeTruthy();
27
+ expect(webview.props.source.html).toContain(
28
+ 'placeholder: "Type something..."'
29
+ );
30
+ expect(webview.props.source.html).toContain(JSON.stringify(initialValue));
31
+ });
32
+
33
+ it('handles editor-change event from webview', () => {
34
+ const onChange = jest.fn();
35
+ const { getByTestId } = renderWithTheme(
36
+ <RichTextEditorInput
37
+ value={initialValue}
38
+ name="test-editor"
39
+ autoFocus={false}
40
+ placeholder="Type here..."
41
+ onChange={onChange}
42
+ />
43
+ );
44
+
45
+ const webview = getByTestId('webview');
46
+ const newValue = [{ type: 'paragraph', children: [{ text: 'Changed' }] }];
47
+ fireEvent(webview, 'message', {
48
+ nativeEvent: {
49
+ data: JSON.stringify({
50
+ type: '@hero-editor/webview/editor-change',
51
+ data: { value: newValue },
52
+ }),
53
+ },
54
+ });
55
+
56
+ expect(onChange).toHaveBeenCalledWith(newValue);
57
+ });
58
+
59
+ it('handles editor-focus and editor-blur events from webview', () => {
60
+ const onFocus = jest.fn();
61
+ const onBlur = jest.fn();
62
+ const { getByTestId } = renderWithTheme(
63
+ <RichTextEditorInput
64
+ value={initialValue}
65
+ name="test-editor"
66
+ autoFocus={false}
67
+ placeholder="Type here..."
68
+ onChange={jest.fn()}
69
+ onFocus={onFocus}
70
+ onBlur={onBlur}
71
+ />
72
+ );
73
+
74
+ const webview = getByTestId('webview');
75
+
76
+ // Spy on emitter
77
+ const spy = jest.spyOn(Events, 'emit');
78
+
79
+ // Simulate focus
80
+ fireEvent(webview, 'message', {
81
+ nativeEvent: {
82
+ data: JSON.stringify({
83
+ type: '@hero-editor/webview/editor-focus',
84
+ }),
85
+ },
86
+ });
87
+ expect(spy).toHaveBeenCalledWith(
88
+ emitter,
89
+ 'test-editor/editor-focus',
90
+ undefined
91
+ );
92
+
93
+ // Simulate blur
94
+ fireEvent(webview, 'message', {
95
+ nativeEvent: {
96
+ data: JSON.stringify({
97
+ type: '@hero-editor/webview/editor-blur',
98
+ }),
99
+ },
100
+ });
101
+ expect(spy).toHaveBeenCalledWith(
102
+ emitter,
103
+ 'test-editor/editor-blur',
104
+ undefined
105
+ );
106
+
107
+ spy.mockRestore();
108
+ });
109
+
110
+ it('handles cursor-change event from webview', () => {
111
+ const onCursorChange = jest.fn();
112
+ const { getByTestId } = renderWithTheme(
113
+ <RichTextEditorInput
114
+ value={initialValue}
115
+ name="test-editor"
116
+ autoFocus={false}
117
+ placeholder="Type here..."
118
+ onChange={jest.fn()}
119
+ onCursorChange={onCursorChange}
120
+ />
121
+ );
122
+
123
+ const webview = getByTestId('webview');
124
+ const cursorData = { position: { top: 10 } };
125
+ fireEvent(webview, 'message', {
126
+ nativeEvent: {
127
+ data: JSON.stringify({
128
+ type: '@hero-editor/webview/cursor-change',
129
+ data: cursorData,
130
+ }),
131
+ },
132
+ });
133
+
134
+ expect(onCursorChange).toHaveBeenCalledWith(cursorData);
135
+ });
136
+ });
@@ -0,0 +1,414 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`EditorToolbar when the editor is focused should render toolbar 1`] = `
4
+ <View
5
+ style={
6
+ [
7
+ [
8
+ {
9
+ "alignItems": "center",
10
+ "backgroundColor": "#f6f6f7",
11
+ "borderTopColor": "#e8e9ea",
12
+ "borderTopWidth": undefined,
13
+ "flexDirection": "row",
14
+ "paddingHorizontal": 7.846153846153847,
15
+ },
16
+ ],
17
+ undefined,
18
+ ]
19
+ }
20
+ testID="toolbar"
21
+ >
22
+ <TouchableOpacity
23
+ onPress={[Function]}
24
+ selected={false}
25
+ style={
26
+ [
27
+ [
28
+ {
29
+ "alignItems": "center",
30
+ "backgroundColor": undefined,
31
+ "height": 47.07692307692308,
32
+ "justifyContent": "center",
33
+ "width": 47.07692307692308,
34
+ },
35
+ ],
36
+ undefined,
37
+ ]
38
+ }
39
+ testID="format-bold"
40
+ >
41
+ <Text
42
+ allowFontScaling={false}
43
+ selectable={false}
44
+ style={
45
+ [
46
+ {
47
+ "color": undefined,
48
+ "fontSize": 12,
49
+ },
50
+ [
51
+ [
52
+ {
53
+ "color": "#001f23",
54
+ "fontSize": 19.615384615384613,
55
+ },
56
+ ],
57
+ undefined,
58
+ ],
59
+ {
60
+ "fontFamily": "hero-icons-mobile",
61
+ "fontStyle": "normal",
62
+ "fontWeight": "normal",
63
+ },
64
+ {},
65
+ ]
66
+ }
67
+ themeIntent="text"
68
+ themeSize="small"
69
+ >
70
+
71
+ </Text>
72
+ </TouchableOpacity>
73
+ <TouchableOpacity
74
+ onPress={[Function]}
75
+ selected={false}
76
+ style={
77
+ [
78
+ [
79
+ {
80
+ "alignItems": "center",
81
+ "backgroundColor": undefined,
82
+ "height": 47.07692307692308,
83
+ "justifyContent": "center",
84
+ "width": 47.07692307692308,
85
+ },
86
+ ],
87
+ undefined,
88
+ ]
89
+ }
90
+ testID="format-italic"
91
+ >
92
+ <Text
93
+ allowFontScaling={false}
94
+ selectable={false}
95
+ style={
96
+ [
97
+ {
98
+ "color": undefined,
99
+ "fontSize": 12,
100
+ },
101
+ [
102
+ [
103
+ {
104
+ "color": "#001f23",
105
+ "fontSize": 19.615384615384613,
106
+ },
107
+ ],
108
+ undefined,
109
+ ],
110
+ {
111
+ "fontFamily": "hero-icons-mobile",
112
+ "fontStyle": "normal",
113
+ "fontWeight": "normal",
114
+ },
115
+ {},
116
+ ]
117
+ }
118
+ themeIntent="text"
119
+ themeSize="small"
120
+ >
121
+
122
+ </Text>
123
+ </TouchableOpacity>
124
+ <TouchableOpacity
125
+ onPress={[Function]}
126
+ selected={false}
127
+ style={
128
+ [
129
+ [
130
+ {
131
+ "alignItems": "center",
132
+ "backgroundColor": undefined,
133
+ "height": 47.07692307692308,
134
+ "justifyContent": "center",
135
+ "width": 47.07692307692308,
136
+ },
137
+ ],
138
+ undefined,
139
+ ]
140
+ }
141
+ testID="format-underlined"
142
+ >
143
+ <Text
144
+ allowFontScaling={false}
145
+ selectable={false}
146
+ style={
147
+ [
148
+ {
149
+ "color": undefined,
150
+ "fontSize": 12,
151
+ },
152
+ [
153
+ [
154
+ {
155
+ "color": "#001f23",
156
+ "fontSize": 19.615384615384613,
157
+ },
158
+ ],
159
+ undefined,
160
+ ],
161
+ {
162
+ "fontFamily": "hero-icons-mobile",
163
+ "fontStyle": "normal",
164
+ "fontWeight": "normal",
165
+ },
166
+ {},
167
+ ]
168
+ }
169
+ themeIntent="text"
170
+ themeSize="small"
171
+ >
172
+
173
+ </Text>
174
+ </TouchableOpacity>
175
+ <View
176
+ style={
177
+ [
178
+ [
179
+ {
180
+ "alignItems": "center",
181
+ "backgroundColor": "#e8e9ea",
182
+ "flexDirection": "row",
183
+ "height": 15.692307692307693,
184
+ "marginHorizontal": 7.846153846153847,
185
+ "width": 1.9615384615384617,
186
+ },
187
+ ],
188
+ undefined,
189
+ ]
190
+ }
191
+ />
192
+ <TouchableOpacity
193
+ onPress={[Function]}
194
+ selected={false}
195
+ style={
196
+ [
197
+ [
198
+ {
199
+ "alignItems": "center",
200
+ "backgroundColor": undefined,
201
+ "height": 47.07692307692308,
202
+ "justifyContent": "center",
203
+ "width": 47.07692307692308,
204
+ },
205
+ ],
206
+ undefined,
207
+ ]
208
+ }
209
+ testID="format-list-bulleted"
210
+ >
211
+ <Text
212
+ allowFontScaling={false}
213
+ selectable={false}
214
+ style={
215
+ [
216
+ {
217
+ "color": undefined,
218
+ "fontSize": 12,
219
+ },
220
+ [
221
+ [
222
+ {
223
+ "color": "#001f23",
224
+ "fontSize": 19.615384615384613,
225
+ },
226
+ ],
227
+ undefined,
228
+ ],
229
+ {
230
+ "fontFamily": "hero-icons-mobile",
231
+ "fontStyle": "normal",
232
+ "fontWeight": "normal",
233
+ },
234
+ {},
235
+ ]
236
+ }
237
+ themeIntent="text"
238
+ themeSize="small"
239
+ >
240
+
241
+ </Text>
242
+ </TouchableOpacity>
243
+ <TouchableOpacity
244
+ onPress={[Function]}
245
+ selected={false}
246
+ style={
247
+ [
248
+ [
249
+ {
250
+ "alignItems": "center",
251
+ "backgroundColor": undefined,
252
+ "height": 47.07692307692308,
253
+ "justifyContent": "center",
254
+ "width": 47.07692307692308,
255
+ },
256
+ ],
257
+ undefined,
258
+ ]
259
+ }
260
+ testID="format-list-numbered"
261
+ >
262
+ <Text
263
+ allowFontScaling={false}
264
+ selectable={false}
265
+ style={
266
+ [
267
+ {
268
+ "color": undefined,
269
+ "fontSize": 12,
270
+ },
271
+ [
272
+ [
273
+ {
274
+ "color": "#001f23",
275
+ "fontSize": 19.615384615384613,
276
+ },
277
+ ],
278
+ undefined,
279
+ ],
280
+ {
281
+ "fontFamily": "hero-icons-mobile",
282
+ "fontStyle": "normal",
283
+ "fontWeight": "normal",
284
+ },
285
+ {},
286
+ ]
287
+ }
288
+ themeIntent="text"
289
+ themeSize="small"
290
+ >
291
+
292
+ </Text>
293
+ </TouchableOpacity>
294
+ <View
295
+ style={
296
+ [
297
+ [
298
+ {
299
+ "alignItems": "center",
300
+ "backgroundColor": "#e8e9ea",
301
+ "flexDirection": "row",
302
+ "height": 15.692307692307693,
303
+ "marginHorizontal": 7.846153846153847,
304
+ "width": 1.9615384615384617,
305
+ },
306
+ ],
307
+ undefined,
308
+ ]
309
+ }
310
+ />
311
+ <TouchableOpacity
312
+ onPress={[Function]}
313
+ selected={false}
314
+ style={
315
+ [
316
+ [
317
+ {
318
+ "alignItems": "center",
319
+ "backgroundColor": undefined,
320
+ "height": 47.07692307692308,
321
+ "justifyContent": "center",
322
+ "width": 47.07692307692308,
323
+ },
324
+ ],
325
+ undefined,
326
+ ]
327
+ }
328
+ testID="format-heading1"
329
+ >
330
+ <Text
331
+ allowFontScaling={false}
332
+ selectable={false}
333
+ style={
334
+ [
335
+ {
336
+ "color": undefined,
337
+ "fontSize": 12,
338
+ },
339
+ [
340
+ [
341
+ {
342
+ "color": "#001f23",
343
+ "fontSize": 19.615384615384613,
344
+ },
345
+ ],
346
+ undefined,
347
+ ],
348
+ {
349
+ "fontFamily": "hero-icons-mobile",
350
+ "fontStyle": "normal",
351
+ "fontWeight": "normal",
352
+ },
353
+ {},
354
+ ]
355
+ }
356
+ themeIntent="text"
357
+ themeSize="small"
358
+ >
359
+
360
+ </Text>
361
+ </TouchableOpacity>
362
+ <TouchableOpacity
363
+ onPress={[Function]}
364
+ selected={false}
365
+ style={
366
+ [
367
+ [
368
+ {
369
+ "alignItems": "center",
370
+ "backgroundColor": undefined,
371
+ "height": 47.07692307692308,
372
+ "justifyContent": "center",
373
+ "width": 47.07692307692308,
374
+ },
375
+ ],
376
+ undefined,
377
+ ]
378
+ }
379
+ testID="format-heading2"
380
+ >
381
+ <Text
382
+ allowFontScaling={false}
383
+ selectable={false}
384
+ style={
385
+ [
386
+ {
387
+ "color": undefined,
388
+ "fontSize": 12,
389
+ },
390
+ [
391
+ [
392
+ {
393
+ "color": "#001f23",
394
+ "fontSize": 19.615384615384613,
395
+ },
396
+ ],
397
+ undefined,
398
+ ],
399
+ {
400
+ "fontFamily": "hero-icons-mobile",
401
+ "fontStyle": "normal",
402
+ "fontWeight": "normal",
403
+ },
404
+ {},
405
+ ]
406
+ }
407
+ themeIntent="text"
408
+ themeSize="small"
409
+ >
410
+
411
+ </Text>
412
+ </TouchableOpacity>
413
+ </View>
414
+ `;
@@ -0,0 +1,13 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`MentionList when search string is not empty should render mention list showing filtered results 1`] = `
4
+ <View>
5
+ <View>
6
+ <Text
7
+ onPress={[Function]}
8
+ >
9
+ Hieu Pham
10
+ </Text>
11
+ </View>
12
+ </View>
13
+ `;
@@ -0,0 +1,9 @@
1
+ export enum ToolbarEvents {
2
+ Bold = 'bold',
3
+ Italic = 'italic',
4
+ Underline = 'underline',
5
+ BulletedList = 'bulleted-list',
6
+ NumberedList = 'numbered-list',
7
+ HeadingOne = 'heading-one',
8
+ HeadingTwo = 'heading-two',
9
+ }
@@ -5,4 +5,10 @@ declare module 'hero-editor/dist/app.js' {
5
5
 
6
6
  declare module 'hero-editor' {
7
7
  export function isEmptyContent(content: unknown): boolean;
8
+ export function plainSerializer(
9
+ content: {
10
+ type: string;
11
+ children: unknown;
12
+ }[]
13
+ ): string;
8
14
  }
@@ -0,0 +1,3 @@
1
+ import * as heroEditorApp from 'hero-editor/dist/app.js';
2
+
3
+ export default heroEditorApp;
@@ -0,0 +1,20 @@
1
+ import React, { forwardRef } from 'react';
2
+ import RichTextEditor, {
3
+ RichTextEditorProps,
4
+ RichTextEditorRef,
5
+ } from './RichTextEditor';
6
+ import MentionList from './MentionList';
7
+
8
+ import Toolbar from './EditorToolbar';
9
+
10
+ const RichTextEditorWithRef = forwardRef<
11
+ RichTextEditorRef,
12
+ Omit<RichTextEditorProps, 'forwardedRef'>
13
+ >((props, ref) => <RichTextEditor {...props} forwardedRef={ref} />);
14
+
15
+ RichTextEditorWithRef.displayName = 'RichTextEditor';
16
+
17
+ export default Object.assign(RichTextEditorWithRef, {
18
+ MentionList,
19
+ Toolbar,
20
+ });