Skip to content

Commit e71f666

Browse files
authored
refactor: Allow use of custom Textarea component in StatusUpdateForm (#342)
1 parent 714300e commit e71f666

2 files changed

Lines changed: 36 additions & 17 deletions

File tree

src/components/StatusUpdateForm/StatusUpdateForm.test.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import React from 'react';
2+
import '@testing-library/jest-dom';
23
import { render } from '@testing-library/react';
34
import { StatusUpdateForm } from './StatusUpdateForm';
45
import { I18n } from 'emoji-mart';
56
import { EmojiPicker } from '../EmojiPicker';
67

8+
const customTextareaPlaceholder = 'Custom placeholder';
9+
const Textarea = jest.fn(() => <textarea placeholder={customTextareaPlaceholder} />);
10+
711
jest.mock('../EmojiPicker', () => {
812
return {
913
...jest.requireActual('../EmojiPicker'),
@@ -12,6 +16,8 @@ jest.mock('../EmojiPicker', () => {
1216
});
1317

1418
describe('StatusUpdateForm', () => {
19+
beforeEach(jest.clearAllMocks);
20+
1521
it('passes i18n prop to EmojiPicker', () => {
1622
const emojiI18n: Partial<I18n> = {
1723
search: 'Custom Search String',
@@ -22,4 +28,14 @@ describe('StatusUpdateForm', () => {
2228
render(<StatusUpdateForm emojiI18n={emojiI18n} />);
2329
expect(EmojiPicker).toHaveBeenCalledWith(expect.objectContaining({ i18n: emojiI18n }), {});
2430
});
31+
32+
it('renders default Textarea', () => {
33+
const { getByRole } = render(<StatusUpdateForm />);
34+
expect(getByRole('textbox')).toHaveProperty('placeholder', 'Type your post...');
35+
});
36+
37+
it('renders custom Textarea', () => {
38+
const { getByRole } = render(<StatusUpdateForm Textarea={Textarea} />);
39+
expect(getByRole('textbox')).toHaveProperty('placeholder', customTextareaPlaceholder);
40+
});
2541
});

src/components/StatusUpdateForm/StatusUpdateForm.tsx

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import React, { ReactNode } from 'react';
22
import { Activity, NewActivity, UR } from 'getstream';
33
import {
4-
ImageUploadButton,
5-
FileUploadButton,
6-
ImagePreviewer,
74
FilePreviewer,
8-
ImageDropzone,
9-
LoadingIndicator,
105
FileUpload,
6+
FileUploadButton,
7+
ImageDropzone,
8+
ImagePreviewer,
119
ImageUpload,
10+
ImageUploadButton,
11+
LoadingIndicator,
1212
} from 'react-file-utils';
1313

1414
import { DefaultAT, DefaultUT, useTranslationContext } from '../../context';
15-
import { PropsWithElementAttributes } from '../../utils';
15+
import { ElementOrComponentOrLiteralType, PropsWithElementAttributes, smartRender } from '../../utils';
1616
import { useStatusUpdateForm } from './useStatusUpdateForm';
17-
import { Panel, PanelContent, PanelHeading, PanelFooter } from '../Panel';
18-
import { Textarea, TextareaProps } from '../Textarea';
17+
import { Panel, PanelContent, PanelFooter, PanelHeading } from '../Panel';
18+
import { Textarea as DefaultTextarea, TextareaProps } from '../Textarea';
1919
import { Avatar } from '../Avatar';
2020
import { Card } from '../Card';
2121
import { Audio } from '../Audio';
@@ -58,6 +58,8 @@ export type StatusUpdateFormProps<AT extends DefaultAT = DefaultAT> = PropsWithE
5858
modifyActivityData?: (activity: NewActivity<AT>) => NewActivity<AT>;
5959
/** A callback to run after the activity is posted successfully */
6060
onSuccess?: (activity: Activity<AT>) => void;
61+
/** Custom Textarea component implementation */
62+
Textarea?: ElementOrComponentOrLiteralType<Omit<TextareaProps, 'maxLength' | 'rows'>>;
6163
/** An extra trigger for ReactTextareaAutocomplete, this can be used to show
6264
* a menu when typing @xxx or #xxx, in addition to the emoji menu when typing
6365
* :xxx */
@@ -81,6 +83,7 @@ export function StatusUpdateForm<
8183
emojiI18n,
8284
Header,
8385
FooterItem,
86+
Textarea = DefaultTextarea,
8487
trigger,
8588
doRequest,
8689
userId,
@@ -112,15 +115,15 @@ export function StatusUpdateForm<
112115
</div>
113116
)}
114117

115-
<Textarea
116-
innerRef={state.textInputRef}
117-
placeholder={t('Type your post...')}
118-
value={state.text}
119-
onChange={state.onChange}
120-
emojiData={emojiData}
121-
trigger={trigger}
122-
onPaste={state.onPaste}
123-
/>
118+
{smartRender(Textarea, {
119+
emojiData,
120+
innerRef: state.textInputRef,
121+
onChange: state.onChange,
122+
onPaste: state.onPaste,
123+
placeholder: t('Type your post...'),
124+
trigger,
125+
value: state.text,
126+
})}
124127
</div>
125128

126129
{state.isOgScraping && (

0 commit comments

Comments
 (0)